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 *name_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 = name_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 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 ip_list = (struct in_addr *)Realloc( ip_list,
403 * ( (*count) + nmb2->answers->rdlength/6 ) );
405 DEBUG(2,("Got a positive name query response from %s ( ",
407 for (i=0;i<nmb2->answers->rdlength/6;i++) {
408 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
409 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
419 * If we're doing a unicast lookup we only
420 * expect one reply. Don't wait the full 2
421 * seconds if we got one. JRA.
428 /* Reach here if we've timed out waiting for replies.. */
429 if( !bcast && !found )
431 /* Timed out wating for WINS server to respond. Mark it dead. */
432 wins_srv_died( to_ip );
438 /********************************************************
439 Start parsing the lmhosts file.
440 *********************************************************/
442 FILE *startlmhosts(char *fname)
444 FILE *fp = sys_fopen(fname,"r");
446 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
447 fname, strerror(errno)));
453 /********************************************************
454 Parse the next line in the lmhosts file.
455 *********************************************************/
457 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
461 while(!feof(fp) && !ferror(fp)) {
462 pstring ip,flags,extra;
468 if (!fgets_slash(line,sizeof(pstring),fp))
480 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
482 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
484 if (next_token(&ptr,flags,NULL, sizeof(flags)))
486 if (next_token(&ptr,extra,NULL, sizeof(extra)))
492 if (count > 0 && count < 2)
494 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
500 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
504 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
506 if (strchr_m(flags,'G') || strchr_m(flags,'S'))
508 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
512 *ipaddr = *interpret_addr2(ip);
514 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
515 then only add that name type. */
516 if((ptr = strchr_m(name, '#')) != NULL)
521 *name_type = (int)strtol(ptr, &endptr, 16);
523 if(!*ptr || (endptr == ptr))
525 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
529 *(--ptr) = '\0'; /* Truncate at the '#' */
538 /********************************************************
539 Finish parsing the lmhosts file.
540 *********************************************************/
542 void endlmhosts(FILE *fp)
547 BOOL name_register_wins(const char *name, int name_type)
549 int sock, i, return_count;
550 int num_interfaces = iface_count();
551 struct in_addr sendto_ip;
554 * Do a broadcast register ...
557 if (!lp_wins_server())
560 DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name, lp_wins_server()));
562 sock = open_socket_in(SOCK_DGRAM, 0, 3,
563 interpret_addr("0.0.0.0"), True);
565 if (sock == -1) return False;
567 set_socket_options(sock, "SO_BROADCAST");
569 sendto_ip.s_addr = inet_addr(lp_wins_server());
571 if (num_interfaces > 1) {
573 for (i = 0; i < num_interfaces; i++) {
575 if (!name_register(sock, name, name_type, *iface_n_ip(i),
576 NMB_NAME_MULTIHOMED_REG_OPCODE,
577 True, sendto_ip, &return_count)) {
589 if (!name_register(sock, name, name_type, *iface_n_ip(0),
591 True, sendto_ip, &return_count)) {
606 /********************************************************
607 Resolve via "bcast" method.
608 *********************************************************/
610 BOOL name_resolve_bcast(const char *name, int name_type,
611 struct in_addr **return_ip_list, int *return_count)
614 int num_interfaces = iface_count();
616 *return_ip_list = NULL;
620 * "bcast" means do a broadcast lookup on all the local interfaces.
623 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
625 sock = open_socket_in( SOCK_DGRAM, 0, 3,
626 interpret_addr(lp_socket_address()), True );
628 if (sock == -1) return False;
630 set_socket_options(sock,"SO_BROADCAST");
632 * Lookup the name on all the interfaces, return on
633 * the first successful match.
635 for( i = num_interfaces-1; i >= 0; i--) {
636 struct in_addr sendto_ip;
637 /* Done this way to fix compiler error on IRIX 5.x */
638 sendto_ip = *iface_bcast(*iface_n_ip(i));
639 *return_ip_list = name_query(sock, name, name_type, True,
640 True, sendto_ip, return_count);
641 if(*return_ip_list != NULL) {
651 /********************************************************
652 Resolve via "wins" method.
653 *********************************************************/
655 static BOOL resolve_wins(const char *name, int name_type,
656 struct in_addr **return_iplist, int *return_count)
659 struct in_addr wins_ip;
662 *return_iplist = NULL;
666 * "wins" means do a unicast lookup to the WINS server.
667 * Ignore if there is no WINS server specified or if the
668 * WINS server is one of our interfaces (if we're being
669 * called from within nmbd - we can't do this call as we
673 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
675 if (lp_wins_support()) {
677 * We're providing WINS support. Call ourselves so
678 * long as we're not nmbd.
680 extern struct in_addr loopback_ip;
681 wins_ip = loopback_ip;
683 } else if( wins_srv_count() < 1 ) {
684 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
687 wins_ip = wins_srv_ip();
688 wins_ismyip = ismyip(wins_ip);
691 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
692 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
693 sock = open_socket_in( SOCK_DGRAM, 0, 3,
694 interpret_addr(lp_socket_address()),
697 *return_iplist = name_query( sock, name,
701 if(*return_iplist != NULL) {
712 /********************************************************
713 Resolve via "lmhosts" method.
714 *********************************************************/
716 static BOOL resolve_lmhosts(const char *name, int name_type,
717 struct in_addr **return_iplist, int *return_count)
720 * "lmhosts" means parse the local lmhosts file.
726 struct in_addr return_ip;
728 *return_iplist = NULL;
731 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
733 fp = startlmhosts( LMHOSTSFILE );
735 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
736 if (strequal(name, lmhost_name) &&
737 ((name_type2 == -1) || (name_type == name_type2))
740 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
741 if(*return_iplist == NULL) {
742 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
745 **return_iplist = return_ip;
756 /********************************************************
757 Resolve via "hosts" method.
758 *********************************************************/
760 static BOOL resolve_hosts(const char *name,
761 struct in_addr **return_iplist, int *return_count)
764 * "host" means do a localhost, or dns lookup.
768 *return_iplist = NULL;
771 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
773 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
774 struct in_addr return_ip;
775 putip((char *)&return_ip,(char *)hp->h_addr);
776 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
777 if(*return_iplist == NULL) {
778 DEBUG(3,("resolve_hosts: malloc fail !\n"));
781 **return_iplist = return_ip;
788 /********************************************************
789 Internal interface to resolve a name into an IP address.
790 Use this function if the string is either an IP address, DNS
791 or host name or NetBIOS name. This uses the name switch in the
792 smb.conf to determine the order of name resolution.
793 *********************************************************/
795 static BOOL internal_resolve_name(const char *name, int name_type,
796 struct in_addr **return_iplist, int *return_count)
798 pstring name_resolve_list;
801 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
802 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
803 BOOL is_address = is_ipaddress(name);
804 *return_iplist = NULL;
807 if (allzeros || allones || is_address) {
808 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
809 if(*return_iplist == NULL) {
810 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
814 /* if it's in the form of an IP address then get the lib to interpret it */
815 (*return_iplist)->s_addr = inet_addr(name);
817 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
823 pstrcpy(name_resolve_list, lp_name_resolve_order());
824 ptr = name_resolve_list;
828 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
829 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
830 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
833 } else if(strequal( tok, "lmhosts")) {
834 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
837 } else if(strequal( tok, "wins")) {
838 /* don't resolve 1D via WINS */
839 if (name_type != 0x1D &&
840 resolve_wins(name, name_type, return_iplist, return_count)) {
843 } else if(strequal( tok, "bcast")) {
844 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
848 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
852 if((*return_iplist) != NULL) {
853 free((char *)(*return_iplist));
854 *return_iplist = NULL;
859 /********************************************************
860 Internal interface to resolve a name into one IP address.
861 Use this function if the string is either an IP address, DNS
862 or host name or NetBIOS name. This uses the name switch in the
863 smb.conf to determine the order of name resolution.
864 *********************************************************/
866 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
868 struct in_addr *ip_list = NULL;
871 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
872 *return_ip = ip_list[0];
873 free((char *)ip_list);
877 free((char *)ip_list);
882 /********************************************************
883 resolve a name of format \\server_name or \\ipaddress
884 into a name. also, cut the \\ from the front for us.
885 *********************************************************/
887 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
891 const char *sv_name = srv_name;
893 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
895 if (srv_name == NULL || strequal("\\\\.", srv_name))
897 extern pstring global_myname;
898 fstrcpy(dest_host, global_myname);
899 ip = interpret_addr2("127.0.0.1");
903 if (strnequal("\\\\", srv_name, 2))
905 sv_name = &srv_name[2];
908 fstrcpy(dest_host, sv_name);
909 /* treat the '*' name specially - it is a magic name for the PDC */
910 if (strcmp(dest_host,"*") == 0) {
911 extern pstring global_myname;
912 ret = resolve_name(lp_workgroup(), ip, 0x1B);
913 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
915 ret = resolve_name(dest_host, ip, 0x20);
918 if (is_ipaddress(dest_host))
920 fstrcpy(dest_host, "*SMBSERVER");
927 /********************************************************
928 Find the IP address of the master browser or DMB for a workgroup.
929 *********************************************************/
931 BOOL find_master_ip(char *group, struct in_addr *master_ip)
933 struct in_addr *ip_list = NULL;
936 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
937 *master_ip = ip_list[0];
938 free((char *)ip_list);
941 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
942 *master_ip = ip_list[0];
943 free((char *)ip_list);
948 free((char *)ip_list);
952 /********************************************************
953 Lookup a PDC name given a Domain name and IP address.
954 *********************************************************/
956 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
958 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
964 * Due to the fact win WinNT *sucks* we must do a node status
970 ret = name_status_find(0x20,*pdc_ip,pdc_name);
972 if(ret && *pdc_name) {
973 fstrcpy(ret_name, pdc_name);
979 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
981 JRA - This code is broken with BDC rollover - we need to do a full
982 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
985 int retry_time = 2000;
987 struct packet_struct p;
988 struct dgram_packet *dgram = &p.packet.dgram;
992 struct sockaddr_in sock_name;
993 int sock_len = sizeof(sock_name);
994 const char *mailslot = NET_LOGON_MAILSLOT;
998 int dgm_id = generate_trn_id();
999 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
1004 /* Find out the transient UDP port we have been allocated. */
1005 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1006 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1013 * Create the request data.
1016 memset(buffer,'\0',sizeof(buffer));
1018 SSVAL(bufp,0,QUERYFORPDC);
1020 fstrcpy(bufp,srcname);
1021 bufp += (strlen(bufp) + 1);
1022 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1023 mailslot_name = bufp;
1024 bufp += (strlen(bufp) + 1);
1025 bufp = ALIGN2(bufp, buffer);
1026 bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE);
1029 SSVAL(bufp,4,0xFFFF);
1030 SSVAL(bufp,6,0xFFFF);
1032 len = PTR_DIFF(bufp,buffer);
1034 memset((char *)&p,'\0',sizeof(p));
1036 /* DIRECT GROUP or UNIQUE datagram. */
1037 dgram->header.msg_type = 0x10;
1038 dgram->header.flags.node_type = M_NODE;
1039 dgram->header.flags.first = True;
1040 dgram->header.flags.more = False;
1041 dgram->header.dgm_id = dgm_id;
1042 dgram->header.source_ip = *iface_ip(*pdc_ip);
1043 dgram->header.source_port = ntohs(sock_name.sin_port);
1044 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1045 dgram->header.packet_offset = 0;
1047 make_nmb_name(&dgram->source_name,srcname,0);
1048 make_nmb_name(&dgram->dest_name,domain,0x1C);
1050 ptr = &dgram->data[0];
1052 /* Setup the smb part. */
1053 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1055 set_message(ptr,17,17 + len,True);
1058 CVAL(ptr,smb_com) = SMBtrans;
1059 SSVAL(ptr,smb_vwv1,len);
1060 SSVAL(ptr,smb_vwv11,len);
1061 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1062 SSVAL(ptr,smb_vwv13,3);
1063 SSVAL(ptr,smb_vwv14,1);
1064 SSVAL(ptr,smb_vwv15,1);
1065 SSVAL(ptr,smb_vwv16,2);
1067 pstrcpy(p2,mailslot);
1068 p2 = skip_string(p2,1);
1070 memcpy(p2,buffer,len);
1073 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1076 p.port = DGRAM_PORT;
1078 p.timestamp = time(NULL);
1079 p.packet_type = DGRAM_PACKET;
1081 GetTimeOfDay(&tval);
1083 if (!send_packet(&p)) {
1084 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1092 struct timeval tval2;
1093 struct packet_struct *p_ret;
1095 GetTimeOfDay(&tval2);
1096 if (TvalDiff(&tval,&tval2) > retry_time) {
1099 if (!send_packet(&p)) {
1100 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1104 GetTimeOfDay(&tval);
1108 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1109 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1113 buf = &dgram2->data[0];
1116 if (CVAL(buf,smb_com) != SMBtrans) {
1117 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1118 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1123 len = SVAL(buf,smb_vwv11);
1124 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1127 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1132 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1133 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1134 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1136 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1137 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1138 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1144 /* Note this is safe as it is a bounded strcpy. */
1145 fstrcpy(ret_name, buf2);
1146 ret_name[sizeof(fstring)-1] = '\0';
1155 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1159 /********************************************************
1160 Get the IP address list of the PDC/BDC's of a Domain.
1161 *********************************************************/
1162 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1164 return internal_resolve_name(group, pdc_only ? 0x1B : 0x1C, ip_list, count);