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
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int num_response_packets;
-extern struct in_addr loopback_ip;
-
static void queue_packet(struct packet_struct *packet);
-BOOL rescan_listen_set = False;
+bool rescan_listen_set = False;
/*******************************************************************
Either loops back or sends out a completed NetBIOS packet.
**************************************************************************/
-static BOOL send_netbios_packet(struct packet_struct *p)
+static bool send_netbios_packet(struct packet_struct *p)
{
- BOOL loopback_this_packet = False;
+ bool loopback_this_packet = False;
/* Check if we are sending to or from ourselves as a WINS server. */
- if(ismyip(p->ip) && (p->port == global_nmb_port))
+ if(ismyip_v4(p->ip) && (p->port == global_nmb_port))
loopback_this_packet = True;
if(loopback_this_packet) {
**************************************************************************/
static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmbname,
- BOOL bcast, BOOL rec_des,
+ bool bcast, bool rec_des,
struct in_addr to_ip)
{
struct packet_struct *packet = NULL;
Sets up the common elements of register, refresh or release packet.
**************************************************************************/
-static BOOL create_and_init_additional_record(struct packet_struct *packet,
+static bool create_and_init_additional_record(struct packet_struct *packet,
uint16 nb_flags,
- struct in_addr *register_ip)
+ const struct in_addr *register_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
if((nmb->additional = SMB_MALLOC_P(struct res_rec)) == NULL) {
- DEBUG(0,("initiate_name_register_packet: malloc fail for additional record.\n"));
+ DEBUG(0,("create_and_init_additional_record: malloc fail for additional record.\n"));
return False;
}
Sends out a name query.
**************************************************************************/
-static BOOL initiate_name_query_packet( struct packet_struct *packet)
+static bool initiate_name_query_packet( struct packet_struct *packet)
{
struct nmb_packet *nmb = NULL;
Sends out a name query - from a WINS server.
**************************************************************************/
-static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *packet)
+static bool initiate_name_query_packet_from_wins_server( struct packet_struct *packet)
{
struct nmb_packet *nmb = NULL;
Sends out a name register.
**************************************************************************/
-static BOOL initiate_name_register_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *register_ip)
+static bool initiate_name_register_packet( struct packet_struct *packet,
+ uint16 nb_flags, const struct in_addr *register_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
Sends out a multihomed name register.
**************************************************************************/
-static BOOL initiate_multihomed_name_register_packet(struct packet_struct *packet,
+static bool initiate_multihomed_name_register_packet(struct packet_struct *packet,
uint16 nb_flags, struct in_addr *register_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
Sends out a name refresh.
**************************************************************************/
-static BOOL initiate_name_refresh_packet( struct packet_struct *packet,
+static bool initiate_name_refresh_packet( struct packet_struct *packet,
uint16 nb_flags, struct in_addr *refresh_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
Sends out a name release.
**************************************************************************/
-static BOOL initiate_name_release_packet( struct packet_struct *packet,
+static bool initiate_name_release_packet( struct packet_struct *packet,
uint16 nb_flags, struct in_addr *release_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
Sends out a node status.
**************************************************************************/
-static BOOL initiate_node_status_packet( struct packet_struct *packet )
+static bool initiate_node_status_packet( struct packet_struct *packet )
{
struct nmb_packet *nmb = &packet->packet.nmb;
broadcast subnet.
****************************************************************************/
-static BOOL assert_check_subnet(struct subnet_record *subrec)
+static bool assert_check_subnet(struct subnet_record *subrec)
{
if( subrec == remote_broadcast_subnet) {
DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \
{
struct packet_struct *p;
struct response_record *rrec;
-
+ struct sockaddr_storage ss;
+ const struct sockaddr_storage *pss = NULL;
if(assert_check_subnet(subrec))
return NULL;
subrec->bcast_ip)) == NULL)
return NULL;
- if(initiate_name_register_packet( p, nb_flags, iface_ip(subrec->bcast_ip)) == False) {
+ in_addr_to_sockaddr_storage(&ss, subrec->bcast_ip);
+ pss = iface_ip(&ss);
+ if (!pss || pss->ss_family != AF_INET) {
+ p->locked = False;
+ free_packet(p);
+ return NULL;
+ }
+
+ if(initiate_name_register_packet(p, nb_flags,
+ &((const struct sockaddr_in *)pss)->sin_addr) == False) {
p->locked = False;
free_packet(p);
return NULL;
userdata = (struct userdata_struct *)SMB_MALLOC(sizeof(*userdata) + strlen(tag) + 1);
if (!userdata) {
+ p->locked = False;
+ free_packet(p);
DEBUG(0,("Failed to allocate userdata structure!\n"));
return;
}
{
struct packet_struct *p;
struct response_record *rrec;
- BOOL ret;
+ bool ret;
/* Sanity check. */
if(subrec != unicast_subnet) {
/* queries to the WINS server turn up here as queries to IP 0.0.0.0
These need to be handled a bit differently */
- if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) {
+ if (subrec->type == UNICAST_SUBNET && is_zero_ip_v4(to_ip)) {
/* What we really need to do is loop over each of our wins
* servers and wins server tags here, but that just doesn't
* fit our architecture at the moment (userdata may already
DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n"));
for(i = 0; i < iface_count(); i++) {
- struct in_addr *ifip = iface_n_ip(i);
+ const struct in_addr *ifip = iface_n_ip_v4(i);
- if(ifip == NULL) {
+ if (ifip == NULL) {
DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i));
continue;
}
- if (ip_equal(*ifip,loopback_ip)) {
+ if (is_loopback_ip_v4(*ifip)) {
DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i));
continue;
}
/****************************************************************************
Queue a query name packet to a given address from the WINS subnet.
****************************************************************************/
-
+
struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip,
response_function resp_fn,
timeout_response_function timeout_fn,
/****************************************************************************
Queue a node status packet to a given name and address.
****************************************************************************/
-
+
struct response_record *queue_node_status( struct subnet_record *subrec,
response_function resp_fn,
timeout_response_function timeout_fn,
p->locked = False;
free_packet(p);
return NULL;
- }
+ }
if((rrec = make_response_record(subrec, /* subnet record. */
p, /* packet we sent. */
struct nmb_packet *nmb = NULL;
struct res_rec answers;
struct nmb_packet *orig_nmb = &orig_packet->packet.nmb;
- BOOL loopback_this_packet = False;
+ bool loopback_this_packet = False;
+ int rr_type = RR_TYPE_NB;
const char *packet_type = "unknown";
-
+
/* Check if we are sending to or from ourselves. */
- if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port))
+ if(ismyip_v4(orig_packet->ip) && (orig_packet->port == global_nmb_port))
loopback_this_packet = True;
-
+
nmb = &packet.packet.nmb;
/* Do a partial copy of the packet. We clear the locked flag and
packet_type = "nmb_status";
nmb->header.nm_flags.recursion_desired = False;
nmb->header.nm_flags.recursion_available = False;
+ rr_type = RR_TYPE_NBSTAT;
break;
case NMB_QUERY:
packet_type = "nmb_query";
nmb->header.nm_flags.recursion_desired = True;
nmb->header.nm_flags.recursion_available = True;
+ if (rcode) {
+ rr_type = RR_TYPE_NULL;
+ }
break;
case NMB_REG:
case NMB_REG_REFRESH:
packet_type = "nmb_wack";
nmb->header.nm_flags.recursion_desired = False;
nmb->header.nm_flags.recursion_available = False;
+ rr_type = RR_TYPE_NULL;
break;
case WINS_REG:
packet_type = "wins_reg";
packet_type = "wins_query";
nmb->header.nm_flags.recursion_desired = True;
nmb->header.nm_flags.recursion_available = True;
+ if (rcode) {
+ rr_type = RR_TYPE_NULL;
+ }
break;
default:
DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n",
nmb->header.nm_flags.bcast = False;
nmb->header.nm_flags.trunc = False;
nmb->header.nm_flags.authoritative = True;
-
+
nmb->header.rcode = rcode;
nmb->header.qdcount = 0;
nmb->header.ancount = 1;
nmb->header.nscount = 0;
nmb->header.arcount = 0;
-
+
memset((char*)&nmb->question,'\0',sizeof(nmb->question));
-
+
nmb->answers = &answers;
memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
-
+
nmb->answers->rr_name = orig_nmb->question.question_name;
- nmb->answers->rr_type = orig_nmb->question.question_type;
- nmb->answers->rr_class = orig_nmb->question.question_class;
+ nmb->answers->rr_type = rr_type;
+ nmb->answers->rr_class = RR_CLASS_IN;
nmb->answers->ttl = ttl;
-
+
if (data && len) {
nmb->answers->rdlength = len;
memcpy(nmb->answers->rdata, data, len);
}
-
+
packet.packet_type = NMB_PACKET;
/* Ensure we send out on the same fd that the original
packet came in on to give the correct source IP address. */
packet.timestamp = time(NULL);
debug_nmb_packet(&packet);
-
+
if(loopback_this_packet) {
struct packet_struct *lo_packet;
DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n"));
packet_queue = packet;
return;
}
-
+
/* find the bottom */
- for (p=packet_queue;p->next;p=p->next)
+ for (p=packet_queue;p->next;p=p->next)
;
p->next = packet;
/* Go through all the broadcast subnets and see if the mask matches. */
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
+ if(same_net_v4(p->ip, subrec->bcast_ip, subrec->mask_ip))
return subrec;
}
process_master_browser_announce(subrec, p, buf+1);
break;
case ANN_BecomeBackup:
- /*
+ /*
* We don't currently implement this. Log it just in case.
*/
debug_browse_data(buf, len);
command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
break;
- }
+ }
}
/****************************************************************************
switch (command) {
case ANN_HostAnnouncement:
debug_browse_data(buf, len);
- process_lm_host_announce(subrec, p, buf+1);
+ process_lm_host_announce(subrec, p, buf+1, len > 1 ? len-1 : 0);
break;
case ANN_AnnouncementRequest:
- process_lm_announce_request(subrec, p, buf+1);
+ process_lm_announce_request(subrec, p, buf+1, len > 1 ? len-1 : 0);
break;
default:
DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \
stage as subsequent processing is expensive.
****************************************************************************/
-static BOOL listening(struct packet_struct *p,struct nmb_name *nbname)
+static bool listening(struct packet_struct *p,struct nmb_name *nbname)
{
struct subnet_record *subrec = NULL;
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
+ if(same_net_v4(p->ip, subrec->bcast_ip, subrec->mask_ip))
break;
}
packet sent to name %s from IP %s\n",
dgram->datasize,
len,
- PTR_DIFF(buf2, dgram->data),
+ (int)PTR_DIFF(buf2, dgram->data),
nmb_namestr(&dgram->dest_name),
inet_ntoa(p->ip) ));
return;
packet sent to name %s from IP %s\n",
dgram->datasize,
len,
- PTR_DIFF(buf2, dgram->data),
+ (int)PTR_DIFF(buf2, dgram->data),
nmb_namestr(&dgram->dest_name),
inet_ntoa(p->ip) ));
return;
Validate a response nmb packet.
****************************************************************************/
-static BOOL validate_nmb_response_packet( struct nmb_packet *nmb )
+static bool validate_nmb_response_packet( struct nmb_packet *nmb )
{
- BOOL ignore = False;
+ bool ignore = False;
switch (nmb->header.opcode) {
case NMB_NAME_REG_OPCODE:
return ignore;
}
-
+
/****************************************************************************
Validate a request nmb packet.
****************************************************************************/
-static BOOL validate_nmb_packet( struct nmb_packet *nmb )
+static bool validate_nmb_packet( struct nmb_packet *nmb )
{
- BOOL ignore = False;
+ bool ignore = False;
switch (nmb->header.opcode) {
case NMB_NAME_REG_OPCODE:
/* Go through all the broadcast subnets and see if the mask matches. */
for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
+ if(same_net_v4(p->ip, subrec->bcast_ip, subrec->mask_ip))
return subrec;
}
break;
}
break;
-
+
case NMB_NAME_RELEASE_OPCODE:
if(subrec == wins_server_subnet)
wins_process_name_release_request(subrec, p);
rrec->num_msgs++;
/* Ensure we don't re-send the request. */
rrec->repeat_count = 0;
-
+
/* Call the response received function for this packet. */
(*rrec->resp_fn)(subrec, rrec, p);
}
}
free_packet(p);
}
-}
+}
/*******************************************************************
Retransmit or timeout elements from all the outgoing subnet response
for (rrec = subrec->responselist; rrec; rrec = nextrrec) {
nextrrec = rrec->next;
-
+
if (rrec->repeat_time <= t) {
if (rrec->repeat_count > 0) {
/* Resend while we have a non-zero repeat_count. */
plus the broadcast sockets.
***************************************************************************/
-static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number, int *maxfd)
+static bool create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number, int *maxfd)
{
int *sock_array = NULL;
struct subnet_record *subrec = NULL;
if((count*2) + 2 > FD_SETSIZE) {
DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
only use %d.\n", (count*2) + 2, FD_SETSIZE));
+ SAFE_FREE(pset);
return True;
}
if((sock_array = SMB_MALLOC_ARRAY(int, (count*2) + 2)) == NULL) {
DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));
+ SAFE_FREE(pset);
return True;
}
*ppset = pset;
*psock_array = sock_array;
-
+
return False;
}
return True if the socket is dead
***************************************************************************/
-BOOL listen_for_packets(BOOL run_election)
+bool listen_for_packets(bool run_election)
{
static fd_set *listen_set = NULL;
static int listen_number = 0;
int i;
static int maxfd = 0;
- fd_set fds;
+ fd_set r_fds;
+ fd_set w_fds;
int selrtn;
struct timeval timeout;
#ifndef SYNC_DNS
rescan_listen_set = False;
}
- memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
+ memcpy((char *)&r_fds, (char *)listen_set, sizeof(fd_set));
+ FD_ZERO(&w_fds);
#ifndef SYNC_DNS
dns_fd = asyncdns_fd();
if (dns_fd != -1) {
- FD_SET(dns_fd, &fds);
+ FD_SET(dns_fd, &r_fds);
maxfd = MAX( maxfd, dns_fd);
}
#endif
- /*
+ /*
* 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
timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
timeout.tv_usec = 0;
+ {
+ struct timeval now = timeval_current();
+ event_add_to_select_args(nmbd_event_context(), &now,
+ &r_fds, &w_fds, &timeout, &maxfd);
+ }
+
+ if (timeval_is_zero(&timeout)) {
+ /* Process a timed event now... */
+ if (run_events(nmbd_event_context(), 0, NULL, NULL)) {
+ return False;
+ }
+ }
+
/* Prepare for the select - allow certain signals. */
BlockSignals(False, SIGTERM);
- selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&timeout);
+ selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&timeout);
/* We can only take signals when we are in the select - block them again here. */
return False;
}
+ if (run_events(nmbd_event_context(), selrtn, &r_fds, &w_fds)) {
+ return False;
+ }
+
#ifndef SYNC_DNS
- if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) {
+ if (dns_fd != -1 && FD_ISSET(dns_fd,&r_fds)) {
run_dns_queue();
}
#endif
for(i = 0; i < listen_number; i++) {
if (i < (listen_number/2)) {
/* Processing a 137 socket. */
- if (FD_ISSET(sock_array[i],&fds)) {
+ if (FD_ISSET(sock_array[i],&r_fds)) {
struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);
if (packet) {
/*
* only is set then check it came from one of our local nets.
*/
if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) &&
- (!is_local_net(packet->ip))) {
+ (!is_local_net_v4(packet->ip))) {
DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
free_packet(packet);
- } else if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) && packet->port == global_nmb_port &&
+ } else if ((is_loopback_ip_v4(packet->ip) ||
+ ismyip_v4(packet->ip)) && packet->port == global_nmb_port &&
packet->packet.nmb.header.nm_flags.bcast) {
DEBUG(7,("discarding own bcast packet from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
}
} else {
/* Processing a 138 socket. */
- if (FD_ISSET(sock_array[i],&fds)) {
+ if (FD_ISSET(sock_array[i],&r_fds)) {
struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);
if (packet) {
/*
* only is set then check it came from one of our local nets.
*/
if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) &&
- (!is_local_net(packet->ip))) {
+ (!is_local_net_v4(packet->ip))) {
DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
free_packet(packet);
- } else if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) && packet->port == DGRAM_PORT) {
+ } else if ((is_loopback_ip_v4(packet->ip) ||
+ ismyip_v4(packet->ip)) && packet->port == DGRAM_PORT) {
DEBUG(7,("discarding own dgram packet from %s:%d\n",
inet_ntoa(packet->ip),packet->port));
free_packet(packet);
Construct and send a netbios DGRAM.
**************************************************************************/
-BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,
+bool send_mailslot(bool unique, const char *mailslot,char *buf, size_t len,
const char *srcname, int src_type,
const char *dstname, int dest_type,
struct in_addr dest_ip,struct in_addr src_ip,
int dest_port)
{
- BOOL loopback_this_packet = False;
+ bool loopback_this_packet = False;
struct packet_struct p;
struct dgram_packet *dgram = &p.packet.dgram;
char *ptr,*p2;
memset((char *)&p,'\0',sizeof(p));
- if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */
+ if(ismyip_v4(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */
loopback_this_packet = True;
/* generate_name_trn_id(); */ /* Not used, so gone, RJS */
/* DIRECT GROUP or UNIQUE datagram. */
- dgram->header.msg_type = unique ? 0x10 : 0x11;
+ dgram->header.msg_type = unique ? 0x10 : 0x11;
dgram->header.flags.node_type = M_NODE;
dgram->header.flags.first = True;
dgram->header.flags.more = False;
dgram->header.source_port = DGRAM_PORT;
dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
dgram->header.packet_offset = 0;
-
+
make_nmb_name(&dgram->source_name,srcname,src_type);
make_nmb_name(&dgram->dest_name,dstname,dest_type);
SSVAL(ptr,smb_vwv16,2);
p2 = smb_buf(ptr);
safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data));
- p2 = skip_string(p2,1);
-
+ p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2);
+
if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) {
DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n"));
return False;