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 StrnCpy(name, status[i].name, 15);
187 dos_to_unix(name, True);
193 /****************************************************************************
194 Do a NetBIOS name registation to try to claim a name ...
195 ***************************************************************************/
196 BOOL name_register(int fd, const char *name, int name_type,
197 struct in_addr name_ip, int opcode,
199 struct in_addr to_ip, int *count)
203 struct packet_struct p;
204 struct packet_struct *p2;
205 struct nmb_packet *nmb = &p.packet.nmb;
206 struct in_addr register_ip;
208 DEBUG(4, ("name_register: %s as %s on %s\n", name, inet_ntoa(name_ip), inet_ntoa(to_ip)));
210 register_ip.s_addr = name_ip.s_addr; /* Fix this ... */
212 bzero((char *)&p, sizeof(p));
216 nmb->header.name_trn_id = generate_trn_id();
217 nmb->header.opcode = opcode;
218 nmb->header.response = False;
219 nmb->header.nm_flags.bcast = False;
220 nmb->header.nm_flags.recursion_available = False;
221 nmb->header.nm_flags.recursion_desired = True; /* ? */
222 nmb->header.nm_flags.trunc = False;
223 nmb->header.nm_flags.authoritative = True;
225 nmb->header.qdcount = 1;
226 nmb->header.ancount = 0;
227 nmb->header.nscount = 0;
228 nmb->header.arcount = 1;
230 make_nmb_name(&nmb->question.question_name, name, name_type);
232 nmb->question.question_type = 0x20;
233 nmb->question.question_class = 0x1;
235 /* Now, create the additional stuff for a registration request */
237 if ((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
239 DEBUG(0, ("name_register: malloc fail for additional record.\n"));
244 bzero((char *)nmb->additional, sizeof(struct res_rec));
246 nmb->additional->rr_name = nmb->question.question_name;
247 nmb->additional->rr_type = RR_TYPE_NB;
248 nmb->additional->rr_class = RR_CLASS_IN;
250 /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
251 if (nmb->header.nm_flags.bcast)
252 nmb->additional->ttl = PERMANENT_TTL;
254 nmb->additional->ttl = lp_max_ttl();
256 nmb->additional->rdlength = 6;
258 nmb->additional->rdata[0] = NB_MFLAG & 0xFF;
260 /* Set the address for the name we are registering. */
261 putip(&nmb->additional->rdata[2], ®ister_ip);
266 p.timestamp = time(NULL);
267 p.packet_type = NMB_PACKET;
271 if (!send_packet(&p))
276 if ((p2 = receive_nmb_packet(fd, 10, nmb->header.name_trn_id))) {
277 debug_nmb_packet(p2);
278 free(p2); /* No memory leaks ... */
284 /****************************************************************************
285 Do a netbios name query to find someones IP.
286 Returns an array of IP addresses or NULL if none.
287 *count will be set to the number of addresses returned.
288 ****************************************************************************/
289 struct in_addr *name_query(int fd,const char *name,int name_type,
290 BOOL bcast,BOOL recurse,
291 struct in_addr to_ip, int *count)
295 int retry_time = bcast?250:2000;
297 struct packet_struct p;
298 struct packet_struct *p2;
299 struct nmb_packet *nmb = &p.packet.nmb;
300 struct in_addr *ip_list = NULL;
302 memset((char *)&p,'\0',sizeof(p));
305 nmb->header.name_trn_id = generate_trn_id();
306 nmb->header.opcode = 0;
307 nmb->header.response = False;
308 nmb->header.nm_flags.bcast = bcast;
309 nmb->header.nm_flags.recursion_available = False;
310 nmb->header.nm_flags.recursion_desired = recurse;
311 nmb->header.nm_flags.trunc = False;
312 nmb->header.nm_flags.authoritative = False;
313 nmb->header.rcode = 0;
314 nmb->header.qdcount = 1;
315 nmb->header.ancount = 0;
316 nmb->header.nscount = 0;
317 nmb->header.arcount = 0;
319 make_nmb_name(&nmb->question.question_name,name,name_type);
321 nmb->question.question_type = 0x20;
322 nmb->question.question_class = 0x1;
327 p.timestamp = time(NULL);
328 p.packet_type = NMB_PACKET;
332 if (!send_packet(&p))
339 struct timeval tval2;
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 ip_list = (struct in_addr *)Realloc( ip_list,
405 * ( (*count) + nmb2->answers->rdlength/6 ) );
407 DEBUG(2,("Got a positive name query response from %s ( ",
409 for (i=0;i<nmb2->answers->rdlength/6;i++) {
410 putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
411 DEBUGADD(2,("%s ",inet_ntoa(ip_list[(*count)])));
421 * If we're doing a unicast lookup we only
422 * expect one reply. Don't wait the full 2
423 * seconds if we got one. JRA.
430 /* Reach here if we've timed out waiting for replies.. */
431 if( !bcast && !found )
433 /* Timed out wating for WINS server to respond. Mark it dead. */
434 wins_srv_died( to_ip );
440 /********************************************************
441 Start parsing the lmhosts file.
442 *********************************************************/
444 FILE *startlmhosts(char *fname)
446 FILE *fp = sys_fopen(fname,"r");
448 DEBUG(4,("startlmhosts: Can't open lmhosts file %s. Error was %s\n",
449 fname, strerror(errno)));
455 /********************************************************
456 Parse the next line in the lmhosts file.
457 *********************************************************/
459 BOOL getlmhostsent( FILE *fp, pstring name, int *name_type, struct in_addr *ipaddr)
463 while(!feof(fp) && !ferror(fp)) {
464 pstring ip,flags,extra;
470 if (!fgets_slash(line,sizeof(pstring),fp))
482 if (next_token(&ptr,ip ,NULL,sizeof(ip)))
484 if (next_token(&ptr,name ,NULL, sizeof(pstring)))
486 if (next_token(&ptr,flags,NULL, sizeof(flags)))
488 if (next_token(&ptr,extra,NULL, sizeof(extra)))
494 if (count > 0 && count < 2)
496 DEBUG(0,("getlmhostsent: Ill formed hosts line [%s]\n",line));
502 DEBUG(0,("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
506 DEBUG(4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip, name, flags));
508 if (strchr(flags,'G') || strchr(flags,'S'))
510 DEBUG(0,("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
514 *ipaddr = *interpret_addr2(ip);
516 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
517 then only add that name type. */
518 if((ptr = strchr(name, '#')) != NULL)
523 *name_type = (int)strtol(ptr, &endptr, 16);
525 if(!*ptr || (endptr == ptr))
527 DEBUG(0,("getlmhostsent: invalid name %s containing '#'.\n", name));
531 *(--ptr) = '\0'; /* Truncate at the '#' */
540 /********************************************************
541 Finish parsing the lmhosts file.
542 *********************************************************/
544 void endlmhosts(FILE *fp)
549 BOOL name_register_wins(const char *name, int name_type)
551 int sock, i, return_count;
552 int num_interfaces = iface_count();
553 struct in_addr sendto_ip;
556 * Do a broadcast register ...
559 if (!lp_wins_server())
562 DEBUG(4, ("name_register_wins:Registering my name %s on %s\n", name, lp_wins_server()));
564 sock = open_socket_in(SOCK_DGRAM, 0, 3,
565 interpret_addr("0.0.0.0"), True);
567 if (sock == -1) return False;
569 set_socket_options(sock, "SO_BROADCAST");
571 sendto_ip.s_addr = inet_addr(lp_wins_server());
573 if (num_interfaces > 1) {
575 for (i = 0; i < num_interfaces; i++) {
577 if (!name_register(sock, name, name_type, *iface_n_ip(i),
578 NMB_NAME_MULTIHOMED_REG_OPCODE,
579 True, sendto_ip, &return_count)) {
591 if (!name_register(sock, name, name_type, *iface_n_ip(0),
593 True, sendto_ip, &return_count)) {
608 /********************************************************
609 Resolve via "bcast" method.
610 *********************************************************/
612 BOOL name_resolve_bcast(const char *name, int name_type,
613 struct in_addr **return_ip_list, int *return_count)
616 int num_interfaces = iface_count();
618 *return_ip_list = NULL;
622 * "bcast" means do a broadcast lookup on all the local interfaces.
625 DEBUG(3,("name_resolve_bcast: Attempting broadcast lookup for name %s<0x%x>\n", name, name_type));
627 sock = open_socket_in( SOCK_DGRAM, 0, 3,
628 interpret_addr(lp_socket_address()), True );
630 if (sock == -1) return False;
632 set_socket_options(sock,"SO_BROADCAST");
634 * Lookup the name on all the interfaces, return on
635 * the first successful match.
637 for( i = num_interfaces-1; i >= 0; i--) {
638 struct in_addr sendto_ip;
639 /* Done this way to fix compiler error on IRIX 5.x */
640 sendto_ip = *iface_bcast(*iface_n_ip(i));
641 *return_ip_list = name_query(sock, name, name_type, True,
642 True, sendto_ip, return_count);
643 if(*return_ip_list != NULL) {
653 /********************************************************
654 Resolve via "wins" method.
655 *********************************************************/
657 static BOOL resolve_wins(const char *name, int name_type,
658 struct in_addr **return_iplist, int *return_count)
661 struct in_addr wins_ip;
664 *return_iplist = NULL;
668 * "wins" means do a unicast lookup to the WINS server.
669 * Ignore if there is no WINS server specified or if the
670 * WINS server is one of our interfaces (if we're being
671 * called from within nmbd - we can't do this call as we
675 DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
677 if( wins_srv_count() < 1 ) {
678 DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
682 wins_ip = wins_srv_ip();
683 wins_ismyip = ismyip(wins_ip);
685 DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
686 if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
687 sock = open_socket_in( SOCK_DGRAM, 0, 3,
688 interpret_addr(lp_socket_address()),
691 *return_iplist = name_query( sock, name,
695 if(*return_iplist != NULL) {
706 /********************************************************
707 Resolve via "lmhosts" method.
708 *********************************************************/
710 static BOOL resolve_lmhosts(const char *name, int name_type,
711 struct in_addr **return_iplist, int *return_count)
714 * "lmhosts" means parse the local lmhosts file.
720 struct in_addr return_ip;
722 *return_iplist = NULL;
725 DEBUG(3,("resolve_lmhosts: Attempting lmhosts lookup for name %s<0x%x>\n", name, name_type));
727 fp = startlmhosts( LMHOSTSFILE );
729 while (getlmhostsent(fp, lmhost_name, &name_type2, &return_ip)) {
730 if (strequal(name, lmhost_name) &&
731 ((name_type2 == -1) || (name_type == name_type2))
734 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
735 if(*return_iplist == NULL) {
736 DEBUG(3,("resolve_lmhosts: malloc fail !\n"));
739 **return_iplist = return_ip;
750 /********************************************************
751 Resolve via "hosts" method.
752 *********************************************************/
754 static BOOL resolve_hosts(const char *name,
755 struct in_addr **return_iplist, int *return_count)
758 * "host" means do a localhost, or dns lookup.
762 *return_iplist = NULL;
765 DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
767 if (((hp = Get_Hostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
768 struct in_addr return_ip;
769 putip((char *)&return_ip,(char *)hp->h_addr);
770 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
771 if(*return_iplist == NULL) {
772 DEBUG(3,("resolve_hosts: malloc fail !\n"));
775 **return_iplist = return_ip;
782 /********************************************************
783 Internal interface to resolve a name into an IP address.
784 Use this function if the string is either an IP address, DNS
785 or host name or NetBIOS name. This uses the name switch in the
786 smb.conf to determine the order of name resolution.
787 *********************************************************/
789 static BOOL internal_resolve_name(const char *name, int name_type,
790 struct in_addr **return_iplist, int *return_count)
792 pstring name_resolve_list;
795 BOOL allones = (strcmp(name,"255.255.255.255") == 0);
796 BOOL allzeros = (strcmp(name,"0.0.0.0") == 0);
797 BOOL is_address = is_ipaddress(name);
798 *return_iplist = NULL;
801 if (allzeros || allones || is_address) {
802 *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr));
803 if(*return_iplist == NULL) {
804 DEBUG(3,("internal_resolve_name: malloc fail !\n"));
808 /* if it's in the form of an IP address then get the lib to interpret it */
809 (*return_iplist)->s_addr = inet_addr(name);
811 (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0;
817 pstrcpy(name_resolve_list, lp_name_resolve_order());
818 ptr = name_resolve_list;
822 while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
823 if((strequal(tok, "host") || strequal(tok, "hosts"))) {
824 if (name_type == 0x20 && resolve_hosts(name, return_iplist, return_count)) {
827 } else if(strequal( tok, "lmhosts")) {
828 if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
831 } else if(strequal( tok, "wins")) {
832 /* don't resolve 1D via WINS */
833 if (name_type != 0x1D &&
834 resolve_wins(name, name_type, return_iplist, return_count)) {
837 } else if(strequal( tok, "bcast")) {
838 if (name_resolve_bcast(name, name_type, return_iplist, return_count)) {
842 DEBUG(0,("resolve_name: unknown name switch type %s\n", tok));
846 if((*return_iplist) != NULL) {
847 free((char *)(*return_iplist));
848 *return_iplist = NULL;
853 /********************************************************
854 Internal interface to resolve a name into one IP address.
855 Use this function if the string is either an IP address, DNS
856 or host name or NetBIOS name. This uses the name switch in the
857 smb.conf to determine the order of name resolution.
858 *********************************************************/
860 BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
862 struct in_addr *ip_list = NULL;
865 if(internal_resolve_name(name, name_type, &ip_list, &count)) {
866 *return_ip = ip_list[0];
867 free((char *)ip_list);
871 free((char *)ip_list);
876 /********************************************************
877 resolve a name of format \\server_name or \\ipaddress
878 into a name. also, cut the \\ from the front for us.
879 *********************************************************/
881 BOOL resolve_srv_name(const char* srv_name, fstring dest_host,
885 const char *sv_name = srv_name;
887 DEBUG(10,("resolve_srv_name: %s\n", srv_name));
889 if (srv_name == NULL || strequal("\\\\.", srv_name))
891 extern pstring global_myname;
892 fstrcpy(dest_host, global_myname);
893 ip = interpret_addr2("127.0.0.1");
897 if (strnequal("\\\\", srv_name, 2))
899 sv_name = &srv_name[2];
902 fstrcpy(dest_host, sv_name);
903 /* treat the '*' name specially - it is a magic name for the PDC */
904 if (strcmp(dest_host,"*") == 0) {
905 extern pstring global_myname;
906 ret = resolve_name(lp_workgroup(), ip, 0x1B);
907 lookup_pdc_name(global_myname, lp_workgroup(), ip, dest_host);
909 ret = resolve_name(dest_host, ip, 0x20);
912 if (is_ipaddress(dest_host))
914 fstrcpy(dest_host, "*SMBSERVER");
921 /********************************************************
922 Find the IP address of the master browser or DMB for a workgroup.
923 *********************************************************/
925 BOOL find_master_ip(char *group, struct in_addr *master_ip)
927 struct in_addr *ip_list = NULL;
930 if (internal_resolve_name(group, 0x1D, &ip_list, &count)) {
931 *master_ip = ip_list[0];
932 free((char *)ip_list);
935 if(internal_resolve_name(group, 0x1B, &ip_list, &count)) {
936 *master_ip = ip_list[0];
937 free((char *)ip_list);
942 free((char *)ip_list);
946 /********************************************************
947 Lookup a PDC name given a Domain name and IP address.
948 *********************************************************/
950 BOOL lookup_pdc_name(const char *srcname, const char *domain, struct in_addr *pdc_ip, char *ret_name)
952 #if !defined(I_HATE_WINDOWS_REPLY_CODE)
958 * Due to the fact win WinNT *sucks* we must do a node status
964 ret = name_status_find(0x20,*pdc_ip,pdc_name);
966 if(ret && *pdc_name) {
967 fstrcpy(ret_name, pdc_name);
973 #else /* defined(I_HATE_WINDOWS_REPLY_CODE) */
975 JRA - This code is broken with BDC rollover - we need to do a full
976 NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all...
979 int retry_time = 2000;
981 struct packet_struct p;
982 struct dgram_packet *dgram = &p.packet.dgram;
986 struct sockaddr_in sock_name;
987 int sock_len = sizeof(sock_name);
988 const char *mailslot = NET_LOGON_MAILSLOT;
992 int dgm_id = generate_trn_id();
993 int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True );
998 /* Find out the transient UDP port we have been allocated. */
999 if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) {
1000 DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n",
1007 * Create the request data.
1010 memset(buffer,'\0',sizeof(buffer));
1012 SSVAL(bufp,0,QUERYFORPDC);
1014 fstrcpy(bufp,srcname);
1015 bufp += (strlen(bufp) + 1);
1016 slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id);
1017 mailslot_name = bufp;
1018 bufp += (strlen(bufp) + 1);
1019 bufp = ALIGN2(bufp, buffer);
1020 bufp += dos_PutUniCode(bufp, srcname, sizeof(buffer) - (bufp - buffer) - 1, True);
1022 SSVAL(bufp,4,0xFFFF);
1023 SSVAL(bufp,6,0xFFFF);
1025 len = PTR_DIFF(bufp,buffer);
1027 memset((char *)&p,'\0',sizeof(p));
1029 /* DIRECT GROUP or UNIQUE datagram. */
1030 dgram->header.msg_type = 0x10;
1031 dgram->header.flags.node_type = M_NODE;
1032 dgram->header.flags.first = True;
1033 dgram->header.flags.more = False;
1034 dgram->header.dgm_id = dgm_id;
1035 dgram->header.source_ip = *iface_ip(*pdc_ip);
1036 dgram->header.source_port = ntohs(sock_name.sin_port);
1037 dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
1038 dgram->header.packet_offset = 0;
1040 make_nmb_name(&dgram->source_name,srcname,0);
1041 make_nmb_name(&dgram->dest_name,domain,0x1C);
1043 ptr = &dgram->data[0];
1045 /* Setup the smb part. */
1046 ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
1048 set_message(ptr,17,17 + len,True);
1051 CVAL(ptr,smb_com) = SMBtrans;
1052 SSVAL(ptr,smb_vwv1,len);
1053 SSVAL(ptr,smb_vwv11,len);
1054 SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
1055 SSVAL(ptr,smb_vwv13,3);
1056 SSVAL(ptr,smb_vwv14,1);
1057 SSVAL(ptr,smb_vwv15,1);
1058 SSVAL(ptr,smb_vwv16,2);
1060 pstrcpy(p2,mailslot);
1061 p2 = skip_string(p2,1);
1063 memcpy(p2,buffer,len);
1066 dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
1069 p.port = DGRAM_PORT;
1071 p.timestamp = time(NULL);
1072 p.packet_type = DGRAM_PACKET;
1074 GetTimeOfDay(&tval);
1076 if (!send_packet(&p)) {
1077 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1085 struct timeval tval2;
1086 struct packet_struct *p_ret;
1088 GetTimeOfDay(&tval2);
1089 if (TvalDiff(&tval,&tval2) > retry_time) {
1092 if (!send_packet(&p)) {
1093 DEBUG(0,("lookup_pdc_name: send_packet failed.\n"));
1097 GetTimeOfDay(&tval);
1101 if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) {
1102 struct dgram_packet *dgram2 = &p_ret->packet.dgram;
1106 buf = &dgram2->data[0];
1109 if (CVAL(buf,smb_com) != SMBtrans) {
1110 DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int)
1111 CVAL(buf,smb_com), (unsigned int)SMBtrans ));
1116 len = SVAL(buf,smb_vwv11);
1117 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1120 DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len ));
1125 DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n",
1126 nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name),
1127 inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len));
1129 if(SVAL(buf2,0) != QUERYFORPDC_R) {
1130 DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n",
1131 (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R ));
1137 /* Note this is safe as it is a bounded strcpy. */
1138 fstrcpy(ret_name, buf2);
1139 ret_name[sizeof(fstring)-1] = '\0';
1148 #endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */
1152 /********************************************************
1153 Get the IP address list of the PDC/BDC's of a Domain.
1154 *********************************************************/
1155 BOOL get_dc_list(BOOL pdc_only, char *group, struct in_addr **ip_list, int *count)
1157 return internal_resolve_name(group, pdc_only ? 0x1B : 0x1C, ip_list, count);