2 Unix SMB/Netbios implementation.
4 NBT netbios library routines
5 Copyright (C) Andrew Tridgell 1994-1996
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.
21 Module name: nameresp.c
28 extern int ClientDGRAM;
30 extern struct subnet_record *subnetlist;
32 extern int DEBUGLEVEL;
35 extern struct in_addr ipzero;
36 extern struct in_addr ipgrp;
41 /***************************************************************************
42 updates the unique transaction identifier
43 **************************************************************************/
44 void update_name_trn_id(void)
48 name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
50 name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
54 /***************************************************************************
55 deals with an entry before it dies
56 **************************************************************************/
57 static void dead_netbios_entry(struct subnet_record *d,
58 struct response_record *n)
60 DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
61 inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs));
63 debug_state_type(n->state);
67 case NAME_QUERY_CONFIRM:
69 if (!lp_wins_support()) return; /* only if we're a WINS server */
73 /* oops. name query had no response. check that the name is
74 unique and then remove it from our WINS database */
76 /* IMPORTANT: see query_refresh_names() */
78 if ((!NAME_GROUP(n->reply.nb_flags)))
80 struct subnet_record *d1 = find_subnet(ipgrp);
83 /* remove the name that had been registered with us,
84 and we're now getting no response when challenging.
85 see rfc1001.txt 15.5.2
87 remove_netbios_name(d1, n->name.name, n->name.name_type,
88 REGISTER, n->send_ip);
95 case NAME_QUERY_MST_CHK:
97 /* if no response received, the master browser must have gone
98 down on that subnet, without telling anyone. */
100 /* IMPORTANT: see response_netbios_packet() */
102 if (n->num_msgs == 0)
103 browser_gone(n->name.name, n->send_ip);
109 /* if no response received, it must be OK for us to release the
110 name. nobody objected (including a potentially dead or deaf
113 /* IMPORTANT: see response_name_release() */
115 if (ismyip(n->send_ip))
117 name_unregister_work(d,n->name.name,n->name.name_type);
121 DEBUG(0,("WINS server did not respond to name release!\n"));
122 /* XXXX whoops. we have problems. must deal with this */
127 case NAME_REGISTER_CHALLENGE:
129 /* name challenge: no reply. we can reply to the person that
130 wanted the unique name and tell them that they can have it
133 add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name,
134 n->reply.nb_flags, GET_TTL(0),
135 n->reply.ip, False, n->reply.ip);
139 DEBUG(1,("WINS server did not respond to name registration!\n"));
140 /* XXXX whoops. we have problems. must deal with this */
147 /* if no response received, and we are using a broadcast registration
148 method, it must be OK for us to register the name: nobody objected
149 on that subnet. if we are using a WINS server, then the WINS
150 server must be dead or deaf.
154 /* broadcast method: implicit acceptance of the name registration
155 by not receiving any objections. */
157 /* IMPORTANT: see response_name_reg() */
159 name_register_work(d,n->token,n->name.name,n->name.name_type,
160 &n->reply, n->ttl, n->reply.ip, n->bcast);
164 /* received no response. rfc1001.txt states that after retrying,
165 we should assume the WINS server is dead, and fall back to
166 broadcasting (see bits about M nodes: can't find any right
169 DEBUG(1,("WINS server did not respond to name registration!\n"));
170 /* XXXX whoops. we have problems. must deal with this */
177 /* nothing to do but delete the dead expected-response structure */
178 /* this is normal. */
185 /*******************************************************************
186 remove old name response entries
188 XXXX retry code needs to be added, including a retry wait period and a count
189 see name_query() and name_status() for suggested implementation.
191 ******************************************************************/
192 void expire_netbios_response_entries()
194 struct subnet_record *d;
196 for (d = subnetlist; d; d = d->next)
198 struct response_record *n, *nextn;
200 for (n = d->responselist; n; n = nextn)
204 if (n->repeat_time <= time(NULL))
206 if (n->repeat_count > 0)
208 /* resend the entry */
209 initiate_netbios_packet(n->response_id, n->fd, n->quest_type,
210 n->name.name, n->name.name_type,
211 n->reply.nb_flags, n->bcast, n->recurse, n->send_ip);
213 n->repeat_time += n->repeat_interval; /* XXXX ms needed */
219 DEBUG(4,("timeout response %d for %s %s\n",
220 n->response_id, namestr(&n->name),
221 inet_ntoa(n->send_ip)));
223 dead_netbios_entry (d,n); /* process the non-response */
224 remove_response_record(d,n); /* remove the non-response */
234 /****************************************************************************
235 wrapper function to override a broadcast message and send it to the WINS
236 name server instead, if it exists. if wins is false, and there has been no
237 WINS server specified, the packet will NOT be sent.
238 ****************************************************************************/
239 void queue_netbios_pkt_wins(struct subnet_record *d,
240 int fd,int quest_type,enum state_type state,
241 int token, char *name,int name_type,int nb_flags, time_t ttl,
242 int server_type, char *my_name, char *my_comment,
243 BOOL bcast,BOOL recurse,
244 struct in_addr send_ip, struct in_addr reply_to_ip)
246 /* XXXX note: please see rfc1001.txt section 10 for details on this
247 function: it is currently inappropriate to use this - it will do
248 for now - once there is a clarification of B, M and P nodes and
249 which one samba is supposed to be
252 if ((!lp_wins_support()) && (*lp_wins_server()))
254 /* samba is not a WINS server, and we are using a WINS server */
255 struct in_addr wins_ip;
256 wins_ip = *interpret_addr2(lp_wins_server());
258 if (!zero_ip(wins_ip))
265 /* oops. smb.conf's wins server parameter MUST be a host_name
267 DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
271 if (zero_ip(send_ip))
273 /* doing a netbios query to samba as a WINS server, internally */
274 if (lp_wins_support())
276 DEBUG(4,("queue netbios packet with ourselves...\n"));
285 queue_netbios_packet(d,fd, quest_type, state,
286 token, name, name_type, nb_flags, ttl,
287 server_type,my_name,my_comment,
288 bcast, recurse, send_ip, reply_to_ip);
292 /****************************************************************************
293 initiate a netbios name query to find someone's or someones' IP
294 this is intended to be used (not exclusively) for broadcasting to
295 master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
296 complete lists across a wide area network
297 ****************************************************************************/
298 void queue_netbios_packet(struct subnet_record *d,
299 int fd,int quest_type,enum state_type state,
300 int token, char *name, int name_type,int nb_flags, time_t ttl,
301 int server_type, char *my_name, char *my_comment,
302 BOOL bcast,BOOL recurse,
303 struct in_addr send_ip, struct in_addr reply_to_ip)
305 struct in_addr wins_ip = ipgrp;
306 struct response_record *n;
308 /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
309 if (ip_equal(wins_ip, send_ip)) return;
311 update_name_trn_id();
313 /* queue the response expected because if we do a query with an ip
314 of zero, we are expecting to hear from ourself immediately */
315 if ((n = make_response_queue_record(state, name_trn_id, fd, quest_type,
316 token, name, name_type, nb_flags, ttl,
317 server_type, my_name, my_comment,
318 bcast, recurse, send_ip, reply_to_ip)))
320 add_response_record(d,n);
323 if (!initiate_netbios_packet(name_trn_id, fd, quest_type, name, name_type,
324 nb_flags, bcast, recurse, send_ip))
326 /* packet wasn't sent - not expecting a response */
327 DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
328 remove_response_record(d, n);