2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
7 Copyright (C) Jeremy Allison 1994-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file contains all the code to process NetBIOS requests coming
24 in on port 137. It does not deal with the code needed to service
25 WINS server requests, but only broadcast and unicast requests.
31 extern fstring global_myworkgroup
;
33 /****************************************************************************
34 Send a name release response.
35 **************************************************************************/
37 static void send_name_release_response(int rcode
, struct packet_struct
*p
)
39 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
42 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
44 reply_netbios_packet(p
, /* Packet to reply to. */
45 rcode
, /* Result code. */
46 NMB_REL
, /* nmbd type code. */
47 NMB_NAME_RELEASE_OPCODE
, /* opcode. */
49 rdata
, /* data to send. */
50 6); /* data length. */
53 /****************************************************************************
54 Process a name release packet on a broadcast subnet.
55 Ignore it if it's not one of our names.
56 ****************************************************************************/
58 void process_name_release_request(struct subnet_record
*subrec
,
59 struct packet_struct
*p
)
61 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
62 struct in_addr owner_ip
;
63 struct nmb_name
*question
= &nmb
->question
.question_name
;
64 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
65 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
66 BOOL group
= (nb_flags
& NB_GROUP
) ? True
: False
;
67 struct name_record
*namerec
;
70 putip((char *)&owner_ip
,&nmb
->additional
->rdata
[2]);
74 /* We should only get broadcast name release packets here.
75 Anyone trying to release unicast should be going to a WINS
76 server. If the code gets here, then either we are not a wins
77 server and they sent it anyway, or we are a WINS server and
78 the request was malformed. Either way, log an error here.
79 and send an error reply back.
81 DEBUG(0,("process_name_release_request: unicast name release request \
82 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
83 nmb_namestr(question
), inet_ntoa(owner_ip
), subrec
->subnet_name
));
85 send_name_release_response(FMT_ERR
, p
);
89 DEBUG(3,("process_name_release_request: Name release on name %s, \
90 subnet %s from owner IP %s\n",
91 nmb_namestr(&nmb
->question
.question_name
),
92 subrec
->subnet_name
, inet_ntoa(owner_ip
)));
94 /* If someone is releasing a broadcast group name, just ignore it. */
95 if( group
&& !ismyip(owner_ip
) )
99 * Code to work around a bug in FTP OnNet software NBT implementation.
100 * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
101 * names and *don't set the group bit* !!!!!
104 if( !group
&& !ismyip(owner_ip
) && strequal(question
->name
, global_myworkgroup
) &&
105 ((question
->name_type
== 0x0) || (question
->name_type
== 0x1e)))
107 DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
108 group release name %s from IP %s on subnet %s with no group bit set.\n",
109 nmb_namestr(question
), inet_ntoa(owner_ip
), subrec
->subnet_name
));
113 namerec
= find_name_on_subnet(subrec
, &nmb
->question
.question_name
, FIND_ANY_NAME
);
115 /* We only care about someone trying to release one of our names. */
117 && ( (namerec
->data
.source
== SELF_NAME
)
118 || (namerec
->data
.source
== PERMANENT_NAME
) ) )
121 DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
122 on subnet %s being rejected as it is one of our names.\n",
123 nmb_namestr(&nmb
->question
.question_name
), inet_ntoa(owner_ip
), subrec
->subnet_name
));
129 /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
130 send_name_release_response(rcode
, p
);
133 /****************************************************************************
134 Send a name registration response.
135 **************************************************************************/
137 static void send_name_registration_response(int rcode
, int ttl
, struct packet_struct
*p
)
139 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
142 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
144 reply_netbios_packet(p
, /* Packet to reply to. */
145 rcode
, /* Result code. */
146 NMB_REG
, /* nmbd type code. */
147 NMB_NAME_REG_OPCODE
, /* opcode. */
149 rdata
, /* data to send. */
150 6); /* data length. */
153 /****************************************************************************
154 Process a name refresh request on a broadcast subnet.
155 **************************************************************************/
157 void process_name_refresh_request(struct subnet_record
*subrec
,
158 struct packet_struct
*p
)
161 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
162 struct nmb_name
*question
= &nmb
->question
.question_name
;
163 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
164 struct in_addr from_ip
;
166 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
170 /* We should only get broadcast name refresh packets here.
171 Anyone trying to refresh unicast should be going to a WINS
172 server. If the code gets here, then either we are not a wins
173 server and they sent it anyway, or we are a WINS server and
174 the request was malformed. Either way, log an error here.
175 and send an error reply back.
177 DEBUG(0,("process_name_refresh_request: unicast name registration request \
178 received for name %s from IP %s on subnet %s.\n",
179 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
180 DEBUG(0,("Error - should be sent to WINS server\n"));
182 send_name_registration_response(FMT_ERR
, 0, p
);
186 /* Just log a message. We really don't care about broadcast name
189 DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
190 IP %s on subnet %s\n", nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
194 /****************************************************************************
195 Process a name registration request on a broadcast subnet.
196 **************************************************************************/
198 void process_name_registration_request(struct subnet_record
*subrec
,
199 struct packet_struct
*p
)
201 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
202 struct nmb_name
*question
= &nmb
->question
.question_name
;
203 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
204 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
205 BOOL group
= (nb_flags
& NB_GROUP
) ? True
: False
;
206 struct name_record
*namerec
= NULL
;
207 int ttl
= nmb
->additional
->ttl
;
208 struct in_addr from_ip
;
210 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
214 /* We should only get broadcast name registration packets here.
215 Anyone trying to register unicast should be going to a WINS
216 server. If the code gets here, then either we are not a wins
217 server and they sent it anyway, or we are a WINS server and
218 the request was malformed. Either way, log an error here.
219 and send an error reply back.
221 DEBUG(0,("process_name_registration_request: unicast name registration request \
222 received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
223 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
225 send_name_registration_response(FMT_ERR
, 0, p
);
229 DEBUG(3,("process_name_registration_request: Name registration for name %s \
230 IP %s on subnet %s\n", nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
232 /* See if the name already exists. */
233 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
236 * If the name being registered exists and is a WINS_PROXY_NAME
237 * then delete the WINS proxy name entry so we don't reply erroneously
241 if((namerec
!= NULL
) && (namerec
->data
.source
== WINS_PROXY_NAME
))
243 remove_name_from_namelist( subrec
, namerec
);
251 if( (namerec
!= NULL
)
252 && ( (namerec
->data
.source
== SELF_NAME
)
253 || (namerec
->data
.source
== PERMANENT_NAME
)
254 || NAME_GROUP(namerec
) ) )
256 /* No-one can register one of Samba's names, nor can they
257 register a name that's a group name as a unique name */
259 send_name_registration_response(ACT_ERR
, 0, p
);
262 else if(namerec
!= NULL
)
264 /* Update the namelist record with the new information. */
265 namerec
->data
.ip
[0] = from_ip
;
266 update_name_ttl(namerec
, ttl
);
268 DEBUG(3,("process_name_registration_request: Updated name record %s \
269 with IP %s on subnet %s\n",nmb_namestr(&namerec
->name
),inet_ntoa(from_ip
), subrec
->subnet_name
));
277 if( (namerec
!= NULL
)
278 && !NAME_GROUP(namerec
)
279 && ( (namerec
->data
.source
== SELF_NAME
)
280 || (namerec
->data
.source
== PERMANENT_NAME
) ) )
282 /* Disallow group names when we have a unique name. */
283 send_name_registration_response(ACT_ERR
, 0, p
);
289 /****************************************************************************
290 This is used to sort names for a name status into a sensible order.
291 We put our own names first, then in alphabetical order.
292 **************************************************************************/
294 static int status_compare(char *n1
,char *n2
)
296 extern pstring global_myname
;
299 /* It's a bit tricky because the names are space padded */
300 for (l1
=0;l1
<15 && n1
[l1
] && n1
[l1
] != ' ';l1
++) ;
301 for (l2
=0;l2
<15 && n2
[l2
] && n2
[l2
] != ' ';l2
++) ;
302 l3
= strlen(global_myname
);
304 if ((l1
==l3
) && strncmp(n1
,global_myname
,l3
) == 0 &&
305 (l2
!=l3
|| strncmp(n2
,global_myname
,l3
) != 0))
308 if ((l2
==l3
) && strncmp(n2
,global_myname
,l3
) == 0 &&
309 (l1
!=l3
|| strncmp(n1
,global_myname
,l3
) != 0))
312 return memcmp(n1
,n2
,18);
316 /****************************************************************************
317 Process a node status query
318 ****************************************************************************/
320 void process_node_status_request(struct subnet_record
*subrec
, struct packet_struct
*p
)
322 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
323 char *qname
= nmb
->question
.question_name
.name
;
324 int ques_type
= nmb
->question
.question_name
.name_type
;
325 char rdata
[MAX_DGRAM_SIZE
];
326 char *countptr
, *buf
, *bufend
, *buf0
;
328 struct name_record
*namerec
;
330 DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
331 subnet %s.\n", nmb_namestr(&nmb
->question
.question_name
), inet_ntoa(p
->ip
),
332 subrec
->subnet_name
));
334 if((namerec
= find_name_on_subnet(subrec
, &nmb
->question
.question_name
,
335 FIND_SELF_NAME
)) == 0)
337 DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
338 subnet %s - name not found.\n", nmb_namestr(&nmb
->question
.question_name
),
339 inet_ntoa(p
->ip
), subrec
->subnet_name
));
344 /* this is not an exact calculation. the 46 is for the stats buffer
345 and the 60 is to leave room for the header etc */
346 bufend
= &rdata
[MAX_DGRAM_SIZE
] - (18 + 46 + 60);
347 countptr
= buf
= rdata
;
353 namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
357 if( (namerec
->data
.source
== SELF_NAME
)
358 || (namerec
->data
.source
== PERMANENT_NAME
) )
360 int name_type
= namerec
->name
.name_type
;
362 if (!strequal(namerec
->name
.name
,"*") &&
363 !strequal(namerec
->name
.name
,"__SAMBA__") &&
364 (name_type
< 0x1b || name_type
>= 0x20 ||
365 ques_type
< 0x1b || ques_type
>= 0x20 ||
366 strequal(qname
, namerec
->name
.name
)))
368 /* Start with the name. */
370 slprintf(buf
, 17, "%-15.15s",namerec
->name
.name
);
373 /* Put the name type and netbios flags in the buffer. */
375 set_nb_flags( &buf
[16],namerec
->data
.nb_flags
);
376 buf
[16] |= NB_ACTIVE
; /* all our names are active */
384 /* Remove duplicate names. */
385 if (names_added
> 1) {
386 qsort( buf0
, names_added
, 18, QSORT_CAST status_compare
);
389 for( i
=1; i
< names_added
; i
++ )
391 if (memcmp(buf0
+ 18*i
,buf0
+ 18*(i
-1),16) == 0)
394 if (names_added
== i
)
396 memmove(buf0
+ 18*i
,buf0
+ 18*(i
+1),18*(names_added
-i
));
401 buf
= buf0
+ 18*names_added
;
403 namerec
= (struct name_record
*)ubi_trNext( namerec
);
407 /* End of the subnet specific name list. Now
408 add the names on the unicast subnet . */
409 struct subnet_record
*uni_subrec
= unicast_subnet
;
411 if (uni_subrec
!= subrec
)
414 namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
422 SCVAL(countptr
,0,names_added
);
424 /* We don't send any stats as they could be used to attack
430 /* Send a NODE STATUS RESPONSE */
431 reply_netbios_packet(p
, /* Packet to reply to. */
432 0, /* Result code. */
433 NMB_STATUS
, /* nmbd type code. */
434 NMB_NAME_QUERY_OPCODE
, /* opcode. */
436 rdata
, /* data to send. */
437 PTR_DIFF(buf
,rdata
)); /* data length. */
441 /***************************************************************************
442 Process a name query.
444 For broadcast name queries:
446 - Only reply if the query is for one of YOUR names.
447 - NEVER send a negative response to a broadcast query.
449 ****************************************************************************/
451 void process_name_query_request(struct subnet_record
*subrec
, struct packet_struct
*p
)
453 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
454 struct nmb_name
*question
= &nmb
->question
.question_name
;
455 int name_type
= question
->name_type
;
456 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
461 BOOL success
= False
;
462 struct name_record
*namerec
= NULL
;
463 int reply_data_len
= 0;
466 DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
467 inet_ntoa(p
->ip
), subrec
->subnet_name
, nmb_namestr(question
)));
469 /* Look up the name in the cache - if the request is a broadcast request that
470 came from a subnet we don't know about then search all the broadcast subnets
471 for a match (as we don't know what interface the request came in on). */
473 if(subrec
== remote_broadcast_subnet
)
474 namerec
= find_name_for_remote_broadcast_subnet( question
, FIND_ANY_NAME
);
476 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
479 /* Check if it is a name that expired */
481 && ( (namerec
->data
.death_time
!= PERMANENT_TTL
)
482 && (namerec
->data
.death_time
< p
->timestamp
) ) )
484 DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec
->name
)));
492 * Always respond to unicast queries.
493 * Don't respond to broadcast queries unless the query is for
494 * a name we own, a Primary Domain Controller name, or a WINS_PROXY
495 * name with type 0 or 0x20. WINS_PROXY names are only ever added
496 * into the namelist if we were configured as a WINS proxy.
501 && ( (name_type
== 0x1b)
502 || (namerec
->data
.source
== SELF_NAME
)
503 || (namerec
->data
.source
== PERMANENT_NAME
)
504 || ( (namerec
->data
.source
== WINS_PROXY_NAME
)
505 && ( (name_type
== 0) || (name_type
== 0x20) )
512 /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
513 or it's a Domain Master type. */
516 * If this is a WINS_PROXY_NAME, then ceck that none of the IP
517 * addresses we are returning is on the same broadcast subnet
518 * as the requesting packet. If it is then don't reply as the
519 * actual machine will be replying also and we don't want two
520 * replies to a broadcast query.
523 if( namerec
->data
.source
== WINS_PROXY_NAME
)
525 for( i
= 0; i
< namerec
->data
.num_ips
; i
++)
527 if(same_net( namerec
->data
.ip
[i
], subrec
->myip
, subrec
->mask_ip
))
529 DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also \
530 on the same subnet (%s) as the requestor. Not replying.\n",
531 nmb_namestr(&namerec
->name
), subrec
->subnet_name
));
537 ttl
= (namerec
->data
.death_time
!= PERMANENT_TTL
) ?
538 namerec
->data
.death_time
- p
->timestamp
: lp_max_ttl();
540 /* Copy all known ip addresses into the return data. */
541 /* Optimise for the common case of one IP address so
542 we don't need a malloc. */
544 if( namerec
->data
.num_ips
== 1 )
548 if((prdata
= (char *)malloc( namerec
->data
.num_ips
* 6 )) == NULL
)
550 DEBUG(0,("process_name_query_request: malloc fail !\n"));
555 for( i
= 0; i
< namerec
->data
.num_ips
; i
++ )
557 set_nb_flags(&prdata
[i
*6],namerec
->data
.nb_flags
);
558 putip((char *)&prdata
[2+(i
*6)], &namerec
->data
.ip
[i
]);
561 sort_query_replies(prdata
, i
, p
->ip
);
563 reply_data_len
= namerec
->data
.num_ips
* 6;
569 * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
570 * set we should initiate a WINS query here. On success we add the resolved name
571 * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
574 if(!success
&& (namerec
== NULL
) && we_are_a_wins_client() && lp_wins_proxy() &&
575 bcast
&& (subrec
!= remote_broadcast_subnet
))
577 make_wins_proxy_name_query_request( subrec
, p
, question
);
581 if (!success
&& bcast
)
585 return; /* Never reply with a negative response to broadcasts. */
589 * Final check. From observation, if a unicast packet is sent
590 * to a non-WINS server with the recursion desired bit set
591 * then never send a negative response.
594 if(!success
&& !bcast
&& nmb
->header
.nm_flags
.recursion_desired
)
609 DEBUG(3,("UNKNOWN\n"));
612 /* See rfc1002.txt 4.2.13. */
614 reply_netbios_packet(p
, /* Packet to reply to. */
615 rcode
, /* Result code. */
616 NMB_QUERY
, /* nmbd type code. */
617 NMB_NAME_QUERY_OPCODE
, /* opcode. */
619 prdata
, /* data to send. */
620 reply_data_len
); /* data length. */