Unix SMB/Netbios implementation.
Version 1.9.
NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1995
+ Copyright (C) Andrew Tridgell 1994-1997
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
BOOL CanRecurse = True;
extern pstring scope;
-extern struct in_addr ipgrp;
+extern struct in_addr wins_ip;
static uint16 name_trn_id=0;
initiate a netbios packet
****************************************************************************/
void initiate_netbios_packet(uint16 *id,
- int fd,int quest_type,char *name,int name_type,
- int nb_flags,BOOL bcast,BOOL recurse,
- struct in_addr to_ip)
+ int fd,int quest_type,char *name,int name_type,
+ int nb_flags,BOOL bcast,BOOL recurse,
+ struct in_addr to_ip)
{
struct packet_struct p;
struct nmb_packet *nmb = &p.packet.nmb;
make_nmb_name(&nmb->question.question_name,name,name_type,scope);
- nmb->question.question_type = quest_type;
+ nmb->question.question_type = quest_type == NMB_STATUS ? 0x21 : 0x20;
nmb->question.question_class = 0x1;
if (quest_type == NMB_REG ||
quest_type == NMB_REG_REFRESH ||
quest_type == NMB_REL)
- {
+ {
nmb->additional = &additional_rec;
bzero((char *)nmb->additional,sizeof(*nmb->additional));
nmb->additional->rr_name = nmb->question.question_name;
- nmb->additional->rr_type = nmb->question.question_type;
- nmb->additional->rr_class = nmb->question.question_class;
+ nmb->additional->rr_type = 0x20;
+ nmb->additional->rr_class = 0x1;
if (quest_type == NMB_REG || quest_type == NMB_REG_REFRESH)
- nmb->additional->ttl = lp_max_ttl();
+ nmb->additional->ttl = lp_max_ttl();
else
- nmb->additional->ttl = 0;
+ nmb->additional->ttl = 0;
+
nmb->additional->rdlength = 6;
nmb->additional->rdata[0] = nb_flags;
putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
- }
+ }
p.ip = to_ip;
p.port = NMB_PORT;
p.timestamp = time(NULL);
p.packet_type = NMB_PACKET;
+ debug_nmb_packet(&p);
+
if (!send_packet(&p)) {
DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
*id = 0xffff;
nmb->header.ancount = 1;
nmb->header.nscount = 0;
nmb->header.arcount = 0;
- nmb->header.rcode = 0;
+ nmb->header.rcode = rcode;
bzero((char*)&nmb->question,sizeof(nmb->question));
struct subnet_record *d;
struct name_record *n1;
+ /* We explicitly don't search WINS here - this will be done
+ in find_name_search if it was a packet from a non-local subnet. */
d = find_subnet(p->ip);
-
+
n1 = find_name_search(&d,n,FIND_LOCAL|FIND_WINS|FIND_SELF,p->ip);
return (n1 != NULL);
/* if we aren't listening to the destination name then ignore the packet */
if (!listening(p,&dgram->dest_name))
+ {
+ DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%x) from %s\n",
+ dgram->dest_name.name, dgram->dest_name.name_type, inet_ntoa(p->ip)));
return;
-
+ }
if (dgram->header.msg_type != 0x10 &&
dgram->header.msg_type != 0x11 &&
- dgram->header.msg_type != 0x12) {
+ dgram->header.msg_type != 0x12)
+ {
/* don't process error packets etc yet */
+ DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%d) from %s as it is \
+ an error packet of type %x\n",
+ dgram->dest_name.name, dgram->dest_name.name_type,
+ inet_ntoa(p->ip), dgram->header.msg_type));
return;
}
len = SVAL(buf,smb_vwv11);
buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
- DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
+ DEBUG(4,("process_dgram: datagram from %s to %s for %s of type %d len=%d\n",
namestr(&dgram->source_name),namestr(&dgram->dest_name),
smb_buf(buf),CVAL(buf2,0),len));
case NMB_REG:
case NMB_REG_REFRESH:
{
- if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
if (nmb->header.response)
+ {
+ if (nmb->header.ancount ==0) break;
response_netbios_packet(p); /* response to registration dealt
with here */
+ }
else
+ {
+ if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
reply_name_reg(p);
+ }
break;
}
case NMB_REL:
{
- if (nmb->header.qdcount==0 || nmb->header.arcount==0)
- {
- DEBUG(2,("netbios release packet rejected\n"));
- break;
- }
-
if (nmb->header.response)
- response_netbios_packet(p); /* response to reply dealt with
- in here */
+ {
+ if (nmb->header.ancount ==0) break;
+ response_netbios_packet(p); /* response to release dealt
+ with here */
+ }
else
+ {
+ if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
reply_name_release(p);
+ }
break;
}
}
***************************************************************************/
void listen_for_packets(BOOL run_election)
{
- fd_set fds;
- int selrtn;
- struct timeval timeout;
+ fd_set fds;
+ int selrtn;
+ struct timeval timeout;
-try_again:
+ FD_ZERO(&fds);
+ FD_SET(ClientNMB,&fds);
+ FD_SET(ClientDGRAM,&fds);
- FD_ZERO(&fds);
- FD_SET(ClientNMB,&fds);
- FD_SET(ClientDGRAM,&fds);
+ /* during elections and when expecting a netbios response packet we
+ need to send election packets at tighter intervals
- /* during elections and when expecting a netbios response packet we
- need to send election packets at tighter intervals
+ ideally it needs to be the interval (in ms) between time now and
+ the time we are expecting the next netbios packet */
- ideally it needs to be the interval (in ms) between time now and
- the time we are expecting the next netbios packet */
+ timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP;
+ timeout.tv_usec = 0;
- timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
+ /* We can only take term signals when we are in the select. */
+ BlockSignals(False, SIGTERM);
+ selrtn = sys_select(&fds,&timeout);
+ BlockSignals(True, SIGTERM);
- selrtn = sys_select(&fds,&timeout);
-
- if (FD_ISSET(ClientNMB,&fds))
- {
- struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
- if (packet) {
- if (ismyip(packet->ip) &&
- (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
- DEBUG(7,("discarding own packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- goto try_again;
- } else {
- queue_packet(packet);
+ if (FD_ISSET(ClientNMB,&fds))
+ {
+ struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
+ if (packet)
+ {
+ if (ismyip(packet->ip) && packet->port == NMB_PORT)
+ {
+ DEBUG(7,("discarding own packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else
+ {
+ queue_packet(packet);
+ }
+ }
}
- }
- }
- if (FD_ISSET(ClientDGRAM,&fds))
- {
- struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
- if (packet) {
- if (ismyip(packet->ip) &&
- (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) {
- DEBUG(7,("discarding own packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- goto try_again;
- } else {
- queue_packet(packet);
+ if (FD_ISSET(ClientDGRAM,&fds))
+ {
+ struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
+ if (packet)
+ {
+ if (ismyip(packet->ip) && packet->port == DGRAM_PORT)
+ {
+ DEBUG(7,("discarding own packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else
+ {
+ queue_packet(packet);
+ }
+ }
}
- }
- }
}
Note that this currently sends all answers to port 138. thats the
wrong things to do! I should send to the requestors port. XXX
**************************************************************************/
-BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
+BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,char *srcname,
char *dstname,int src_type,int dest_type,
struct in_addr dest_ip,struct in_addr src_ip)
{
struct packet_struct p;
struct dgram_packet *dgram = &p.packet.dgram;
- struct in_addr wins_ip = ipgrp;
char *ptr,*p2;
char tmp[4];
update_name_trn_id();
- dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
+ /* DIRECT GROUP or UNIQUE datagram */
+ dgram->header.msg_type = unique ? 0x10 : 0x11;
dgram->header.flags.node_type = M_NODE;
dgram->header.flags.first = True;
dgram->header.flags.more = False;