2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1994-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* nmbd.c sets this to True. */
26 BOOL global_in_nmbd = False;
28 /****************************************************************************
29 generate a random trn_id
30 ****************************************************************************/
31 static int generate_trn_id(void)
36 sys_srandom(sys_getpid());
39 trn_id = sys_random();
41 return trn_id % (unsigned)0x7FFF;
45 /****************************************************************************
46 parse a node status response into an array of structures
47 ****************************************************************************/
48 static struct node_status *parse_node_status(char *p, int *num_names)
50 struct node_status *ret;
53 *num_names = CVAL(p,0);
55 if (*num_names == 0) return NULL;
57 ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
58 if (!ret) return NULL;
61 for (i=0;i< *num_names;i++) {
62 StrnCpy(ret[i].name,p,15);
63 trim_string(ret[i].name,NULL," ");
64 ret[i].type = CVAL(p,15);
72 /****************************************************************************
73 do a NBT node status query on an open socket and return an array of
74 structures holding the returned names or NULL if the query failed
75 **************************************************************************/
76 struct node_status *node_status_query(int fd,struct nmb_name *name,
77 struct in_addr to_ip, int *num_names)
81 int retry_time = 2000;
83 struct packet_struct p;
84 struct packet_struct *p2;
85 struct nmb_packet *nmb = &p.packet.nmb;
86 struct node_status *ret;
90 nmb->header.name_trn_id = generate_trn_id();
91 nmb->header.opcode = 0;
92 nmb->header.response = False;
93 nmb->header.nm_flags.bcast = False;
94 nmb->header.nm_flags.recursion_available = False;
95 nmb->header.nm_flags.recursion_desired = False;
96 nmb->header.nm_flags.trunc = False;
97 nmb->header.nm_flags.authoritative = False;
98 nmb->header.rcode = 0;
99 nmb->header.qdcount = 1;
100 nmb->header.ancount = 0;
101 nmb->header.nscount = 0;
102 nmb->header.arcount = 0;
103 nmb->question.question_name = *name;
104 nmb->question.question_type = 0x21;
105 nmb->question.question_class = 0x1;
110 p.timestamp = time(NULL);
111 p.packet_type = NMB_PACKET;
115 if (!send_packet(&p))
121 struct timeval tval2;
122 GetTimeOfDay(&tval2);
123 if (TvalDiff(&tval,&tval2) > retry_time) {
126 if (!found && !send_packet(&p))
132 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
133 struct nmb_packet *nmb2 = &p2->packet.nmb;
134 debug_nmb_packet(p2);
136 if (nmb2->header.opcode != 0 ||
137 nmb2->header.nm_flags.bcast ||
138 nmb2->header.rcode ||
139 !nmb2->header.ancount ||
140 nmb2->answers->rr_type != 0x21) {
141 /* XXXX what do we do with this? could be a
142 redirect, but we'll discard it for the
148 ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
158 /****************************************************************************
159 find the first type XX name in a node status reply - used for finding
160 a servers name given its IP
161 return the matched name in *name
162 **************************************************************************/
163 BOOL name_status_find(int type, struct in_addr to_ip, char *name)
165 struct node_status *status;
166 struct nmb_name nname;
170 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
171 if (sock == -1) return False;
173 make_nmb_name(&nname, "*", 0);
174 status = node_status_query(sock, &nname, to_ip, &count);
176 if (!status) return False;
178 for (i=0;i<count;i++) {
179 if (status[i].type == type) break;
181 if (i == count) return False;
183 pull_ascii(name, status[i].name, 15, 0, STR_TERMINATE);
189 /****************************************************************************
190 Do a NetBIOS name registation to try to claim a name ...
191 ***************************************************************************/
192 BOOL name_register(int fd, const char *name, int name_type,
193 struct in_addr name_ip, int opcode,
195 struct in_addr to_ip, int *count)
199 struct packet_struct p;
200 struct packet_struct *p2;
201 struct nmb_packet *nmb = &p.packet.nmb;
202 struct in_addr register_ip;
204 DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
206 register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
208 bzero((char *)&p, sizeof(p));
212 nmb->header.name_trn_id = generate_trn_id();
213 nmb->header.opcode = opcode;
214 nmb->header.response = False;
215 nmb->header.nm_flags.bcast = False;
216 nmb->header.nm_flags.recursion_available = False;
217 nmb->header.nm_flags.recursion_desired = True; /* ? */
218 nmb->header.nm_flags.trunc = False;
219 nmb->header.nm_flags.authoritative = True;
221 nmb->header.qdcount = 1;
222 nmb->header.ancount = 0;
223 nmb->header.nscount = 0;
224 nmb->header.arcount = 1;
226 make_nmb_name(&nmb->question.question_name, name, name_type);
228 nmb->question.question_type = 0x20;
229 nmb->question.question_class = 0x1;
231 /* Now, create the additional stuff for a registration request */
233 if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
235 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
240 bzero((char *)nmb->additional, sizeof(struct res_rec));
242 nmb->additional->rr_name = nmb->question.question_name;
243 nmb->additional->rr_type = RR_TYPE_NB;
244 nmb->additional->rr_class = RR_CLASS_IN;
246 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
247 if (nmb->header.nm_flags.bcast)
248 nmb->additional->ttl = PERMANENT_TTL;
250 nmb->additional->ttl = lp_max_ttl();
252 nmb->additional->rdlength = 6;
254 nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
256 /* Set the address for the name we are registering. */
257 putip(&nmb->additional->rdata[2], ®ister_ip);
262 p.timestamp = time(NULL);
263 p.packet_type = NMB_PACKET;
267 if (!send_packet(&p))
272 if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
273 debug_nmb_packet(p2);
274 SAFE_FREE(p2); /* No memory leaks ... */
280 /****************************************************************************
281 Do a netbios name query to find someones IP.
282 Returns an array of IP addresses or NULL if none.
283 *count will be set to the number of addresses returned.
284 ****************************************************************************/
285 struct in_addr *name_query(int fd,const char *name,int name_type,
286 BOOL bcast,BOOL recurse,
287 struct in_addr to_ip, int *count)
291 int retry_time = bcast?250:2000;
293 struct packet_struct p;
294 struct packet_struct *p2;
295 struct nmb_packet *nmb = &p.packet.nmb;
296 struct in_addr *ip_list = NULL;
298 memset((char *)&p,'\0',sizeof(p));
301 nmb->header.name_trn_id = generate_trn_id();
302 nmb->header.opcode = 0;
303 nmb->header.response = False;
304 nmb->header.nm_flags.bcast = bcast;
305 nmb->header.nm_flags.recursion_available = False;
306 nmb->header.nm_flags.recursion_desired = recurse;
307 nmb->header.nm_flags.trunc = False;
308 nmb->header.nm_flags.authoritative = False;
309 nmb->header.rcode = 0;
310 nmb->header.qdcount = 1;
311 nmb->header.ancount = 0;
312 nmb->header.nscount = 0;
313 nmb->header.arcount = 0;
315 make_nmb_name(&nmb->question.question_name,name,name_type);
317 nmb->question.question_type = 0x20;
318 nmb->question.question_class = 0x1;
323 p.timestamp = time(NULL);
324 p.packet_type = NMB_PACKET;
328 if (!send_packet(&p))
335 struct timeval tval2;
336 struct in_addr *tmp_ip_list;
338 GetTimeOfDay(&tval2);
339 if (TvalDiff(&tval,&tval2) > retry_time) {
342 if (!found && !send_packet(&p))
348 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
349 struct nmb_packet *nmb2 = &p2->packet.nmb;
350 debug_nmb_packet(p2);
352 /* If we get a Negative Name Query Response from a WINS
353 * server, we should report it and give up.
355 if( 0 == nmb2->header.opcode /* A query response */
356 && !(bcast) /* from a WINS server */
357 && nmb2->header.rcode /* Error returned */
360 if( DEBUGLVL( 3 ) ) {
361 /* Only executed if DEBUGLEVEL >= 3 */
362 dbgtext( "Negative name query response, rcode 0x%02x: ",
363 nmb2->header.rcode );
364 switch( nmb2->header.rcode ) {
366 dbgtext( "Request was invalidly formatted.\n" );
369 dbgtext( "Problem with NBNS, cannot process name.\n");
372 dbgtext( "The name requested does not exist.\n" );
375 dbgtext( "Unsupported request error.\n" );
378 dbgtext( "Query refused error.\n" );
381 dbgtext( "Unrecognized error code.\n" );
389 if (nmb2->header.opcode != 0 ||
390 nmb2->header.nm_flags.bcast ||
391 nmb2->header.rcode ||
392 !nmb2->header.ancount) {
394 * XXXX what do we do with this? Could be a
395 * redirect, but we'll discard it for the
401 tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
402 * ( (*count) + nmb2->answers->rdlength/6 ) );
405 DEBUG(0,("name_query: Realloc failed.\n"));
409 ip_list = tmp_ip_list;
412 DEBUG(2,("Got a positive name query response from %s ( ",
414 for (i=0;i<nmb2->answers->rdlength/6;i++) {
415 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
416 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
426 * If we're doing a unicast lookup we only
427 * expect one reply. Don't wait the full 2
428 * seconds if we got one. JRA.
435 /* Reach here if we've timed out waiting for replies.. */
436 if( !bcast && !found )
438 /* Timed out wating for WINS server to respond. Mark it dead. */
439 wins_srv_died( to_ip );
445 /********************************************************
446 Start parsing the lmhosts file.
447 *********************************************************/
449 XFILE *startlmhosts(char *fname)
451 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
453 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
454 fname, strerror(errno)));
460 /********************************************************
461 Parse the next line in the lmhosts file.
462 *********************************************************/
464 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
468 while(!x_feof(fp) && !x_ferror(fp)) {
469 pstring ip,flags,extra;
475 if (!fgets_slash(line,sizeof(pstring),fp))
487 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
489 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
491 if (next_token(&ptr,flags,NULL, sizeof(flags)))
493 if (next_token(&ptr,extra,NULL, sizeof(extra)))
499 if (count > 0 && count < 2)
501 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
507 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
511 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
513 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
515 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
519 *ipaddr = *interpret_addr2(ip);
521 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
522 then only add that name type. */
523 if((ptr = strchr_m(name, '#')) != NULL)
528 *name_type = (int)strtol(ptr, &endptr, 16);
530 if(!*ptr || (endptr == ptr))
532 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
536 *(--ptr) = '\0'; /* Truncate at the '#' */
545 /********************************************************
546 Finish parsing the lmhosts file.
547 *********************************************************/
549 void endlmhosts(XFILE *fp)
554 BOOL name_register_wins(const char *name, int name_type)
556 int sock, i, return_count;
557 int num_interfaces = iface_count();
558 struct in_addr sendto_ip;
561 * Check if we have any interfaces, prevents a segfault later
564 if (num_interfaces <= 0)
565 return False; /* Should return some indication of the problem */
568 * Do a broadcast register ...
571 if (0 == wins_srv_count())
576 dbgtext( "name_register_wins: Registering my name %s ", name );
577 dbgtext( "with WINS server %s.\n", wins_srv_name() );
580 sock = open_socket_in( SOCK_DGRAM, 0, 3,
581 interpret_addr("0.0.0.0"), True );
583 if (sock == -1) return False;
585 set_socket_options(sock, "SO_BROADCAST"); /* ????! crh */
587 sendto_ip = wins_srv_ip();
589 if (num_interfaces > 1) {
591 for (i = 0; i < num_interfaces; i++) {
593 if (!name_register(sock, name, name_type, *iface_n_ip(i),
594 NMB_NAME_MULTIHOMED_REG_OPCODE,
595 True, sendto_ip, &return_count)) {
607 if (!name_register(sock, name, name_type, *iface_n_ip(0),
609 True, sendto_ip, &return_count)) {
624 /********************************************************
625 Resolve via "bcast" method.
626 *********************************************************/
628 BOOL name_resolve_bcast(const char *name, int name_type,
629 struct in_addr **return_ip_list, int *return_count)
632 int num_interfaces = iface_count();
634 *return_ip_list = NULL;
638 * "bcast" means do a broadcast lookup on all the local interfaces.
641 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
643 sock = open_socket_in( SOCK_DGRAM, 0, 3,
644 interpret_addr(lp_socket_address()), True );
646 if (sock == -1) return False;
648 set_socket_options(sock,"SO_BROADCAST");
650 * Lookup the name on all the interfaces, return on
651 * the first successful match.
653 for( i = num_interfaces-1; i >= 0; i--) {
654 struct in_addr sendto_ip;
655 /* Done this way to fix compiler error on IRIX 5.x */
656 sendto_ip = *iface_bcast(*iface_n_ip(i));
657 *return_ip_list = name_query(sock, name, name_type, True,
658 True, sendto_ip, return_count);
659 if(*return_ip_list != NULL) {
669 /********************************************************
670 Resolve via "wins" method.
671 *********************************************************/
673 static BOOL resolve_wins(const char *name, int name_type,
674 struct in_addr **return_iplist, int *return_count)
677 struct in_addr wins_ip;
680 *return_iplist = NULL;
684 * "wins" means do a unicast lookup to the WINS server.
685 * Ignore if there is no WINS server specified or if the
686 * WINS server is one of our interfaces (if we're being
687 * called from within nmbd - we can't do this call as we
691 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
693 if (lp_wins_support()) {
695 * We're providing WINS support. Call ourselves so
696 * long as we're not nmbd.
698 extern struct in_addr loopback_ip;
699 wins_ip = loopback_ip;
701 } else if( wins_srv_count() < 1 ) {
702 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
705 wins_ip = wins_srv_ip();
706 wins_ismyip = ismyip(wins_ip);
709 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
710 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
711 sock = open_socket_in( SOCK_DGRAM, 0, 3,
712 interpret_addr(lp_socket_address()),
715 *return_iplist = name_query( sock, name,
719 if(*return_iplist != NULL) {
730 /********************************************************
731 Resolve via "lmhosts" method.
732 *********************************************************/
734 static BOOL resolve_lmhosts(const char *name, int name_type,
735 struct in_addr **return_iplist, int *return_count)
738 * "lmhosts" means parse the local lmhosts file.
744 struct in_addr return_ip;
746 *return_iplist = NULL;
749 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
751 fp = startlmhosts( LMHOSTSFILE );
753 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
754 if (strequal(name, lmhost_name) &&
755 ((name_type2 == -1) || (name_type == name_type2))
758 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
759 if(*return_iplist == NULL) {
760 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
763 **return_iplist = return_ip;
774 /********************************************************
775 Resolve via "hosts" method.
776 *********************************************************/
778 static BOOL resolve_hosts(const char *name,
779 struct in_addr **return_iplist, int *return_count)
782 * "host" means do a localhost, or dns lookup.
786 *return_iplist = NULL;
789 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
791 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
792 struct in_addr return_ip;
793 putip((char *)&return_ip,(char *)hp->h_addr);
794 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
795 if(*return_iplist == NULL) {
796 DEBUG(3,("resolve_hosts: malloc fail !\n"));
799 **return_iplist = return_ip;
806 /********************************************************
807 Internal interface to resolve a name into an IP address.
808 Use this function if the string is either an IP address, DNS
809 or host name or NetBIOS name. This uses the name switch in the
810 smb.conf to determine the order of name resolution.
811 *********************************************************/
813 static BOOL internal_resolve_name(const char *name, int name_type,
814 struct in_addr **return_iplist, int *return_count)
816 pstring name_resolve_list;
819 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
820 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
821 BOOL is_address = is_ipaddress(name);
822 *return_iplist = NULL;
825 if (allzeros || allones || is_address) {
826 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
827 if(*return_iplist == NULL) {
828 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
832 /* if it's in the form of an IP address then get the lib to interpret it */
833 (*return_iplist)->s_addr = inet_addr(name);
835 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
841 pstrcpy(name_resolve_list, lp_name_resolve_order());
842 ptr = name_resolve_list;
846 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
847 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
848 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
851 } else if(strequal( tok, "lmhosts")) {
852 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
855 } else if(strequal( tok, "wins")) {
856 /* don't resolve 1D via WINS */
857 if (name_type != 0x1D &&
858 resolve_wins(name, name_type, return_iplist, return_count)) {
861 } else if(strequal( tok, "bcast")) {
862 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
866 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
870 SAFE_FREE(*return_iplist);
874 /********************************************************
875 Internal interface to resolve a name into one IP address.
876 Use this function if the string is either an IP address, DNS
877 or host name or NetBIOS name. This uses the name switch in the
878 smb.conf to determine the order of name resolution.
879 *********************************************************/
881 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
883 struct in_addr *ip_list = NULL;
886 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
887 *return_ip = ip_list[0];
896 /********************************************************
897 resolve a name of format \\server_name or \\ipaddress
898 into a name. also, cut the \\ from the front for us.
899 *********************************************************/
901 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
905 const char *sv_name = srv_name;
907 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
909 if (srv_name == NULL || strequal("\\\\.", srv_name))
911 extern pstring global_myname;
912 fstrcpy(dest_host, global_myname);
913 ip = interpret_addr2("127.0.0.1");
917 if (strnequal("\\\\", srv_name, 2))
919 sv_name = &srv_name[2];
922 fstrcpy(dest_host, sv_name);
923 /* treat the '*' name specially - it is a magic name for the PDC */
924 if (strcmp(dest_host,"*") == 0) {
925 extern pstring global_myname;
926 ret = resolve_name(lp_workgroup(), ip, 0x1B);
927 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
929 ret = resolve_name(dest_host, ip, 0x20);
932 if (is_ipaddress(dest_host))
934 fstrcpy(dest_host, "*SMBSERVER");
941 /********************************************************
942 Find the IP address of the master browser or DMB for a workgroup.
943 *********************************************************/
945 BOOL find_master_ip(char *group, struct in_addr *master_ip)
947 struct in_addr *ip_list = NULL;
950 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
951 *master_ip = ip_list[0];
955 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
956 *master_ip = ip_list[0];
965 /********************************************************
966 Lookup a PDC name given a Domain name and IP address.
967 *********************************************************/
969 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
971 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
977 * Due to the fact win WinNT *sucks* we must do a node status
983 ret = name_status_find(0x20,*pdc_ip,pdc_name);
985 if(ret && *pdc_name) {
986 fstrcpy(ret_name, pdc_name);
992 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
994 JRA - This code is broken with BDC rollover - we need to do a full
995 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
998 int retry_time = 2000;
1000 struct packet_struct p;
1001 struct dgram_packet *dgram = &p.packet.dgram;
1005 struct sockaddr_in sock_name;
1006 int sock_len = sizeof(sock_name);
1007 const char *mailslot = NET_LOGON_MAILSLOT;
1008 char *mailslot_name;
1011 int dgm_id = generate_trn_id();
1012 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1017 /* Find out the transient UDP port we have been allocated. */
1018 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1019 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1026 * Create the request data.
1029 memset(buffer,'\0',sizeof(buffer));
1031 SSVAL(bufp,0,QUERYFORPDC);
1033 fstrcpy(bufp,srcname);
1034 bufp += (strlen(bufp) + 1);
1035 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1036 mailslot_name = bufp;
1037 bufp += (strlen(bufp) + 1);
1038 bufp = ALIGN2(bufp, buffer);
1039 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1042 SSVAL(bufp,4,0xFFFF);
1043 SSVAL(bufp,6,0xFFFF);
1045 len = PTR_DIFF(bufp,buffer);
1047 memset((char *)&p,'\0',sizeof(p));
1049 /* DIRECT GROUP or UNIQUE datagram. */
1050 dgram->header.msg_type = 0x10;
1051 dgram->header.flags.node_type = M_NODE;
1052 dgram->header.flags.first = True;
1053 dgram->header.flags.more = False;
1054 dgram->header.dgm_id = dgm_id;
1055 dgram->header.source_ip = *iface_ip(*pdc_ip);
1056 dgram->header.source_port = ntohs(sock_name.sin_port);
1057 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1058 dgram->header.packet_offset = 0;
1060 make_nmb_name(&dgram->source_name,srcname,0);
1061 make_nmb_name(&dgram->dest_name,domain,0x1C);
1063 ptr = &dgram->data[0];
1065 /* Setup the smb part. */
1066 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1068 set_message(ptr,17,17 + len,True);
1071 CVAL(ptr,smb_com) = SMBtrans;
1072 SSVAL(ptr,smb_vwv1,len);
1073 SSVAL(ptr,smb_vwv11,len);
1074 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1075 SSVAL(ptr,smb_vwv13,3);
1076 SSVAL(ptr,smb_vwv14,1);
1077 SSVAL(ptr,smb_vwv15,1);
1078 SSVAL(ptr,smb_vwv16,2);
1080 pstrcpy(p2,mailslot);
1081 p2 = skip_string(p2,1);
1083 memcpy(p2,buffer,len);
1086 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1089 p.port = DGRAM_PORT;
1091 p.timestamp = time(NULL);
1092 p.packet_type = DGRAM_PACKET;
1094 GetTimeOfDay(&tval);
1096 if (!send_packet(&p)) {
1097 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1105 struct timeval tval2;
1106 struct packet_struct *p_ret;
1108 GetTimeOfDay(&tval2);
1109 if (TvalDiff(&tval,&tval2) > retry_time) {
1112 if (!send_packet(&p)) {
1113 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1117 GetTimeOfDay(&tval);
1121 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1122 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1126 buf = &dgram2->data[0];
1129 if (CVAL(buf,smb_com) != SMBtrans) {
1130 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1131 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1136 len = SVAL(buf,smb_vwv11);
1137 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1140 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1145 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1146 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1147 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1149 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1150 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1151 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1157 /* Note this is safe as it is a bounded strcpy. */
1158 fstrcpy(ret_name, buf2);
1159 ret_name[sizeof(fstring)-1] = '\0';
1168 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1172 /********************************************************
1173 Get the IP address list of the PDC/BDC's of a Domain.
1174 *********************************************************/
1175 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1177 return internal_resolve_name(group, pdc_only ? 0x1B : 0x1C, ip_list, count);