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 SAFE_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"));
411 ip_list = tmp_ip_list;
414 DEBUG(2,("Got a positive name query response from %s ( ",
416 for (i=0;i<nmb2->answers->rdlength/6;i++) {
417 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
418 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
428 * If we're doing a unicast lookup we only
429 * expect one reply. Don't wait the full 2
430 * seconds if we got one. JRA.
437 /* Reach here if we've timed out waiting for replies.. */
438 if( !bcast && !found )
440 /* Timed out wating for WINS server to respond. Mark it dead. */
441 wins_srv_died( to_ip );
447 /********************************************************
448 Start parsing the lmhosts file.
449 *********************************************************/
451 XFILE *startlmhosts(char *fname)
453 XFILE *fp = x_fopen(fname,O_RDONLY, 0);
455 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
456 fname, strerror(errno)));
462 /********************************************************
463 Parse the next line in the lmhosts file.
464 *********************************************************/
466 BOOL getlmhostsent( XFILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
470 while(!x_feof(fp) && !x_ferror(fp)) {
471 pstring ip,flags,extra;
477 if (!fgets_slash(line,sizeof(pstring),fp))
489 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
491 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
493 if (next_token(&ptr,flags,NULL, sizeof(flags)))
495 if (next_token(&ptr,extra,NULL, sizeof(extra)))
501 if (count > 0 && count < 2)
503 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
509 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
513 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
515 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
517 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
521 *ipaddr = *interpret_addr2(ip);
523 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
524 then only add that name type. */
525 if((ptr = strchr_m(name, '#')) != NULL)
530 *name_type = (int)strtol(ptr, &endptr, 16);
532 if(!*ptr || (endptr == ptr))
534 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
538 *(--ptr) = '\0'; /* Truncate at the '#' */
547 /********************************************************
548 Finish parsing the lmhosts file.
549 *********************************************************/
551 void endlmhosts(XFILE *fp)
556 BOOL name_register_wins(const char *name, int name_type)
558 int sock, i, return_count;
559 int num_interfaces = iface_count();
560 struct in_addr sendto_ip;
563 * Check if we have any interfaces, prevents a segfault later
566 if (num_interfaces <= 0)
567 return False; /* Should return some indication of the problem */
570 * Do a broadcast register ...
573 if (0 == wins_srv_count())
578 dbgtext( "name_register_wins: Registering my name %s ", name );
579 dbgtext( "with WINS server %s.\n", wins_srv_name() );
582 sock = open_socket_in( SOCK_DGRAM, 0, 3,
583 interpret_addr("0.0.0.0"), True );
585 if (sock == -1) return False;
587 set_socket_options(sock, "SO_BROADCAST"); /* ????! crh */
589 sendto_ip = wins_srv_ip();
591 if (num_interfaces > 1) {
593 for (i = 0; i < num_interfaces; i++) {
595 if (!name_register(sock, name, name_type, *iface_n_ip(i),
596 NMB_NAME_MULTIHOMED_REG_OPCODE,
597 True, sendto_ip, &return_count)) {
609 if (!name_register(sock, name, name_type, *iface_n_ip(0),
611 True, sendto_ip, &return_count)) {
626 /********************************************************
627 Resolve via "bcast" method.
628 *********************************************************/
630 BOOL name_resolve_bcast(const char *name, int name_type,
631 struct in_addr **return_ip_list, int *return_count)
634 int num_interfaces = iface_count();
636 *return_ip_list = NULL;
640 * "bcast" means do a broadcast lookup on all the local interfaces.
643 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
645 sock = open_socket_in( SOCK_DGRAM, 0, 3,
646 interpret_addr(lp_socket_address()), True );
648 if (sock == -1) return False;
650 set_socket_options(sock,"SO_BROADCAST");
652 * Lookup the name on all the interfaces, return on
653 * the first successful match.
655 for( i = num_interfaces-1; i >= 0; i--) {
656 struct in_addr sendto_ip;
657 /* Done this way to fix compiler error on IRIX 5.x */
658 sendto_ip = *iface_bcast(*iface_n_ip(i));
659 *return_ip_list = name_query(sock, name, name_type, True,
660 True, sendto_ip, return_count);
661 if(*return_ip_list != NULL) {
671 /********************************************************
672 Resolve via "wins" method.
673 *********************************************************/
675 static BOOL resolve_wins(const char *name, int name_type,
676 struct in_addr **return_iplist, int *return_count)
679 struct in_addr wins_ip;
682 *return_iplist = NULL;
686 * "wins" means do a unicast lookup to the WINS server.
687 * Ignore if there is no WINS server specified or if the
688 * WINS server is one of our interfaces (if we're being
689 * called from within nmbd - we can't do this call as we
693 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
695 if (lp_wins_support()) {
697 * We're providing WINS support. Call ourselves so
698 * long as we're not nmbd.
700 extern struct in_addr loopback_ip;
701 wins_ip = loopback_ip;
703 } else if( wins_srv_count() < 1 ) {
704 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
707 wins_ip = wins_srv_ip();
708 wins_ismyip = ismyip(wins_ip);
711 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
712 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
713 sock = open_socket_in( SOCK_DGRAM, 0, 3,
714 interpret_addr(lp_socket_address()),
717 *return_iplist = name_query( sock, name,
721 if(*return_iplist != NULL) {
732 /********************************************************
733 Resolve via "lmhosts" method.
734 *********************************************************/
736 static BOOL resolve_lmhosts(const char *name, int name_type,
737 struct in_addr **return_iplist, int *return_count)
740 * "lmhosts" means parse the local lmhosts file.
746 struct in_addr return_ip;
748 *return_iplist = NULL;
751 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
753 fp = startlmhosts( LMHOSTSFILE );
755 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
756 if (strequal(name, lmhost_name) &&
757 ((name_type2 == -1) || (name_type == name_type2))
760 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
761 if(*return_iplist == NULL) {
762 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
765 **return_iplist = return_ip;
776 /********************************************************
777 Resolve via "hosts" method.
778 *********************************************************/
780 static BOOL resolve_hosts(const char *name,
781 struct in_addr **return_iplist, int *return_count)
784 * "host" means do a localhost, or dns lookup.
788 *return_iplist = NULL;
791 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
793 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
794 struct in_addr return_ip;
795 putip((char *)&return_ip,(char *)hp->h_addr);
796 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
797 if(*return_iplist == NULL) {
798 DEBUG(3,("resolve_hosts: malloc fail !\n"));
801 **return_iplist = return_ip;
808 /********************************************************
809 Internal interface to resolve a name into an IP address.
810 Use this function if the string is either an IP address, DNS
811 or host name or NetBIOS name. This uses the name switch in the
812 smb.conf to determine the order of name resolution.
813 *********************************************************/
815 static BOOL internal_resolve_name(const char *name, int name_type,
816 struct in_addr **return_iplist, int *return_count)
818 pstring name_resolve_list;
821 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
822 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
823 BOOL is_address = is_ipaddress(name);
824 *return_iplist = NULL;
827 if (allzeros || allones || is_address) {
828 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
829 if(*return_iplist == NULL) {
830 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
834 /* if it's in the form of an IP address then get the lib to interpret it */
835 (*return_iplist)->s_addr = inet_addr(name);
837 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
843 pstrcpy(name_resolve_list, lp_name_resolve_order());
844 ptr = name_resolve_list;
848 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
849 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
850 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
853 } else if(strequal( tok, "lmhosts")) {
854 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
857 } else if(strequal( tok, "wins")) {
858 /* don't resolve 1D via WINS */
859 if (name_type != 0x1D &&
860 resolve_wins(name, name_type, return_iplist, return_count)) {
863 } else if(strequal( tok, "bcast")) {
864 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
868 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
872 SAFE_FREE(*return_iplist);
876 /********************************************************
877 Internal interface to resolve a name into one IP address.
878 Use this function if the string is either an IP address, DNS
879 or host name or NetBIOS name. This uses the name switch in the
880 smb.conf to determine the order of name resolution.
881 *********************************************************/
883 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
885 struct in_addr *ip_list = NULL;
888 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
889 *return_ip = ip_list[0];
898 /********************************************************
899 resolve a name of format \\server_name or \\ipaddress
900 into a name. also, cut the \\ from the front for us.
901 *********************************************************/
903 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
907 const char *sv_name = srv_name;
909 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
911 if (srv_name == NULL || strequal("\\\\.", srv_name))
913 extern pstring global_myname;
914 fstrcpy(dest_host, global_myname);
915 ip = interpret_addr2("127.0.0.1");
919 if (strnequal("\\\\", srv_name, 2))
921 sv_name = &srv_name[2];
924 fstrcpy(dest_host, sv_name);
925 /* treat the '*' name specially - it is a magic name for the PDC */
926 if (strcmp(dest_host,"*") == 0) {
927 extern pstring global_myname;
928 ret = resolve_name(lp_workgroup(), ip, 0x1B);
929 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
931 ret = resolve_name(dest_host, ip, 0x20);
934 if (is_ipaddress(dest_host))
936 fstrcpy(dest_host, "*SMBSERVER");
943 /********************************************************
944 Find the IP address of the master browser or DMB for a workgroup.
945 *********************************************************/
947 BOOL find_master_ip(char *group, struct in_addr *master_ip)
949 struct in_addr *ip_list = NULL;
952 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
953 *master_ip = ip_list[0];
957 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
958 *master_ip = ip_list[0];
967 /********************************************************
968 Lookup a PDC name given a Domain name and IP address.
969 *********************************************************/
971 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
973 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
979 * Due to the fact win WinNT *sucks* we must do a node status
985 ret = name_status_find(0x20,*pdc_ip,pdc_name);
987 if(ret && *pdc_name) {
988 fstrcpy(ret_name, pdc_name);
994 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
996 JRA - This code is broken with BDC rollover - we need to do a full
997 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
1000 int retry_time = 2000;
1001 struct timeval tval;
1002 struct packet_struct p;
1003 struct dgram_packet *dgram = &p.packet.dgram;
1007 struct sockaddr_in sock_name;
1008 int sock_len = sizeof(sock_name);
1009 const char *mailslot = NET_LOGON_MAILSLOT;
1010 char *mailslot_name;
1013 int dgm_id = generate_trn_id();
1014 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1019 /* Find out the transient UDP port we have been allocated. */
1020 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1021 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1028 * Create the request data.
1031 memset(buffer,'\0',sizeof(buffer));
1033 SSVAL(bufp,0,QUERYFORPDC);
1035 fstrcpy(bufp,srcname);
1036 bufp += (strlen(bufp) + 1);
1037 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1038 mailslot_name = bufp;
1039 bufp += (strlen(bufp) + 1);
1040 bufp = ALIGN2(bufp, buffer);
1041 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1044 SSVAL(bufp,4,0xFFFF);
1045 SSVAL(bufp,6,0xFFFF);
1047 len = PTR_DIFF(bufp,buffer);
1049 memset((char *)&p,'\0',sizeof(p));
1051 /* DIRECT GROUP or UNIQUE datagram. */
1052 dgram->header.msg_type = 0x10;
1053 dgram->header.flags.node_type = M_NODE;
1054 dgram->header.flags.first = True;
1055 dgram->header.flags.more = False;
1056 dgram->header.dgm_id = dgm_id;
1057 dgram->header.source_ip = *iface_ip(*pdc_ip);
1058 dgram->header.source_port = ntohs(sock_name.sin_port);
1059 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1060 dgram->header.packet_offset = 0;
1062 make_nmb_name(&dgram->source_name,srcname,0);
1063 make_nmb_name(&dgram->dest_name,domain,0x1C);
1065 ptr = &dgram->data[0];
1067 /* Setup the smb part. */
1068 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1070 set_message(ptr,17,17 + len,True);
1073 CVAL(ptr,smb_com) = SMBtrans;
1074 SSVAL(ptr,smb_vwv1,len);
1075 SSVAL(ptr,smb_vwv11,len);
1076 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1077 SSVAL(ptr,smb_vwv13,3);
1078 SSVAL(ptr,smb_vwv14,1);
1079 SSVAL(ptr,smb_vwv15,1);
1080 SSVAL(ptr,smb_vwv16,2);
1082 pstrcpy(p2,mailslot);
1083 p2 = skip_string(p2,1);
1085 memcpy(p2,buffer,len);
1088 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1091 p.port = DGRAM_PORT;
1093 p.timestamp = time(NULL);
1094 p.packet_type = DGRAM_PACKET;
1096 GetTimeOfDay(&tval);
1098 if (!send_packet(&p)) {
1099 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1107 struct timeval tval2;
1108 struct packet_struct *p_ret;
1110 GetTimeOfDay(&tval2);
1111 if (TvalDiff(&tval,&tval2) > retry_time) {
1114 if (!send_packet(&p)) {
1115 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1119 GetTimeOfDay(&tval);
1123 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1124 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1128 buf = &dgram2->data[0];
1131 if (CVAL(buf,smb_com) != SMBtrans) {
1132 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1133 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1138 len = SVAL(buf,smb_vwv11);
1139 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1142 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1147 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1148 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1149 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1151 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1152 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1153 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1159 /* Note this is safe as it is a bounded strcpy. */
1160 fstrcpy(ret_name, buf2);
1161 ret_name[sizeof(fstring)-1] = '\0';
1170 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1174 /********************************************************
1175 Get the IP address list of the PDC/BDC's of a Domain.
1176 *********************************************************/
1177 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1179 return internal_resolve_name(group, pdc_only ? 0x1B : 0x1C, ip_list, count);