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 extern int DEBUGLEVEL;
27 /* nmbd.c sets this to True. */
28 BOOL global_in_nmbd = False;
30 /****************************************************************************
31 generate a random trn_id
32 ****************************************************************************/
33 static int generate_trn_id(void)
38 sys_srandom(sys_getpid());
41 trn_id = sys_random();
43 return trn_id % (unsigned)0x7FFF;
47 /****************************************************************************
48 parse a node status response into an array of structures
49 ****************************************************************************/
50 static struct node_status *parse_node_status(char *p, int *num_names)
52 struct node_status *ret;
55 *num_names = CVAL(p,0);
57 if (*num_names == 0) return NULL;
59 ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names));
60 if (!ret) return NULL;
63 for (i=0;i< *num_names;i++) {
64 StrnCpy(ret[i].name,p,15);
65 trim_string(ret[i].name,NULL," ");
66 ret[i].type = CVAL(p,15);
74 /****************************************************************************
75 do a NBT node status query on an open socket and return an array of
76 structures holding the returned names or NULL if the query failed
77 **************************************************************************/
78 struct node_status *node_status_query(int fd,struct nmb_name *name,
79 struct in_addr to_ip, int *num_names)
83 int retry_time = 2000;
85 struct packet_struct p;
86 struct packet_struct *p2;
87 struct nmb_packet *nmb = &p.packet.nmb;
88 struct node_status *ret;
92 nmb->header.name_trn_id = generate_trn_id();
93 nmb->header.opcode = 0;
94 nmb->header.response = False;
95 nmb->header.nm_flags.bcast = False;
96 nmb->header.nm_flags.recursion_available = False;
97 nmb->header.nm_flags.recursion_desired = False;
98 nmb->header.nm_flags.trunc = False;
99 nmb->header.nm_flags.authoritative = False;
100 nmb->header.rcode = 0;
101 nmb->header.qdcount = 1;
102 nmb->header.ancount = 0;
103 nmb->header.nscount = 0;
104 nmb->header.arcount = 0;
105 nmb->question.question_name = *name;
106 nmb->question.question_type = 0x21;
107 nmb->question.question_class = 0x1;
112 p.timestamp = time(NULL);
113 p.packet_type = NMB_PACKET;
117 if (!send_packet(&p))
123 struct timeval tval2;
124 GetTimeOfDay(&tval2);
125 if (TvalDiff(&tval,&tval2) > retry_time) {
128 if (!found && !send_packet(&p))
134 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
135 struct nmb_packet *nmb2 = &p2->packet.nmb;
136 debug_nmb_packet(p2);
138 if (nmb2->header.opcode != 0 ||
139 nmb2->header.nm_flags.bcast ||
140 nmb2->header.rcode ||
141 !nmb2->header.ancount ||
142 nmb2->answers->rr_type != 0x21) {
143 /* XXXX what do we do with this? could be a
144 redirect, but we'll discard it for the
150 ret = parse_node_status(&nmb2->answers->rdata[0], num_names);
160 /****************************************************************************
161 find the first type XX name in a node status reply - used for finding
162 a servers name given its IP
163 return the matched name in *name
164 **************************************************************************/
165 BOOL name_status_find(int type, struct in_addr to_ip, char *name)
167 struct node_status *status;
168 struct nmb_name nname;
172 sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
173 if (sock == -1) return False;
175 make_nmb_name(&nname, "*", 0);
176 status = node_status_query(sock, &nname, to_ip, &count);
178 if (!status) return False;
180 for (i=0;i<count;i++) {
181 if (status[i].type == type) break;
183 if (i == count) return False;
185 pull_ascii(name, status[i].name, 15, 0, STR_TERMINATE);
191 /****************************************************************************
192 Do a NetBIOS name registation to try to claim a name ...
193 ***************************************************************************/
194 BOOL name_register(int fd, const char *name, int name_type,
195 struct in_addr name_ip, int opcode,
197 struct in_addr to_ip, int *count)
201 struct packet_struct p;
202 struct packet_struct *p2;
203 struct nmb_packet *nmb = &p.packet.nmb;
204 struct in_addr register_ip;
206 DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
208 register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
210 bzero((char *)&p, sizeof(p));
214 nmb->header.name_trn_id = generate_trn_id();
215 nmb->header.opcode = opcode;
216 nmb->header.response = False;
217 nmb->header.nm_flags.bcast = False;
218 nmb->header.nm_flags.recursion_available = False;
219 nmb->header.nm_flags.recursion_desired = True; /* ? */
220 nmb->header.nm_flags.trunc = False;
221 nmb->header.nm_flags.authoritative = True;
223 nmb->header.qdcount = 1;
224 nmb->header.ancount = 0;
225 nmb->header.nscount = 0;
226 nmb->header.arcount = 1;
228 make_nmb_name(&nmb->question.question_name, name, name_type);
230 nmb->question.question_type = 0x20;
231 nmb->question.question_class = 0x1;
233 /* Now, create the additional stuff for a registration request */
235 if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
237 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
242 bzero((char *)nmb->additional, sizeof(struct res_rec));
244 nmb->additional->rr_name = nmb->question.question_name;
245 nmb->additional->rr_type = RR_TYPE_NB;
246 nmb->additional->rr_class = RR_CLASS_IN;
248 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
249 if (nmb->header.nm_flags.bcast)
250 nmb->additional->ttl = PERMANENT_TTL;
252 nmb->additional->ttl = lp_max_ttl();
254 nmb->additional->rdlength = 6;
256 nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
258 /* Set the address for the name we are registering. */
259 putip(&nmb->additional->rdata[2], ®ister_ip);
264 p.timestamp = time(NULL);
265 p.packet_type = NMB_PACKET;
269 if (!send_packet(&p))
274 if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
275 debug_nmb_packet(p2);
276 free(p2); /* No memory leaks ... */
282 /****************************************************************************
283 Do a netbios name query to find someones IP.
284 Returns an array of IP addresses or NULL if none.
285 *count will be set to the number of addresses returned.
286 ****************************************************************************/
287 struct in_addr *name_query(int fd,const char *name,int name_type,
288 BOOL bcast,BOOL recurse,
289 struct in_addr to_ip, int *count)
293 int retry_time = bcast?250:2000;
295 struct packet_struct p;
296 struct packet_struct *p2;
297 struct nmb_packet *nmb = &p.packet.nmb;
298 struct in_addr *ip_list = NULL;
300 memset((char *)&p,'\0',sizeof(p));
303 nmb->header.name_trn_id = generate_trn_id();
304 nmb->header.opcode = 0;
305 nmb->header.response = False;
306 nmb->header.nm_flags.bcast = bcast;
307 nmb->header.nm_flags.recursion_available = False;
308 nmb->header.nm_flags.recursion_desired = recurse;
309 nmb->header.nm_flags.trunc = False;
310 nmb->header.nm_flags.authoritative = False;
311 nmb->header.rcode = 0;
312 nmb->header.qdcount = 1;
313 nmb->header.ancount = 0;
314 nmb->header.nscount = 0;
315 nmb->header.arcount = 0;
317 make_nmb_name(&nmb->question.question_name,name,name_type);
319 nmb->question.question_type = 0x20;
320 nmb->question.question_class = 0x1;
325 p.timestamp = time(NULL);
326 p.packet_type = NMB_PACKET;
330 if (!send_packet(&p))
337 struct timeval tval2;
338 struct in_addr *tmp_ip_list;
340 GetTimeOfDay(&tval2);
341 if (TvalDiff(&tval,&tval2) > retry_time) {
344 if (!found && !send_packet(&p))
350 if ((p2=receive_nmb_packet(fd,90,nmb->header.name_trn_id))) {
351 struct nmb_packet *nmb2 = &p2->packet.nmb;
352 debug_nmb_packet(p2);
354 /* If we get a Negative Name Query Response from a WINS
355 * server, we should report it and give up.
357 if( 0 == nmb2->header.opcode /* A query response */
358 && !(bcast) /* from a WINS server */
359 && nmb2->header.rcode /* Error returned */
362 if( DEBUGLVL( 3 ) ) {
363 /* Only executed if DEBUGLEVEL >= 3 */
364 dbgtext( "Negative name query response, rcode 0x%02x: ",
365 nmb2->header.rcode );
366 switch( nmb2->header.rcode ) {
368 dbgtext( "Request was invalidly formatted.\n" );
371 dbgtext( "Problem with NBNS, cannot process name.\n");
374 dbgtext( "The name requested does not exist.\n" );
377 dbgtext( "Unsupported request error.\n" );
380 dbgtext( "Query refused error.\n" );
383 dbgtext( "Unrecognized error code.\n" );
391 if (nmb2->header.opcode != 0 ||
392 nmb2->header.nm_flags.bcast ||
393 nmb2->header.rcode ||
394 !nmb2->header.ancount) {
396 * XXXX what do we do with this? Could be a
397 * redirect, but we'll discard it for the
403 tmp_ip_list = (struct in_addr *)Realloc( ip_list, sizeof( ip_list[0] )
404 * ( (*count) + nmb2->answers->rdlength/6 ) );
407 DEBUG(0,("name_query: Realloc failed.\n"));
412 ip_list = tmp_ip_list;
415 DEBUG(2,("Got a positive name query response from %s ( ",
417 for (i=0;i<nmb2->answers->rdlength/6;i++) {
418 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
419 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
429 * If we're doing a unicast lookup we only
430 * expect one reply. Don't wait the full 2
431 * seconds if we got one. JRA.
438 /* Reach here if we've timed out waiting for replies.. */
439 if( !bcast && !found )
441 /* Timed out wating for WINS server to respond. Mark it dead. */
442 wins_srv_died( to_ip );
448 /********************************************************
449 Start parsing the lmhosts file.
450 *********************************************************/
452 FILE *startlmhosts(char *fname)
454 FILE *fp = sys_fopen(fname,"r");
456 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
457 fname, strerror(errno)));
463 /********************************************************
464 Parse the next line in the lmhosts file.
465 *********************************************************/
467 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
471 while(!feof(fp) && !ferror(fp)) {
472 pstring ip,flags,extra;
478 if (!fgets_slash(line,sizeof(pstring),fp))
490 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
492 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
494 if (next_token(&ptr,flags,NULL, sizeof(flags)))
496 if (next_token(&ptr,extra,NULL, sizeof(extra)))
502 if (count > 0 && count < 2)
504 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
510 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
514 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
516 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
518 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
522 *ipaddr = *interpret_addr2(ip);
524 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
525 then only add that name type. */
526 if((ptr = strchr_m(name, '#')) != NULL)
531 *name_type = (int)strtol(ptr, &endptr, 16);
533 if(!*ptr || (endptr == ptr))
535 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
539 *(--ptr) = '\0'; /* Truncate at the '#' */
548 /********************************************************
549 Finish parsing the lmhosts file.
550 *********************************************************/
552 void endlmhosts(FILE *fp)
557 BOOL name_register_wins(const char *name, int name_type)
559 int sock, i, return_count;
560 int num_interfaces = iface_count();
561 struct in_addr sendto_ip;
564 * Check if we have any interfaces, prevents a segfault later
567 if (num_interfaces <= 0)
568 return False; /* Should return some indication of the problem */
571 * Do a broadcast register ...
574 if (0 == wins_srv_count())
579 dbgtext( "name_register_wins: Registering my name %s ", name );
580 dbgtext( "with WINS server %s.\n", wins_srv_name() );
583 sock = open_socket_in( SOCK_DGRAM, 0, 3,
584 interpret_addr("0.0.0.0"), True );
586 if (sock == -1) return False;
588 set_socket_options(sock, "SO_BROADCAST"); /* ????! crh */
590 sendto_ip = wins_srv_ip();
592 if (num_interfaces > 1) {
594 for (i = 0; i < num_interfaces; i++) {
596 if (!name_register(sock, name, name_type, *iface_n_ip(i),
597 NMB_NAME_MULTIHOMED_REG_OPCODE,
598 True, sendto_ip, &return_count)) {
610 if (!name_register(sock, name, name_type, *iface_n_ip(0),
612 True, sendto_ip, &return_count)) {
627 /********************************************************
628 Resolve via "bcast" method.
629 *********************************************************/
631 BOOL name_resolve_bcast(const char *name, int name_type,
632 struct in_addr **return_ip_list, int *return_count)
635 int num_interfaces = iface_count();
637 *return_ip_list = NULL;
641 * "bcast" means do a broadcast lookup on all the local interfaces.
644 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
646 sock = open_socket_in( SOCK_DGRAM, 0, 3,
647 interpret_addr(lp_socket_address()), True );
649 if (sock == -1) return False;
651 set_socket_options(sock,"SO_BROADCAST");
653 * Lookup the name on all the interfaces, return on
654 * the first successful match.
656 for( i = num_interfaces-1; i >= 0; i--) {
657 struct in_addr sendto_ip;
658 /* Done this way to fix compiler error on IRIX 5.x */
659 sendto_ip = *iface_bcast(*iface_n_ip(i));
660 *return_ip_list = name_query(sock, name, name_type, True,
661 True, sendto_ip, return_count);
662 if(*return_ip_list != NULL) {
672 /********************************************************
673 Resolve via "wins" method.
674 *********************************************************/
676 static BOOL resolve_wins(const char *name, int name_type,
677 struct in_addr **return_iplist, int *return_count)
680 struct in_addr wins_ip;
683 *return_iplist = NULL;
687 * "wins" means do a unicast lookup to the WINS server.
688 * Ignore if there is no WINS server specified or if the
689 * WINS server is one of our interfaces (if we're being
690 * called from within nmbd - we can't do this call as we
694 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
696 if (lp_wins_support()) {
698 * We're providing WINS support. Call ourselves so
699 * long as we're not nmbd.
701 extern struct in_addr loopback_ip;
702 wins_ip = loopback_ip;
704 } else if( wins_srv_count() < 1 ) {
705 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
708 wins_ip = wins_srv_ip();
709 wins_ismyip = ismyip(wins_ip);
712 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
713 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
714 sock = open_socket_in( SOCK_DGRAM, 0, 3,
715 interpret_addr(lp_socket_address()),
718 *return_iplist = name_query( sock, name,
722 if(*return_iplist != NULL) {
733 /********************************************************
734 Resolve via "lmhosts" method.
735 *********************************************************/
737 static BOOL resolve_lmhosts(const char *name, int name_type,
738 struct in_addr **return_iplist, int *return_count)
741 * "lmhosts" means parse the local lmhosts file.
747 struct in_addr return_ip;
749 *return_iplist = NULL;
752 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
754 fp = startlmhosts( LMHOSTSFILE );
756 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
757 if (strequal(name, lmhost_name) &&
758 ((name_type2 == -1) || (name_type == name_type2))
761 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
762 if(*return_iplist == NULL) {
763 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
766 **return_iplist = return_ip;
777 /********************************************************
778 Resolve via "hosts" method.
779 *********************************************************/
781 static BOOL resolve_hosts(const char *name,
782 struct in_addr **return_iplist, int *return_count)
785 * "host" means do a localhost, or dns lookup.
789 *return_iplist = NULL;
792 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
794 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
795 struct in_addr return_ip;
796 putip((char *)&return_ip,(char *)hp->h_addr);
797 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
798 if(*return_iplist == NULL) {
799 DEBUG(3,("resolve_hosts: malloc fail !\n"));
802 **return_iplist = return_ip;
809 /********************************************************
810 Internal interface to resolve a name into an IP address.
811 Use this function if the string is either an IP address, DNS
812 or host name or NetBIOS name. This uses the name switch in the
813 smb.conf to determine the order of name resolution.
814 *********************************************************/
816 static BOOL internal_resolve_name(const char *name, int name_type,
817 struct in_addr **return_iplist, int *return_count)
819 pstring name_resolve_list;
822 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
823 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
824 BOOL is_address = is_ipaddress(name);
825 *return_iplist = NULL;
828 if (allzeros || allones || is_address) {
829 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
830 if(*return_iplist == NULL) {
831 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
835 /* if it's in the form of an IP address then get the lib to interpret it */
836 (*return_iplist)->s_addr = inet_addr(name);
838 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
844 pstrcpy(name_resolve_list, lp_name_resolve_order());
845 ptr = name_resolve_list;
849 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
850 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
851 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
854 } else if(strequal( tok, "lmhosts")) {
855 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
858 } else if(strequal( tok, "wins")) {
859 /* don't resolve 1D via WINS */
860 if (name_type != 0x1D &&
861 resolve_wins(name, name_type, return_iplist, return_count)) {
864 } else if(strequal( tok, "bcast")) {
865 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
869 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
873 if((*return_iplist) != NULL) {
874 free((char *)(*return_iplist));
875 *return_iplist = NULL;
880 /********************************************************
881 Internal interface to resolve a name into one IP address.
882 Use this function if the string is either an IP address, DNS
883 or host name or NetBIOS name. This uses the name switch in the
884 smb.conf to determine the order of name resolution.
885 *********************************************************/
887 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
889 struct in_addr *ip_list = NULL;
892 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
893 *return_ip = ip_list[0];
894 free((char *)ip_list);
898 free((char *)ip_list);
903 /********************************************************
904 resolve a name of format \\server_name or \\ipaddress
905 into a name. also, cut the \\ from the front for us.
906 *********************************************************/
908 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
912 const char *sv_name = srv_name;
914 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
916 if (srv_name == NULL || strequal("\\\\.", srv_name))
918 extern pstring global_myname;
919 fstrcpy(dest_host, global_myname);
920 ip = interpret_addr2("127.0.0.1");
924 if (strnequal("\\\\", srv_name, 2))
926 sv_name = &srv_name[2];
929 fstrcpy(dest_host, sv_name);
930 /* treat the '*' name specially - it is a magic name for the PDC */
931 if (strcmp(dest_host,"*") == 0) {
932 extern pstring global_myname;
933 ret = resolve_name(lp_workgroup(), ip, 0x1B);
934 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
936 ret = resolve_name(dest_host, ip, 0x20);
939 if (is_ipaddress(dest_host))
941 fstrcpy(dest_host, "*SMBSERVER");
948 /********************************************************
949 Find the IP address of the master browser or DMB for a workgroup.
950 *********************************************************/
952 BOOL find_master_ip(char *group, struct in_addr *master_ip)
954 struct in_addr *ip_list = NULL;
957 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
958 *master_ip = ip_list[0];
959 free((char *)ip_list);
962 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
963 *master_ip = ip_list[0];
964 free((char *)ip_list);
969 free((char *)ip_list);
973 /********************************************************
974 Lookup a PDC name given a Domain name and IP address.
975 *********************************************************/
977 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
979 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
985 * Due to the fact win WinNT *sucks* we must do a node status
991 ret = name_status_find(0x20,*pdc_ip,pdc_name);
993 if(ret && *pdc_name) {
994 fstrcpy(ret_name, pdc_name);
1000 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1002 JRA - This code is broken with BDC rollover - we need to do a full
1003 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1006 int retry_time = 2000;
1007 struct timeval tval;
1008 struct packet_struct p;
1009 struct dgram_packet *dgram = &p.packet.dgram;
1013 struct sockaddr_in sock_name;
1014 int sock_len = sizeof(sock_name);
1015 const char *mailslot = NET_LOGON_MAILSLOT;
1016 char *mailslot_name;
1019 int dgm_id = generate_trn_id();
1020 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1025 /* Find out the transient UDP port we have been allocated. */
1026 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1027 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1034 * Create the request data.
1037 memset(buffer,'\0',sizeof(buffer));
1039 SSVAL(bufp,0,QUERYFORPDC);
1041 fstrcpy(bufp,srcname);
1042 bufp += (strlen(bufp) + 1);
1043 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1044 mailslot_name = bufp;
1045 bufp += (strlen(bufp) + 1);
1046 bufp = ALIGN2(bufp, buffer);
1047 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1050 SSVAL(bufp,4,0xFFFF);
1051 SSVAL(bufp,6,0xFFFF);
1053 len = PTR_DIFF(bufp,buffer);
1055 memset((char *)&p,'\0',sizeof(p));
1057 /* DIRECT GROUP or UNIQUE datagram. */
1058 dgram->header.msg_type = 0x10;
1059 dgram->header.flags.node_type = M_NODE;
1060 dgram->header.flags.first = True;
1061 dgram->header.flags.more = False;
1062 dgram->header.dgm_id = dgm_id;
1063 dgram->header.source_ip = *iface_ip(*pdc_ip);
1064 dgram->header.source_port = ntohs(sock_name.sin_port);
1065 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1066 dgram->header.packet_offset = 0;
1068 make_nmb_name(&dgram->source_name,srcname,0);
1069 make_nmb_name(&dgram->dest_name,domain,0x1C);
1071 ptr = &dgram->data[0];
1073 /* Setup the smb part. */
1074 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1076 set_message(ptr,17,17 + len,True);
1079 CVAL(ptr,smb_com) = SMBtrans;
1080 SSVAL(ptr,smb_vwv1,len);
1081 SSVAL(ptr,smb_vwv11,len);
1082 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1083 SSVAL(ptr,smb_vwv13,3);
1084 SSVAL(ptr,smb_vwv14,1);
1085 SSVAL(ptr,smb_vwv15,1);
1086 SSVAL(ptr,smb_vwv16,2);
1088 pstrcpy(p2,mailslot);
1089 p2 = skip_string(p2,1);
1091 memcpy(p2,buffer,len);
1094 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1097 p.port = DGRAM_PORT;
1099 p.timestamp = time(NULL);
1100 p.packet_type = DGRAM_PACKET;
1102 GetTimeOfDay(&tval);
1104 if (!send_packet(&p)) {
1105 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1113 struct timeval tval2;
1114 struct packet_struct *p_ret;
1116 GetTimeOfDay(&tval2);
1117 if (TvalDiff(&tval,&tval2) > retry_time) {
1120 if (!send_packet(&p)) {
1121 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1125 GetTimeOfDay(&tval);
1129 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1130 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1134 buf = &dgram2->data[0];
1137 if (CVAL(buf,smb_com) != SMBtrans) {
1138 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1139 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1144 len = SVAL(buf,smb_vwv11);
1145 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1148 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1153 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1154 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1155 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1157 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1158 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1159 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1165 /* Note this is safe as it is a bounded strcpy. */
1166 fstrcpy(ret_name, buf2);
1167 ret_name[sizeof(fstring)-1] = '\0';
1176 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1180 /********************************************************
1181 Get the IP address list of the PDC/BDC's of a Domain.
1182 *********************************************************/
1183 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1185 return internal_resolve_name(group, pdc_only ? 0x1B : 0x1C, ip_list, count);