2 Unix SMB/Netbios implementation.
6 Copyright (C) Andrew Tridgell 1994-1998
9 The Free Software Foundation, Inc.
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 const char *unix_error_string (int error_num
);
31 extern int DEBUGLEVEL
;
33 /* nmbd.c sets this to True. */
34 const BOOL global_in_nmbd
= False
;
36 /****************************************************************************
37 interpret a node status response
38 ****************************************************************************/
40 _interpret_node_status (char *p
, char *master
, char *rname
)
42 int numnames
= CVAL (p
, 0);
43 DEBUG (1, ("received %d names\n", numnames
));
58 StrnCpy (qname
, p
, 15);
62 fstrcat (flags
, (p
[0] & 0x80) ? "<GROUP> " : " ");
63 if ((p
[0] & 0x60) == 0x00)
64 fstrcat (flags
, "B ");
65 if ((p
[0] & 0x60) == 0x20)
66 fstrcat (flags
, "P ");
67 if ((p
[0] & 0x60) == 0x40)
68 fstrcat (flags
, "M ");
69 if ((p
[0] & 0x60) == 0x60)
70 fstrcat (flags
, "H ");
72 fstrcat (flags
, "<DEREGISTERING> ");
74 fstrcat (flags
, "<CONFLICT> ");
76 fstrcat (flags
, "<ACTIVE> ");
78 fstrcat (flags
, "<PERMANENT> ");
80 if (master
&& !*master
&& type
== 0x1d)
82 StrnCpy (master
, qname
, 15);
83 trim_string (master
, NULL
, " ");
86 if (rname
&& !*rname
&& type
== 0x20 && !(p
[0] & 0x80))
88 StrnCpy (rname
, qname
, 15);
89 trim_string (rname
, NULL
, " ");
92 for (i
= strlen (qname
); --i
>= 0;)
94 if (!isprint ((int) qname
[i
]))
97 DEBUG (1, ("\t%-15s <%02x> - %s\n", qname
, type
, flags
));
100 DEBUG (1, ("num_good_sends=%d num_good_receives=%d\n", IVAL (p
, 20), IVAL (p
, 24)));
104 /****************************************************************************
105 do a netbios name query to find someones IP
106 returns an array of IP addresses or NULL if none
107 *count will be set to the number of addresses returned
108 ****************************************************************************/
110 name_query (int fd
, const char *name
, int name_type
, BOOL bcast
, BOOL recurse
,
111 struct in_addr to_ip
, int *count
, void (*fn
) (struct packet_struct
*))
115 int retry_time
= bcast
? 250 : 2000;
117 struct packet_struct p
;
118 struct packet_struct
*p2
;
119 struct nmb_packet
*nmb
= &p
.packet
.nmb
;
120 static int name_trn_id
= 0;
121 struct in_addr
*ip_list
= NULL
;
123 memset ((char *) &p
, '\0', sizeof (p
));
127 name_trn_id
= ((unsigned) time (NULL
) % (unsigned) 0x7FFF) +
128 ((unsigned) getpid () % (unsigned) 100);
129 name_trn_id
= (name_trn_id
+ 1) % (unsigned) 0x7FFF;
131 nmb
->header
.name_trn_id
= name_trn_id
;
132 nmb
->header
.opcode
= 0;
133 nmb
->header
.response
= False
;
134 nmb
->header
.nm_flags
.bcast
= bcast
;
135 nmb
->header
.nm_flags
.recursion_available
= False
;
136 nmb
->header
.nm_flags
.recursion_desired
= recurse
;
137 nmb
->header
.nm_flags
.trunc
= False
;
138 nmb
->header
.nm_flags
.authoritative
= False
;
139 nmb
->header
.rcode
= 0;
140 nmb
->header
.qdcount
= 1;
141 nmb
->header
.ancount
= 0;
142 nmb
->header
.nscount
= 0;
143 nmb
->header
.arcount
= 0;
145 make_nmb_name (&nmb
->question
.question_name
, name
, name_type
);
147 nmb
->question
.question_type
= 0x20;
148 nmb
->question
.question_class
= 0x1;
153 p
.timestamp
= time (NULL
);
154 p
.packet_type
= NMB_PACKET
;
156 GetTimeOfDay (&tval
);
158 if (!send_packet (&p
))
165 struct timeval tval2
;
166 GetTimeOfDay (&tval2
);
167 if (TvalDiff (&tval
, &tval2
) > retry_time
)
171 if (!found
&& !send_packet (&p
))
173 GetTimeOfDay (&tval
);
177 if ((p2
= receive_packet (fd
, NMB_PACKET
, 90)))
179 struct nmb_packet
*nmb2
= &p2
->packet
.nmb
;
180 debug_nmb_packet (p2
);
182 if (nmb
->header
.name_trn_id
!= nmb2
->header
.name_trn_id
|| !nmb2
->header
.response
)
185 * Its not for us - maybe deal with it later
186 * (put it on the queue?).
195 if (nmb2
->header
.opcode
!= 0 ||
196 nmb2
->header
.nm_flags
.bcast
|| nmb2
->header
.rcode
|| !nmb2
->header
.ancount
)
199 * XXXX what do we do with this? Could be a redirect, but
200 * we'll discard it for the moment.
206 ip_list
= (struct in_addr
*) Realloc (ip_list
, sizeof (ip_list
[0]) *
207 ((*count
) + nmb2
->answers
->rdlength
/ 6));
210 DEBUG (fn
? 3 : 2, ("Got a positive name query response from %s ( ",
211 inet_ntoa (p2
->ip
)));
212 for (i
= 0; i
< nmb2
->answers
->rdlength
/ 6; i
++)
214 putip ((char *) &ip_list
[(*count
)], &nmb2
->answers
->rdata
[2 + i
* 6]);
215 DEBUG (fn
? 3 : 2, ("%s ", inet_ntoa (ip_list
[(*count
)])));
218 DEBUG (fn
? 3 : 2, (")\n"));
228 * If we're doing a unicast lookup we only
229 * expect one reply. Don't wait the full 2
230 * seconds if we got one. JRA.
240 /********************************************************
241 Start parsing the lmhosts file.
242 *********************************************************/
245 startlmhosts (const char *fname
)
247 FILE *fp
= sys_fopen (fname
, "r");
250 DEBUG (4, ("startlmhosts: Cannot open lmhosts file %s. Error was %s\n",
251 fname
, unix_error_string (errno
)));
257 /********************************************************
258 Parse the next line in the lmhosts file.
259 *********************************************************/
261 getlmhostsent (FILE * fp
, pstring name
, int *name_type
, struct in_addr
* ipaddr
)
265 while (!feof (fp
) && !ferror (fp
))
267 pstring ip
, flags
, extra
;
273 if (!fgets_slash (line
, sizeof (pstring
), fp
))
285 if (next_token (&ptr
, ip
, NULL
, sizeof (ip
)))
287 if (next_token (&ptr
, name
, NULL
, sizeof (pstring
)))
289 if (next_token (&ptr
, flags
, NULL
, sizeof (flags
)))
291 if (next_token (&ptr
, extra
, NULL
, sizeof (extra
)))
297 if (count
> 0 && count
< 2)
299 DEBUG (0, ("getlmhostsent: Ill formed hosts line [%s]\n", line
));
305 DEBUG (0, ("getlmhostsent: too many columns in lmhosts file (obsolete syntax)\n"));
309 DEBUG (4, ("getlmhostsent: lmhost entry: %s %s %s\n", ip
, name
, flags
));
311 if (strchr (flags
, 'G') || strchr (flags
, 'S'))
313 DEBUG (0, ("getlmhostsent: group flag in lmhosts ignored (obsolete)\n"));
317 *ipaddr
= *interpret_addr2 (ip
);
319 /* Extra feature. If the name ends in '#XX', where XX is a hex number,
320 then only add that name type. */
321 if ((ptr
= strchr (name
, '#')) != NULL
)
326 *name_type
= (int) strtol (ptr
, &endptr
, 16);
328 if (!*ptr
|| (endptr
== ptr
))
330 DEBUG (0, ("getlmhostsent: invalid name %s containing '#'.\n", name
));
334 *(--ptr
) = '\0'; /* Truncate at the '#' */
343 /********************************************************
344 Finish parsing the lmhosts file.
345 *********************************************************/
348 endlmhosts (FILE * fp
)
353 /********************************************************
354 resolve via "bcast" method
355 *********************************************************/
357 resolve_bcast (const char *name
, struct in_addr
*return_ip
, int name_type
)
362 * "bcast" means do a broadcast lookup on all the local interfaces.
365 DEBUG (3, ("resolve_name: Attempting broadcast lookup for name %s<0x%x>\n", name
, name_type
));
367 sock
= open_socket_in (SOCK_DGRAM
, 0, 3, interpret_addr (lp_socket_address ()), True
);
371 struct in_addr
*iplist
= NULL
;
373 int num_interfaces
= iface_count ();
374 static char so_broadcast
[] = "SO_BROADCAST";
375 set_socket_options (sock
, so_broadcast
);
377 * Lookup the name on all the interfaces, return on
378 * the first successful match.
380 for (i
= 0; i
< num_interfaces
; i
++)
382 struct in_addr sendto_ip
;
383 /* Done this way to fix compiler error on IRIX 5.x */
384 sendto_ip
= *iface_bcast (*iface_n_ip (i
));
385 iplist
= name_query (sock
, name
, name_type
, True
, True
, sendto_ip
, &count
, NULL
);
388 *return_ip
= iplist
[0];
389 free ((char *) iplist
);
402 /********************************************************
403 resolve via "wins" method
404 *********************************************************/
406 resolve_wins (const char *name
, struct in_addr
*return_ip
, int name_type
)
409 struct in_addr wins_ip
;
413 * "wins" means do a unicast lookup to the WINS server.
414 * Ignore if there is no WINS server specified or if the
415 * WINS server is one of our interfaces (if we're being
416 * called from within nmbd - we can't do this call as we
420 DEBUG (3, ("resolve_name: Attempting wins lookup for name %s<0x%x>\n", name
, name_type
));
422 if (!*lp_wins_server ())
424 DEBUG (3, ("resolve_name: WINS server resolution selected and no WINS server present.\n"));
428 wins_ip
= *interpret_addr2 (lp_wins_server ());
429 wins_ismyip
= ismyip (wins_ip
);
431 if ((wins_ismyip
&& !global_in_nmbd
) || !wins_ismyip
)
433 sock
= open_socket_in (SOCK_DGRAM
, 0, 3, interpret_addr (lp_socket_address ()), True
);
437 struct in_addr
*iplist
= NULL
;
439 iplist
= name_query (sock
, name
, name_type
, False
, True
, wins_ip
, &count
, NULL
);
442 *return_ip
= iplist
[0];
443 free ((char *) iplist
);
455 /********************************************************
456 resolve via "lmhosts" method
457 *********************************************************/
459 resolve_lmhosts (const char *name
, struct in_addr
*return_ip
, int name_type
)
462 * "lmhosts" means parse the local lmhosts file.
469 DEBUG (3, ("resolve_name: Attempting lmhosts lookup for name %s<0x%x>\n", name
, name_type
));
471 fp
= startlmhosts (LMHOSTSFILE
);
474 while (getlmhostsent (fp
, lmhost_name
, &name_type2
, return_ip
))
476 if (strequal (name
, lmhost_name
) && ((name_type2
== -1) || (name_type
== name_type2
)))
488 /********************************************************
489 resolve via "hosts" method
490 *********************************************************/
492 resolve_hosts (const char *name
, struct in_addr
*return_ip
)
495 * "host" means do a localhost, or dns lookup.
499 DEBUG (3, ("resolve_name: Attempting host lookup for name %s<0x20>\n", name
));
501 if (((hp
= Get_Hostbyname (name
)) != NULL
) && (hp
->h_addr
!= NULL
))
503 putip ((char *) return_ip
, (char *) hp
->h_addr
);
510 /********************************************************
511 Resolve a name into an IP address. Use this function if
512 the string is either an IP address, DNS or host name
513 or NetBIOS name. This uses the name switch in the
514 smb.conf to determine the order of name resolution.
515 *********************************************************/
517 resolve_name (const char *name
, struct in_addr
* return_ip
, int name_type
)
520 BOOL pure_address
= True
;
521 pstring name_resolve_list
;
525 if (strcmp (name
, "0.0.0.0") == 0)
527 return_ip
->s_addr
= 0;
530 if (strcmp (name
, "255.255.255.255") == 0)
532 return_ip
->s_addr
= 0xFFFFFFFF;
536 for (i
= 0; pure_address
&& name
[i
]; i
++)
537 if (!(isdigit ((int) name
[i
]) || name
[i
] == '.'))
538 pure_address
= False
;
540 /* if it's in the form of an IP address then get the lib to interpret it */
543 return_ip
->s_addr
= inet_addr (name
);
547 pstrcpy (name_resolve_list
, lp_name_resolve_order ());
548 if (name_resolve_list
== NULL
|| *name_resolve_list
== '\0')
549 pstrcpy (name_resolve_list
, "host");
550 ptr
= name_resolve_list
;
552 while (next_token (&ptr
, tok
, LIST_SEP
, sizeof (tok
)))
554 if ((strequal (tok
, "host") || strequal (tok
, "hosts")))
556 if (name_type
== 0x20 && resolve_hosts (name
, return_ip
))
561 else if (strequal (tok
, "lmhosts"))
563 if (resolve_lmhosts (name
, return_ip
, name_type
))
568 else if (strequal (tok
, "wins"))
570 /* don't resolve 1D via WINS */
571 if (name_type
!= 0x1D && resolve_wins (name
, return_ip
, name_type
))
576 else if (strequal (tok
, "bcast"))
578 if (resolve_bcast (name
, return_ip
, name_type
))
585 DEBUG (0, ("resolve_name: unknown name switch type %s\n", tok
));
594 /********************************************************
595 find the IP address of the master browser or DMB for a workgroup
596 *********************************************************/
598 find_master_ip (char *group
, struct in_addr
* master_ip
)
600 if (resolve_name (group
, master_ip
, 0x1D))
603 return resolve_name (group
, master_ip
, 0x1B);