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;
/*******************************************************************
struct subnet_record *subrec;
for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- if(ip_equal(local_ip, subrec->myip))
+ if(ip_equal_v4(local_ip, subrec->myip))
return subrec->nmb_sock;
return ClientNMB;
struct subnet_record *subrec;
for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- if(ip_equal(local_ip, subrec->myip))
+ if(ip_equal_v4(local_ip, subrec->myip))
return subrec->dgram_sock;
return ClientDGRAM;
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;
packet->ip = to_ip;
packet->port = NMB_PORT;
- packet->fd = ClientNMB;
+ packet->recv_fd = -1;
+ packet->send_fd = ClientNMB;
packet->timestamp = time(NULL);
packet->packet_type = NMB_PACKET;
packet->locked = False;
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;
}
our standard refresh cycle for that name which copes nicely
with disconnected networks.
*/
- packet->fd = find_subnet_fd_for_address(*register_ip);
+ packet->recv_fd = -1;
+ packet->send_fd = find_subnet_fd_for_address(*register_ip);
return True;
}
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((struct sockaddr *)&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;
{
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;
}
DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip)));
- p->fd = find_subnet_fd_for_address( *ifip );
+ p->send_fd = find_subnet_fd_for_address( *ifip );
break;
}
}
/****************************************************************************
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
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 = rr_type;
nmb->answers->rr_class = RR_CLASS_IN;
nmb->answers->ttl = ttl;
-
+
if (data && len) {
+ if (len < 0 || len > sizeof(nmb->answers->rdata)) {
+ DEBUG(5,("reply_netbios_packet: "
+ "invalid packet len (%d)\n",
+ len ));
+ return;
+ }
nmb->answers->rdlength = len;
memcpy(nmb->answers->rdata, data, len);
}
-
+
packet.packet_type = NMB_PACKET;
+ packet.recv_fd = -1;
/* Ensure we send out on the same fd that the original
packet came in on to give the correct source IP address. */
- packet.fd = orig_packet->fd;
+ if (orig_packet->send_fd != -1) {
+ packet.send_fd = orig_packet->send_fd;
+ } else {
+ packet.send_fd = orig_packet->recv_fd;
+ }
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"));
Queue a packet into a packet queue
******************************************************************/
-static void queue_packet(struct packet_struct *packet)
+void queue_packet(struct packet_struct *packet)
{
struct packet_struct *p;
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;
}
pull_ascii_nstring(src_name, sizeof(src_name), dgram->source_name.name);
if (is_myname(src_name)) {
- DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \
+ DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Source name \
%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name)));
return;
}
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;
}
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 (subrec = FIRST_SUBNET; subrec; subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) {
struct response_record *rrec, *nextrrec;
+ restart:
+
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. */
no timeout function. */
remove_response_record(subrec, rrec);
}
+ /* We have changed subrec->responselist,
+ * restart from the beginning of this list. */
+ goto restart;
} /* !rrec->in_expitation_processing */
} /* rrec->repeat_count > 0 */
} /* rrec->repeat_time <= t */
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;
return True;
}
+ /* The Client* sockets */
+ count++;
+
/* Check that we can add all the fd's we need. */
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
count++;
- if((count*2) + 2 > FD_SETSIZE) {
+ /* each interface gets 4 sockets */
+ count *= 4;
+
+ if(count > FD_SETSIZE) {
DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
-only use %d.\n", (count*2) + 2, FD_SETSIZE));
+only use %d.\n", count, 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"));
+ if((sock_array = SMB_MALLOC_ARRAY(int, count)) == NULL) {
+ DEBUG(0,("create_listen_fdset: malloc fail for socket array. size %d\n", count));
+ SAFE_FREE(pset);
return True;
}
FD_ZERO(pset);
- /* Add in the broadcast socket on 137. */
+ /* Add in the lp_socket_address() interface on 137. */
FD_SET(ClientNMB,pset);
sock_array[num++] = ClientNMB;
*maxfd = MAX( *maxfd, ClientNMB);
+ /* the lp_socket_address() interface has only one socket */
+ sock_array[num++] = -1;
+
/* Add in the 137 sockets on all the interfaces. */
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
FD_SET(subrec->nmb_sock,pset);
sock_array[num++] = subrec->nmb_sock;
*maxfd = MAX( *maxfd, subrec->nmb_sock);
+
+ sock_array[num++] = subrec->nmb_bcast;
+ if (subrec->nmb_bcast != -1) {
+ FD_SET(subrec->nmb_bcast,pset);
+ *maxfd = MAX( *maxfd, subrec->nmb_bcast);
+ }
}
- /* Add in the broadcast socket on 138. */
+ /* Add in the lp_socket_address() interface on 138. */
FD_SET(ClientDGRAM,pset);
sock_array[num++] = ClientDGRAM;
*maxfd = MAX( *maxfd, ClientDGRAM);
+ /* the lp_socket_address() interface has only one socket */
+ sock_array[num++] = -1;
+
/* Add in the 138 sockets on all the interfaces. */
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
FD_SET(subrec->dgram_sock,pset);
sock_array[num++] = subrec->dgram_sock;
*maxfd = MAX( *maxfd, subrec->dgram_sock);
+
+ sock_array[num++] = subrec->dgram_bcast;
+ if (subrec->dgram_bcast != -1) {
+ FD_SET(subrec->dgram_bcast,pset);
+ *maxfd = MAX( *maxfd, subrec->dgram_bcast);
+ }
}
- *listen_number = (count*2) + 2;
+ *listen_number = count;
SAFE_FREE(*ppset);
SAFE_FREE(*psock_array);
*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
- /*
+ /* Process a signal and timer events now... */
+ if (run_events(nmbd_event_context(), 0, NULL, NULL)) {
+ return False;
+ }
+
+ /*
* 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;
- /* Prepare for the select - allow certain signals. */
-
- BlockSignals(False, SIGTERM);
-
- selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&timeout);
+ {
+ struct timeval now = timeval_current();
+ event_add_to_select_args(nmbd_event_context(), &now,
+ &r_fds, &w_fds, &timeout, &maxfd);
+ }
- /* We can only take signals when we are in the select - block them again here. */
+ selrtn = sys_select(maxfd+1,&r_fds,&w_fds,NULL,&timeout);
- BlockSignals(True, SIGTERM);
+ if (run_events(nmbd_event_context(), selrtn, &r_fds, &w_fds)) {
+ return False;
+ }
- if(selrtn == -1) {
+ if (selrtn == -1) {
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++) {
+ enum packet_type packet_type;
+ struct packet_struct *packet;
+ const char *packet_name;
+ int client_fd;
+ int client_port;
+
+ if (sock_array[i] == -1) {
+ continue;
+ }
+
+ if (!FD_ISSET(sock_array[i],&r_fds)) {
+ continue;
+ }
+
if (i < (listen_number/2)) {
- /* Processing a 137 socket. */
- if (FD_ISSET(sock_array[i],&fds)) {
- struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);
- if (packet) {
- /*
- * If we got a packet on the broadcast socket and interfaces
- * 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))) {
- 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 &&
- packet->packet.nmb.header.nm_flags.bcast) {
- DEBUG(7,("discarding own bcast packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- } else {
- /* Save the file descriptor this packet came in on. */
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- }
- }
+ /* Port 137 */
+ packet_type = NMB_PACKET;
+ packet_name = "nmb";
+ client_fd = ClientNMB;
+ client_port = global_nmb_port;
} else {
- /* Processing a 138 socket. */
- if (FD_ISSET(sock_array[i],&fds)) {
- struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);
- if (packet) {
- /*
- * If we got a packet on the broadcast socket and interfaces
- * 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))) {
- 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) {
- DEBUG(7,("discarding own dgram packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- } else {
- /* Save the file descriptor this packet came in on. */
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- }
+ /* Port 137 */
+ packet_type = DGRAM_PACKET;
+ packet_name = "dgram";
+ client_fd = ClientDGRAM;
+ client_port = DGRAM_PORT;
+ }
+
+ packet = read_packet(sock_array[i], packet_type);
+ if (!packet) {
+ continue;
+ }
+
+ /*
+ * If we got a packet on the broadcast socket and interfaces
+ * only is set then check it came from one of our local nets.
+ */
+ if (lp_bind_interfaces_only() &&
+ (sock_array[i] == client_fd) &&
+ (!is_local_net_v4(packet->ip))) {
+ DEBUG(7,("discarding %s packet sent to broadcast socket from %s:%d\n",
+ packet_name, inet_ntoa(packet->ip), packet->port));
+ free_packet(packet);
+ continue;
+ }
+
+ if ((is_loopback_ip_v4(packet->ip) || ismyip_v4(packet->ip)) &&
+ packet->port == client_port)
+ {
+ if (client_port == DGRAM_PORT) {
+ DEBUG(7,("discarding own dgram packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ continue;
}
- } /* end processing 138 socket. */
- } /* end for */
+
+ if (packet->packet.nmb.header.nm_flags.bcast) {
+ DEBUG(7,("discarding own nmb bcast packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ continue;
+ }
+ }
+
+ /*
+ * 0,2,4,... are unicast sockets
+ * 1,3,5,... are broadcast sockets
+ *
+ * on broadcast socket we only receive packets
+ * and send replies via the unicast socket.
+ *
+ * 0,1 and 2,3 and ... belong together.
+ */
+ if ((i % 2) != 0) {
+ /* this is a broadcast socket */
+ packet->send_fd = sock_array[i-1];
+ } else {
+ /* this is already a unicast socket */
+ packet->send_fd = sock_array[i];
+ }
+
+ queue_packet(packet);
+ }
+
return False;
}
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);
/* Setup the smb part. */
ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
memcpy(tmp,ptr,4);
- set_message(ptr,17,strlen(mailslot) + 1 + len,True);
+
+ if (smb_size + 17*2 + strlen(mailslot) + 1 + len > MAX_DGRAM_SIZE) {
+ DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n"));
+ return false;
+ }
+
+ cli_set_message(ptr,17,strlen(mailslot) + 1 + len,True);
memcpy(ptr,tmp,4);
SCVAL(ptr,smb_com,SMBtrans);
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;
} else {
- memcpy(p2,buf,len);
+ if (len) {
+ memcpy(p2,buf,len);
+ }
p2 += len;
}
p.ip = dest_ip;
p.port = dest_port;
- p.fd = find_subnet_mailslot_fd_for_address( src_ip );
+ p.recv_fd = -1;
+ p.send_fd = find_subnet_mailslot_fd_for_address( src_ip );
p.timestamp = time(NULL);
p.packet_type = DGRAM_PACKET;