~vcs-imports/samba/main

« back to all changes in this revision

Viewing changes to source/nmbd/nmbd_incomingrequests.c

  • Committer: jerry
  • Date: 2006-07-14 21:48:39 UTC
  • Revision ID: vcs-imports@canonical.com-20060714214839-586d8c489a8fcead
gutting trunk to move to svn:externals

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Unix SMB/CIFS implementation.
3
 
   NBT netbios routines and daemon - version 2
4
 
   Copyright (C) Andrew Tridgell 1994-1998
5
 
   Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6
 
   Copyright (C) Jeremy Allison 1994-2003
7
 
   
8
 
   This program is free software; you can redistribute it and/or modify
9
 
   it under the terms of the GNU General Public License as published by
10
 
   the Free Software Foundation; either version 2 of the License, or
11
 
   (at your option) any later version.
12
 
   
13
 
   This program is distributed in the hope that it will be useful,
14
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
   GNU General Public License for more details.
17
 
   
18
 
   You should have received a copy of the GNU General Public License
19
 
   along with this program; if not, write to the Free Software
20
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
 
   
22
 
   This file contains all the code to process NetBIOS requests coming
23
 
   in on port 137. It does not deal with the code needed to service
24
 
   WINS server requests, but only broadcast and unicast requests.
25
 
 
26
 
*/
27
 
 
28
 
#include "includes.h"
29
 
 
30
 
/****************************************************************************
31
 
Send a name release response.
32
 
**************************************************************************/
33
 
 
34
 
static void send_name_release_response(int rcode, struct packet_struct *p)
35
 
{
36
 
        struct nmb_packet *nmb = &p->packet.nmb;
37
 
        char rdata[6];
38
 
 
39
 
        memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
40
 
  
41
 
        reply_netbios_packet(p,                       /* Packet to reply to. */
42
 
                        rcode,                        /* Result code. */
43
 
                        NMB_REL,                      /* nmbd type code. */
44
 
                        NMB_NAME_RELEASE_OPCODE,      /* opcode. */
45
 
                        0,                            /* ttl. */
46
 
                        rdata,                        /* data to send. */
47
 
                        6);                           /* data length. */
48
 
}
49
 
 
50
 
/****************************************************************************
51
 
Process a name release packet on a broadcast subnet.
52
 
Ignore it if it's not one of our names.
53
 
****************************************************************************/
54
 
 
55
 
void process_name_release_request(struct subnet_record *subrec, 
56
 
                                  struct packet_struct *p)
57
 
{
58
 
        struct nmb_packet *nmb = &p->packet.nmb;
59
 
        struct in_addr owner_ip;
60
 
        struct nmb_name *question = &nmb->question.question_name;
61
 
        unstring qname;
62
 
        BOOL bcast = nmb->header.nm_flags.bcast;
63
 
        uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
64
 
        BOOL group = (nb_flags & NB_GROUP) ? True : False;
65
 
        struct name_record *namerec;
66
 
        int rcode = 0;
67
 
  
68
 
        putip((char *)&owner_ip,&nmb->additional->rdata[2]);  
69
 
  
70
 
        if(!bcast) {
71
 
                /* We should only get broadcast name release packets here.
72
 
                   Anyone trying to release unicast should be going to a WINS
73
 
                   server. If the code gets here, then either we are not a wins
74
 
                   server and they sent it anyway, or we are a WINS server and
75
 
                   the request was malformed. Either way, log an error here.
76
 
                   and send an error reply back.
77
 
                */
78
 
                DEBUG(0,("process_name_release_request: unicast name release request \
79
 
received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
80
 
                        nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));      
81
 
 
82
 
                send_name_release_response(FMT_ERR, p);
83
 
                return;
84
 
        }
85
 
 
86
 
        DEBUG(3,("process_name_release_request: Name release on name %s, \
87
 
subnet %s from owner IP %s\n",
88
 
                nmb_namestr(&nmb->question.question_name),
89
 
                subrec->subnet_name, inet_ntoa(owner_ip)));
90
 
  
91
 
        /* If someone is releasing a broadcast group name, just ignore it. */
92
 
        if( group && !ismyip(owner_ip) )
93
 
                return;
94
 
 
95
 
        /*
96
 
         * Code to work around a bug in FTP OnNet software NBT implementation.
97
 
         * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
98
 
         * names and *don't set the group bit* !!!!!
99
 
         */
100
 
 
101
 
        pull_ascii_nstring(qname, sizeof(qname), question->name);
102
 
        if( !group && !ismyip(owner_ip) && strequal(qname, lp_workgroup()) && 
103
 
                        ((question->name_type == 0x0) || (question->name_type == 0x1e))) {
104
 
                DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
105
 
group release name %s from IP %s on subnet %s with no group bit set.\n",
106
 
                        nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
107
 
                return;
108
 
        }
109
 
 
110
 
        namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
111
 
 
112
 
        /* We only care about someone trying to release one of our names. */
113
 
        if( namerec && ( (namerec->data.source == SELF_NAME)
114
 
                        || (namerec->data.source == PERMANENT_NAME) ) ) {
115
 
                rcode = ACT_ERR;
116
 
                DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
117
 
on subnet %s being rejected as it is one of our names.\n", 
118
 
                nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
119
 
        }
120
 
 
121
 
        if(rcode == 0)
122
 
                return;
123
 
 
124
 
        /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
125
 
        send_name_release_response(rcode, p);
126
 
}
127
 
 
128
 
/****************************************************************************
129
 
Send a name registration response.
130
 
**************************************************************************/
131
 
 
132
 
static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
133
 
{
134
 
        struct nmb_packet *nmb = &p->packet.nmb;
135
 
        char rdata[6];
136
 
 
137
 
        memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
138
 
  
139
 
        reply_netbios_packet(p,                                /* Packet to reply to. */
140
 
                                rcode,                         /* Result code. */
141
 
                                NMB_REG,                       /* nmbd type code. */
142
 
                                NMB_NAME_REG_OPCODE,           /* opcode. */
143
 
                                ttl,                           /* ttl. */
144
 
                                rdata,                         /* data to send. */
145
 
                                6);                            /* data length. */
146
 
}
147
 
 
148
 
/****************************************************************************
149
 
Process a name refresh request on a broadcast subnet.
150
 
**************************************************************************/
151
 
     
152
 
void process_name_refresh_request(struct subnet_record *subrec,
153
 
                                  struct packet_struct *p)
154
 
{    
155
 
        struct nmb_packet *nmb = &p->packet.nmb;
156
 
        struct nmb_name *question = &nmb->question.question_name;
157
 
        BOOL bcast = nmb->header.nm_flags.bcast;
158
 
        struct in_addr from_ip;
159
 
  
160
 
        putip((char *)&from_ip,&nmb->additional->rdata[2]);
161
 
 
162
 
        if(!bcast) { 
163
 
                /* We should only get broadcast name refresh packets here.
164
 
                   Anyone trying to refresh unicast should be going to a WINS
165
 
                   server. If the code gets here, then either we are not a wins
166
 
                   server and they sent it anyway, or we are a WINS server and
167
 
                   the request was malformed. Either way, log an error here.
168
 
                   and send an error reply back.
169
 
                */
170
 
                DEBUG(0,("process_name_refresh_request: unicast name registration request \
171
 
received for name %s from IP %s on subnet %s.\n",
172
 
                        nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
173
 
                DEBUG(0,("Error - should be sent to WINS server\n"));
174
 
    
175
 
                send_name_registration_response(FMT_ERR, 0, p);
176
 
                return;
177
 
        } 
178
 
 
179
 
        /* Just log a message. We really don't care about broadcast name refreshes. */
180
 
     
181
 
        DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
182
 
IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
183
 
}
184
 
    
185
 
/****************************************************************************
186
 
Process a name registration request on a broadcast subnet.
187
 
**************************************************************************/
188
 
 
189
 
void process_name_registration_request(struct subnet_record *subrec, 
190
 
                                       struct packet_struct *p)
191
 
{
192
 
        struct nmb_packet *nmb = &p->packet.nmb;
193
 
        struct nmb_name *question = &nmb->question.question_name;
194
 
        BOOL bcast = nmb->header.nm_flags.bcast;
195
 
        uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
196
 
        BOOL group = (nb_flags & NB_GROUP) ? True : False;
197
 
        struct name_record *namerec = NULL;
198
 
        int ttl = nmb->additional->ttl;
199
 
        struct in_addr from_ip;
200
 
  
201
 
        putip((char *)&from_ip,&nmb->additional->rdata[2]);
202
 
  
203
 
        if(!bcast) {
204
 
                /* We should only get broadcast name registration packets here.
205
 
                   Anyone trying to register unicast should be going to a WINS
206
 
                   server. If the code gets here, then either we are not a wins
207
 
                   server and they sent it anyway, or we are a WINS server and
208
 
                   the request was malformed. Either way, log an error here.
209
 
                   and send an error reply back.
210
 
                */
211
 
                DEBUG(0,("process_name_registration_request: unicast name registration request \
212
 
received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
213
 
                        nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));      
214
 
 
215
 
                send_name_registration_response(FMT_ERR, 0, p);
216
 
                return;
217
 
        }
218
 
 
219
 
        DEBUG(3,("process_name_registration_request: Name registration for name %s \
220
 
IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
221
 
  
222
 
        /* See if the name already exists. */
223
 
        namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
224
 
 
225
 
        /* 
226
 
         * If the name being registered exists and is a WINS_PROXY_NAME 
227
 
         * then delete the WINS proxy name entry so we don't reply erroneously
228
 
         * later to queries.
229
 
         */
230
 
 
231
 
        if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) {
232
 
                remove_name_from_namelist( subrec, namerec );
233
 
                namerec = NULL;
234
 
        }
235
 
 
236
 
        if (!group) {
237
 
                /* Unique name. */
238
 
 
239
 
                if( (namerec != NULL)
240
 
                                && ( (namerec->data.source == SELF_NAME)
241
 
                                || (namerec->data.source == PERMANENT_NAME)
242
 
                                || NAME_GROUP(namerec) ) ) {
243
 
                        /* No-one can register one of Samba's names, nor can they
244
 
                                register a name that's a group name as a unique name */
245
 
 
246
 
                        send_name_registration_response(ACT_ERR, 0, p);
247
 
                        return;
248
 
                } else if(namerec != NULL) {
249
 
                        /* Update the namelist record with the new information. */
250
 
                        namerec->data.ip[0] = from_ip;
251
 
                        update_name_ttl(namerec, ttl);
252
 
 
253
 
                        DEBUG(3,("process_name_registration_request: Updated name record %s \
254
 
with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
255
 
                        return;
256
 
                }
257
 
        } else {
258
 
                /* Group name. */
259
 
 
260
 
                if( (namerec != NULL)
261
 
                                && !NAME_GROUP(namerec)
262
 
                                && ( (namerec->data.source == SELF_NAME)
263
 
                                || (namerec->data.source == PERMANENT_NAME) ) ) {
264
 
                        /* Disallow group names when we have a unique name. */
265
 
                        send_name_registration_response(ACT_ERR, 0, p);  
266
 
                        return;  
267
 
                }  
268
 
        }
269
 
}
270
 
 
271
 
/****************************************************************************
272
 
This is used to sort names for a name status into a sensible order.
273
 
We put our own names first, then in alphabetical order.
274
 
**************************************************************************/
275
 
 
276
 
static int status_compare(char *n1,char *n2)
277
 
{
278
 
        unstring name1, name2;
279
 
        int l1,l2,l3;
280
 
 
281
 
        memset(name1, '\0', sizeof(name1));
282
 
        memset(name2, '\0', sizeof(name2));
283
 
        pull_ascii_nstring(name1, sizeof(name1), n1);
284
 
        pull_ascii_nstring(name2, sizeof(name2), n2);
285
 
        n1 = name1;
286
 
        n2 = name2;
287
 
 
288
 
        /* It's a bit tricky because the names are space padded */
289
 
        for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++)
290
 
                ;
291
 
        for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++)
292
 
                ;
293
 
        l3 = strlen(global_myname());
294
 
 
295
 
        if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 && 
296
 
                        (l2!=l3 || strncmp(n2,global_myname(),l3) != 0))
297
 
                return -1;
298
 
 
299
 
        if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 && 
300
 
                        (l1!=l3 || strncmp(n1,global_myname(),l3) != 0))
301
 
                return 1;
302
 
 
303
 
        return memcmp(n1,n2,sizeof(name1));
304
 
}
305
 
 
306
 
/****************************************************************************
307
 
  Process a node status query
308
 
  ****************************************************************************/
309
 
 
310
 
void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
311
 
{
312
 
        struct nmb_packet *nmb = &p->packet.nmb;
313
 
        unstring qname;
314
 
        int ques_type = nmb->question.question_name.name_type;
315
 
        char rdata[MAX_DGRAM_SIZE];
316
 
        char *countptr, *buf, *bufend, *buf0;
317
 
        int names_added,i;
318
 
        struct name_record *namerec;
319
 
 
320
 
        pull_ascii_nstring(qname, sizeof(qname), nmb->question.question_name.name);
321
 
 
322
 
        DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
323
 
subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name));
324
 
 
325
 
        if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME)) == 0) {
326
 
                DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
327
 
subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
328
 
                        inet_ntoa(p->ip), subrec->subnet_name));
329
 
 
330
 
                return;
331
 
        }
332
 
 
333
 
        /* this is not an exact calculation. the 46 is for the stats buffer
334
 
                and the 60 is to leave room for the header etc */
335
 
        bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
336
 
        countptr = buf = rdata;
337
 
        buf += 1;
338
 
        buf0 = buf;
339
 
 
340
 
        names_added = 0;
341
 
 
342
 
        namerec = subrec->namelist;
343
 
 
344
 
        while (buf < bufend) {
345
 
                if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) {
346
 
                        int name_type = namerec->name.name_type;
347
 
                        unstring name;
348
 
 
349
 
                        pull_ascii_nstring(name, sizeof(name), namerec->name.name);
350
 
                        strupper_m(name);
351
 
                        if (!strequal(name,"*") &&
352
 
                                        !strequal(name,"__SAMBA__") &&
353
 
                                        (name_type < 0x1b || name_type >= 0x20 || 
354
 
                                        ques_type < 0x1b || ques_type >= 0x20 ||
355
 
                                        strequal(qname, name))) {
356
 
                                /* Start with the name. */
357
 
                                size_t len;
358
 
                                push_ascii_nstring(buf, name);
359
 
                                len = strlen(buf);
360
 
                                memset(buf + len, ' ', MAX_NETBIOSNAME_LEN - len - 1);
361
 
                                buf[MAX_NETBIOSNAME_LEN - 1] = '\0';
362
 
 
363
 
                                /* Put the name type and netbios flags in the buffer. */
364
 
 
365
 
                                buf[15] = name_type;
366
 
                                set_nb_flags( &buf[16],namerec->data.nb_flags );
367
 
                                buf[16] |= NB_ACTIVE; /* all our names are active */
368
 
 
369
 
                                buf += 18;
370
 
 
371
 
                                names_added++;
372
 
                        }
373
 
                }
374
 
 
375
 
                /* Remove duplicate names. */
376
 
                if (names_added > 1) {
377
 
                        qsort( buf0, names_added, 18, QSORT_CAST status_compare );
378
 
                }
379
 
 
380
 
                for( i=1; i < names_added ; i++ ) {
381
 
                        if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
382
 
                                names_added--;
383
 
                                if (names_added == i)
384
 
                                        break;
385
 
                                memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
386
 
                                i--;
387
 
                        }
388
 
                }
389
 
 
390
 
                buf = buf0 + 18*names_added;
391
 
 
392
 
                namerec = namerec->next;
393
 
 
394
 
                if (!namerec) {
395
 
                        /* End of the subnet specific name list. Now 
396
 
                                add the names on the unicast subnet . */
397
 
                        struct subnet_record *uni_subrec = unicast_subnet;
398
 
 
399
 
                        if (uni_subrec != subrec) {
400
 
                                subrec = uni_subrec;
401
 
                                namerec = subrec->namelist;
402
 
                        }
403
 
                }
404
 
                if (!namerec)
405
 
                        break;
406
 
 
407
 
        }
408
 
  
409
 
        SCVAL(countptr,0,names_added);
410
 
  
411
 
        /* We don't send any stats as they could be used to attack
412
 
                the protocol. */
413
 
        memset(buf,'\0',46);
414
 
  
415
 
        buf += 46;
416
 
  
417
 
        /* Send a NODE STATUS RESPONSE */
418
 
        reply_netbios_packet(p,                               /* Packet to reply to. */
419
 
                                0,                            /* Result code. */
420
 
                                NMB_STATUS,                   /* nmbd type code. */
421
 
                                NMB_NAME_QUERY_OPCODE,        /* opcode. */
422
 
                                0,                            /* ttl. */
423
 
                                rdata,                        /* data to send. */
424
 
                                PTR_DIFF(buf,rdata));         /* data length. */
425
 
}
426
 
 
427
 
 
428
 
/***************************************************************************
429
 
Process a name query.
430
 
 
431
 
For broadcast name queries:
432
 
 
433
 
  - Only reply if the query is for one of YOUR names.
434
 
  - NEVER send a negative response to a broadcast query.
435
 
 
436
 
****************************************************************************/
437
 
 
438
 
void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
439
 
{
440
 
        struct nmb_packet *nmb = &p->packet.nmb;
441
 
        struct nmb_name *question = &nmb->question.question_name;
442
 
        int name_type = question->name_type;
443
 
        BOOL bcast = nmb->header.nm_flags.bcast;
444
 
        int ttl=0;
445
 
        int rcode = 0;
446
 
        char *prdata = NULL;
447
 
        char rdata[6];
448
 
        BOOL success = False;
449
 
        struct name_record *namerec = NULL;
450
 
        int reply_data_len = 0;
451
 
        int i;
452
 
        
453
 
        DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n", 
454
 
                 inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
455
 
  
456
 
        /* Look up the name in the cache - if the request is a broadcast request that
457
 
           came from a subnet we don't know about then search all the broadcast subnets
458
 
           for a match (as we don't know what interface the request came in on). */
459
 
 
460
 
        if(subrec == remote_broadcast_subnet)
461
 
                namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
462
 
        else
463
 
                namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
464
 
 
465
 
        /* Check if it is a name that expired */
466
 
        if (namerec && 
467
 
            ((namerec->data.death_time != PERMANENT_TTL) && 
468
 
             (namerec->data.death_time < p->timestamp))) {
469
 
                DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
470
 
                namerec = NULL;
471
 
        }
472
 
 
473
 
        if (namerec) {
474
 
                /* 
475
 
                 * Always respond to unicast queries.
476
 
                 * Don't respond to broadcast queries unless the query is for
477
 
                 * a name we own, a Primary Domain Controller name, or a WINS_PROXY 
478
 
                 * name with type 0 or 0x20. WINS_PROXY names are only ever added
479
 
                 * into the namelist if we were configured as a WINS proxy.
480
 
                 */
481
 
                
482
 
                if (!bcast || 
483
 
                    (bcast && ((name_type == 0x1b) ||
484
 
                               (namerec->data.source == SELF_NAME) ||
485
 
                               (namerec->data.source == PERMANENT_NAME) ||
486
 
                               ((namerec->data.source == WINS_PROXY_NAME) &&
487
 
                                ((name_type == 0) || (name_type == 0x20)))))) {
488
 
                        /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY, 
489
 
                           or it's a Domain Master type. */
490
 
 
491
 
                        /*
492
 
                         * If this is a WINS_PROXY_NAME, then ceck that none of the IP 
493
 
                         * addresses we are returning is on the same broadcast subnet 
494
 
                         * as the requesting packet. If it is then don't reply as the 
495
 
                         * actual machine will be replying also and we don't want two 
496
 
                         * replies to a broadcast query.
497
 
                         */
498
 
                        
499
 
                        if (namerec->data.source == WINS_PROXY_NAME) {
500
 
                                for( i = 0; i < namerec->data.num_ips; i++) {
501
 
                                        if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
502
 
                                                DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n", 
503
 
                                                         nmb_namestr(&namerec->name), subrec->subnet_name ));
504
 
                                                return;
505
 
                                        }
506
 
                                }
507
 
                        }
508
 
 
509
 
                        ttl = (namerec->data.death_time != PERMANENT_TTL) ?
510
 
                                namerec->data.death_time - p->timestamp : lp_max_ttl();
511
 
 
512
 
                        /* Copy all known ip addresses into the return data. */
513
 
                        /* Optimise for the common case of one IP address so 
514
 
                           we don't need a malloc. */
515
 
 
516
 
                        if (namerec->data.num_ips == 1) {
517
 
                                prdata = rdata;
518
 
                        } else {
519
 
                                if ((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
520
 
                                        DEBUG(0,("process_name_query_request: malloc fail !\n"));
521
 
                                        return;
522
 
                                }
523
 
                        }
524
 
 
525
 
                        for (i = 0; i < namerec->data.num_ips; i++) {
526
 
                                set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
527
 
                                putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
528
 
                        }
529
 
 
530
 
                        sort_query_replies(prdata, i, p->ip);
531
 
                        
532
 
                        reply_data_len = namerec->data.num_ips * 6;
533
 
                        success = True;
534
 
                }
535
 
        }
536
 
 
537
 
        /*
538
 
         * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
539
 
         * set we should initiate a WINS query here. On success we add the resolved name 
540
 
         * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
541
 
         */
542
 
        
543
 
        if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() && 
544
 
           bcast && (subrec != remote_broadcast_subnet)) {
545
 
                make_wins_proxy_name_query_request( subrec, p, question );
546
 
                return;
547
 
        }
548
 
 
549
 
        if (!success && bcast) {
550
 
                if(prdata != rdata)
551
 
                        SAFE_FREE(prdata);
552
 
                return; /* Never reply with a negative response to broadcasts. */
553
 
        }
554
 
 
555
 
        /* 
556
 
         * Final check. From observation, if a unicast packet is sent
557
 
         * to a non-WINS server with the recursion desired bit set
558
 
         * then never send a negative response.
559
 
         */
560
 
        
561
 
        if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
562
 
                if(prdata != rdata)
563
 
                        SAFE_FREE(prdata);
564
 
                return;
565
 
        }
566
 
 
567
 
        if (success) {
568
 
                rcode = 0;
569
 
                DEBUG(3,("OK\n"));
570
 
        } else {
571
 
                rcode = NAM_ERR;
572
 
                DEBUG(3,("UNKNOWN\n"));      
573
 
        }
574
 
 
575
 
        /* See rfc1002.txt 4.2.13. */
576
 
 
577
 
        reply_netbios_packet(p,                              /* Packet to reply to. */
578
 
                             rcode,                          /* Result code. */
579
 
                             NMB_QUERY,                      /* nmbd type code. */
580
 
                             NMB_NAME_QUERY_OPCODE,          /* opcode. */
581
 
                             ttl,                            /* ttl. */
582
 
                             prdata,                         /* data to send. */
583
 
                             reply_data_len);                /* data length. */
584
 
        
585
 
        if(prdata != rdata)
586
 
                SAFE_FREE(prdata);
587
 
}