0b38c4bb9a66ae68a0ee42a2efcb1ee3b15ed2f1
[samba.git] / source / nameresp.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios library routines
5    Copyright (C) Andrew Tridgell 1994-1996
6    
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.
11    
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.
16    
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.
20    
21    Module name: nameresp.c
22
23 */
24
25 #include "includes.h"
26
27 extern int ClientNMB;
28 extern int ClientDGRAM;
29
30 extern struct subnet_record *subnetlist;
31
32 extern int DEBUGLEVEL;
33
34 extern pstring scope;
35 extern struct in_addr ipzero;
36 extern struct in_addr ipgrp;
37
38 extern int num_response_packets;
39
40
41 /***************************************************************************
42   deals with an entry before it dies
43   **************************************************************************/
44 static void dead_netbios_entry(struct subnet_record *d,
45                                 struct response_record *n)
46 {
47   DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
48            inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs));
49
50   switch (n->state)
51   {
52     case NAME_QUERY_CONFIRM:
53     {
54                 if (!lp_wins_support()) return; /* only if we're a WINS server */
55
56                 if (n->num_msgs == 0)
57         {
58                         /* oops. name query had no response. check that the name is
59                            unique and then remove it from our WINS database */
60
61                         /* IMPORTANT: see query_refresh_names() */
62
63                         if ((!NAME_GROUP(n->nb_flags)))
64                         {
65                                 struct subnet_record *d1 = find_subnet(ipgrp);
66                                 if (d1)
67                                 {
68                                         /* remove the name that had been registered with us,
69                                            and we're now getting no response when challenging.
70                                            see rfc1001.txt 15.5.2
71                                          */
72                                         remove_netbios_name(d1, n->name.name, n->name.name_type,
73                                                                         REGISTER, n->send_ip);
74                                 }
75                         }
76                 }
77                 break;
78     }
79
80         case NAME_QUERY_MST_CHK:
81         {
82           /* if no response received, the master browser must have gone
83                  down on that subnet, without telling anyone. */
84
85           /* IMPORTANT: see response_netbios_packet() */
86
87           if (n->num_msgs == 0)
88                   browser_gone(n->name.name, n->send_ip);
89           break;
90         }
91
92         case NAME_RELEASE:
93         {
94           /* if no response received, it must be OK for us to release the
95                  name. nobody objected (including a potentially dead or deaf
96                  WINS server) */
97
98           /* IMPORTANT: see response_name_release() */
99
100           if (ismyip(n->send_ip))
101           {
102                 name_unregister_work(d,n->name.name,n->name.name_type);
103           }
104           if (!n->bcast)
105           {
106                  DEBUG(0,("WINS server did not respond to name release!\n"));
107          /* XXXX whoops. we have problems. must deal with this */
108           }
109           break;
110         }
111
112         case NAME_REGISTER_CHALLENGE:
113         {
114                 /* name challenge: no reply. we can reply to the person that
115                    wanted the unique name and tell them that they can have it
116                  */
117
118                 add_netbios_entry(d, n->name.name, n->name.name_type,
119                                                         n->nb_flags, GET_TTL(0), REGISTER,
120                                                         n->reply_to_ip, False, True);
121
122                 send_name_response(n->fd, n->response_id, NMB_REG,
123                                                 True, True,
124                                                 &n->name, n->nb_flags, GET_TTL(0), n->reply_to_ip);
125                 break;
126         }
127         case NAME_REGISTER:
128         {
129           /* if no response received, and we are using a broadcast registration
130                  method, it must be OK for us to register the name: nobody objected 
131                  on that subnet. if we are using a WINS server, then the WINS
132                  server must be dead or deaf.
133            */
134           if (n->bcast)
135           {
136                 /* broadcast method: implicit acceptance of the name registration
137                    by not receiving any objections. */
138
139                 /* IMPORTANT: see response_name_reg() */
140
141                 name_register_work(d,n->name.name,n->name.name_type,
142                                 n->nb_flags, n->ttl, n->send_ip, n->bcast);
143           }
144           else
145           {
146                 /* XXXX oops. this is where i wish this code could retry DGRAM
147                    packets. we directed a name registration at a WINS server, and
148                    received no response. rfc1001.txt states that after retrying,
149                    we should assume the WINS server is dead, and fall back to
150                    broadcasting. */
151                 
152                  DEBUG(1,("WINS server did not respond to name registration!\n"));
153          /* XXXX whoops. we have problems. must deal with this */
154           }
155           break;
156         }
157
158         default:
159         {
160           /* nothing to do but delete the dead expected-response structure */
161           /* this is normal. */
162           break;
163         }
164   }
165 }
166
167
168 /*******************************************************************
169   remove old name response entries
170
171   XXXX retry code needs to be added, including a retry wait period and a count
172        see name_query() and name_status() for suggested implementation.
173
174   ******************************************************************/
175 void expire_netbios_response_entries()
176 {
177   struct response_record *n;
178   struct response_record *nextn;
179   struct subnet_record *d;
180
181   for (d = subnetlist; d; d = d->next)
182    for (n = d->responselist; n; n = nextn)
183     {
184       if (n->repeat_time < time(NULL))
185           {
186                   if (n->repeat_count > 0)
187                   {
188                         /* resend the entry */
189                         initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
190                                                 n->name.name, n->name.name_type,
191                                       n->nb_flags, n->bcast, n->recurse, n->send_ip);
192
193             n->repeat_time += n->repeat_interval; /* XXXX ms needed */
194             n->repeat_count--;
195                   }
196                   else
197                   {
198                           nextn = n->next;
199
200                           dead_netbios_entry    (d,n); /* process the non-response */
201               remove_response_record(d,n); /* remove the non-response */
202
203                           continue;
204                    }
205           }
206           nextn = n->next;
207     }
208 }
209
210
211 /****************************************************************************
212   wrapper function to override a broadcast message and send it to the WINS
213   name server instead, if it exists. if wins is false, and there has been no
214   WINS server specified, the packet will NOT be sent.
215   ****************************************************************************/
216 struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
217                                 int fd,int quest_type,enum state_type state,
218                             char *name,int name_type,int nb_flags, time_t ttl,
219                             BOOL bcast,BOOL recurse,
220                                 struct in_addr send_ip, struct in_addr reply_to_ip)
221 {
222   /* XXXX note: please see rfc1001.txt section 10 for details on this
223      function: it is currently inappropriate to use this - it will do
224      for now - once there is a clarification of B, M and P nodes and
225      which one samba is supposed to be
226    */
227
228   if ((!lp_wins_support()) && (*lp_wins_server()))
229     {
230       /* samba is not a WINS server, and we are using a WINS server */
231       struct in_addr wins_ip;
232       wins_ip = *interpret_addr2(lp_wins_server());
233
234       if (!zero_ip(wins_ip))
235         {
236           bcast = False;
237           send_ip = wins_ip;
238         }
239       else
240         {
241           /* oops. smb.conf's wins server parameter MUST be a host_name 
242              or an ip_address. */
243           DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
244         }
245     }
246
247   if (zero_ip(send_ip)) return NULL;
248
249   return queue_netbios_packet(d,fd, quest_type, state, 
250                        name, name_type, nb_flags, ttl,
251                        bcast, recurse, send_ip, reply_to_ip);
252 }
253
254
255 /****************************************************************************
256   initiate a netbios name query to find someone's or someones' IP
257   this is intended to be used (not exclusively) for broadcasting to
258   master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
259   complete lists across a wide area network
260   ****************************************************************************/
261 struct response_record *queue_netbios_packet(struct subnet_record *d,
262                         int fd,int quest_type,enum state_type state,char *name,
263                         int name_type,int nb_flags, time_t ttl,
264                             BOOL bcast,BOOL recurse,
265                                 struct in_addr send_ip, struct in_addr reply_to_ip)
266 {
267   struct in_addr wins_ip = ipgrp;
268   struct response_record *n;
269   uint16 id = 0xffff;
270
271   /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
272   if (ip_equal(wins_ip, send_ip)) return NULL;
273
274   initiate_netbios_packet(&id, fd, quest_type, name, name_type,
275                                       nb_flags, bcast, recurse, send_ip);
276
277   if (id == 0xffff) return NULL;
278   
279   if ((n = make_response_queue_record(state,id,fd,
280                                                 quest_type,name,name_type,nb_flags,ttl,
281                                                 bcast,recurse,send_ip,reply_to_ip)))
282     {
283       add_response_record(d,n);
284       return n;
285     }
286    return NULL;
287 }