#include "nmbd/nmbd.h"
#include "../lib/util/select.h"
#include "system/select.h"
+#include "libsmb/libsmb.h"
+#include "libsmb/unexpected.h"
extern int ClientNMB;
extern int ClientDGRAM;
Get/Set problematic nb_flags as network byte order 16 bit int.
**************************************************************************/
-uint16 get_nb_flags(char *buf)
+uint16_t get_nb_flags(char *buf)
{
- return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK);
+ return ((((uint16_t)*buf)&0xFFFF) & NB_FLGMSK);
}
-void set_nb_flags(char *buf, uint16 nb_flags)
+void set_nb_flags(char *buf, uint16_t nb_flags)
{
*buf++ = ((nb_flags & NB_FLGMSK) & 0xFF);
*buf = '\0';
Generates the unique transaction identifier
**************************************************************************/
-static uint16 name_trn_id=0;
+static uint16_t name_trn_id=0;
-static uint16 generate_name_trn_id(void)
+static uint16_t generate_name_trn_id(void)
{
if (!name_trn_id) {
- name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100);
+ name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)getpid()%(unsigned)100);
}
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
return name_trn_id;
**************************************************************************/
static bool create_and_init_additional_record(struct packet_struct *packet,
- uint16 nb_flags,
+ uint16_t nb_flags,
const struct in_addr *register_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
**************************************************************************/
static bool initiate_name_register_packet( struct packet_struct *packet,
- uint16 nb_flags, const struct in_addr *register_ip)
+ uint16_t nb_flags, const struct in_addr *register_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
**************************************************************************/
static bool initiate_multihomed_name_register_packet(struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *register_ip)
+ uint16_t nb_flags, struct in_addr *register_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
fstring second_ip_buf;
**************************************************************************/
static bool initiate_name_refresh_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *refresh_ip)
+ uint16_t nb_flags, struct in_addr *refresh_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
**************************************************************************/
static bool initiate_name_release_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *release_ip)
+ uint16_t nb_flags, struct in_addr *release_ip)
{
struct nmb_packet *nmb = &packet->packet.nmb;
register_name_fail_function fail_fn,
struct userdata_struct *userdata,
struct nmb_name *nmbname,
- uint16 nb_flags)
+ uint16_t nb_flags)
{
struct packet_struct *p;
struct response_record *rrec;
void queue_wins_refresh(struct nmb_name *nmbname,
response_function resp_fn,
timeout_response_function timeout_fn,
- uint16 nb_flags,
+ uint16_t nb_flags,
struct in_addr refresh_ip,
const char *tag)
{
register_name_fail_function fail_fn,
struct userdata_struct *userdata,
struct nmb_name *nmbname,
- uint16 nb_flags,
+ uint16_t nb_flags,
struct in_addr register_ip,
struct in_addr wins_ip)
{
release_name_fail_function fail_fn,
struct userdata_struct *userdata,
struct nmb_name *nmbname,
- uint16 nb_flags,
+ uint16_t nb_flags,
struct in_addr release_ip,
struct in_addr dest_ip)
{
return;
}
- DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \
-for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
- inet_ntoa(packet.ip), orig_nmb->header.name_trn_id));
+ DEBUG(4, ("reply_netbios_packet: sending a reply of packet type: %s "
+ "%s to ip %s for id %d\n", packet_type,
+ nmb_namestr(&orig_nmb->question.question_name),
+ inet_ntoa(packet.ip), orig_nmb->header.name_trn_id));
nmb->header.name_trn_id = orig_nmb->header.name_trn_id;
nmb->header.opcode = opcode;
void queue_packet(struct packet_struct *packet)
{
- DLIST_ADD_END(packet_queue, packet, struct packet_struct *);
+ DLIST_ADD_END(packet_queue, packet);
}
/****************************************************************************
/* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */
pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE);
- if (!strequal(scope, global_scope())) {
+ if (!strequal(scope, lp_netbios_scope())) {
DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \
-mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope()));
+mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, lp_netbios_scope()));
return;
}
/* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */
pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE);
- if (!strequal(scope, global_scope())) {
+ if (!strequal(scope, lp_netbios_scope())) {
DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \
-mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope()));
+mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, lp_netbios_scope()));
return;
}
rrec = find_response_record( &subrec, nmb->header.name_trn_id);
if(rrec == NULL) {
- DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n",
- nmb->header.name_trn_id));
+ DEBUG(3, ("find_subnet_for_nmb_packet: response "
+ "record not found for response id %d\n",
+ nmb->header.name_trn_id));
nb_packet_dispatch(packet_server, p);
return NULL;
}
if(subrec == NULL) {
- DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n",
- nmb->header.name_trn_id));
+ DEBUG(0, ("find_subnet_for_nmb_packet: subnet record "
+ "not found for response id %d\n",
+ nmb->header.name_trn_id));
return NULL;
}
return;
if(rrec == NULL) {
- DEBUG(0,("process_nmb_response: response packet received but no response record \
-found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id));
+ DEBUG(0, ("process_nmb_response: response packet received but "
+ "no response record found for id = %d. Ignoring "
+ "packet.\n", nmb->header.name_trn_id));
return;
}
struct socket_attributes {
enum packet_type type;
bool broadcast;
+ int fd;
+ bool triggered;
};
-static bool create_listen_pollfds(struct pollfd **pfds,
- struct socket_attributes **pattrs,
+static bool create_listen_array(struct socket_attributes **pattrs,
int *pnum_sockets)
{
struct subnet_record *subrec = NULL;
int count = 0;
int num = 0;
- struct pollfd *fds;
struct socket_attributes *attrs;
/* The ClientNMB and ClientDGRAM sockets */
for (subrec = FIRST_SUBNET;
subrec != NULL;
subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- count += 2; /* nmb_sock and dgram_sock */
+ if (subrec->nmb_sock != -1) {
+ count += 1;
+ }
+ if (subrec->dgram_sock != -1) {
+ count += 1;
+ }
if (subrec->nmb_bcast != -1) {
count += 1;
}
}
}
- fds = TALLOC_ZERO_ARRAY(NULL, struct pollfd, count);
- if (fds == NULL) {
- DEBUG(1, ("create_listen_pollfds: malloc fail for fds. "
+ attrs = talloc_zero_array(NULL, struct socket_attributes, count);
+ if (attrs == NULL) {
+ DEBUG(1, ("talloc fail for attrs. "
"size %d\n", count));
return true;
}
- attrs = TALLOC_ARRAY(NULL, struct socket_attributes, count);
- if (fds == NULL) {
- DEBUG(1, ("create_listen_pollfds: malloc fail for attrs. "
- "size %d\n", count));
- SAFE_FREE(fds);
- return true;
- }
-
num = 0;
- fds[num].fd = ClientNMB;
+ attrs[num].fd = ClientNMB;
attrs[num].type = NMB_PACKET;
attrs[num].broadcast = false;
num += 1;
- fds[num].fd = ClientDGRAM;
+ attrs[num].fd = ClientDGRAM;
attrs[num].type = DGRAM_PACKET;
attrs[num].broadcast = false;
num += 1;
for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- fds[num].fd = subrec->nmb_sock;
- attrs[num].type = NMB_PACKET;
- attrs[num].broadcast = false;
- num += 1;
+ if (subrec->nmb_sock != -1) {
+ attrs[num].fd = subrec->nmb_sock;
+ attrs[num].type = NMB_PACKET;
+ attrs[num].broadcast = false;
+ num += 1;
+ }
if (subrec->nmb_bcast != -1) {
- fds[num].fd = subrec->nmb_bcast;
+ attrs[num].fd = subrec->nmb_bcast;
attrs[num].type = NMB_PACKET;
attrs[num].broadcast = true;
num += 1;
}
- fds[num].fd = subrec->dgram_sock;
- attrs[num].type = DGRAM_PACKET;
- attrs[num].broadcast = false;
- num += 1;
+ if (subrec->dgram_sock != -1) {
+ attrs[num].fd = subrec->dgram_sock;
+ attrs[num].type = DGRAM_PACKET;
+ attrs[num].broadcast = false;
+ num += 1;
+ }
if (subrec->dgram_bcast != -1) {
- fds[num].fd = subrec->dgram_bcast;
+ attrs[num].fd = subrec->dgram_bcast;
attrs[num].type = DGRAM_PACKET;
attrs[num].broadcast = true;
num += 1;
}
}
- TALLOC_FREE(*pfds);
- *pfds = fds;
-
TALLOC_FREE(*pattrs);
*pattrs = attrs;
}
}
+/****************************************************************************
+ Timeout callback - just notice we timed out.
+***************************************************************************/
+
+static void nmbd_timeout_handler(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval current_time,
+ void *private_data)
+{
+ bool *got_timeout = private_data;
+ *got_timeout = true;
+}
+
+/****************************************************************************
+ fd callback - remember the fd that triggered.
+***************************************************************************/
+
+static void nmbd_fd_handler(struct tevent_context *ev,
+ struct tevent_fd *fde,
+ uint16_t flags,
+ void *private_data)
+{
+ struct socket_attributes *attr = private_data;
+ attr->triggered = true;
+}
+
+/*******************************************************************
+ Read a packet from a socket and parse it, returning a packet ready
+ to be used or put on the queue. This assumes a UDP socket.
+******************************************************************/
+
+static struct packet_struct *read_packet(int fd,enum packet_type packet_type)
+{
+ struct packet_struct *packet;
+ struct sockaddr_storage sa;
+ struct sockaddr_in *si = (struct sockaddr_in *)&sa;
+ char buf[MAX_DGRAM_SIZE];
+ int length;
+
+ length = read_udp_v4_socket(fd,buf,sizeof(buf),&sa);
+ if (length < MIN_DGRAM_SIZE || sa.ss_family != AF_INET) {
+ return NULL;
+ }
+
+ packet = parse_packet(buf,
+ length,
+ packet_type,
+ si->sin_addr,
+ ntohs(si->sin_port));
+ if (!packet)
+ return NULL;
+
+ packet->recv_fd = fd;
+ packet->send_fd = -1;
+
+ DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
+ length, inet_ntoa(packet->ip), packet->port ) );
+
+ return(packet);
+}
+
/****************************************************************************
Listens for NMB or DGRAM packets, and queues them.
return True if the socket is dead
***************************************************************************/
-bool listen_for_packets(bool run_election)
+bool listen_for_packets(struct messaging_context *msg, bool run_election)
{
- static struct pollfd *fds = NULL;
static struct socket_attributes *attrs = NULL;
static int listen_number = 0;
int num_sockets;
int i;
+ int loop_rtn;
+ int timeout_secs;
- int pollrtn;
- int timeout;
#ifndef SYNC_DNS
int dns_fd;
int dns_pollidx = -1;
#endif
struct processed_packet *processed_packet_list = NULL;
+ struct tevent_timer *te = NULL;
+ bool got_timeout = false;
+ TALLOC_CTX *frame = talloc_stackframe();
- if ((fds == NULL) || rescan_listen_set) {
- if (create_listen_pollfds(&fds, &attrs, &listen_number)) {
+ if ((attrs == NULL) || rescan_listen_set) {
+ if (create_listen_array(&attrs, &listen_number)) {
DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
+ TALLOC_FREE(frame);
return True;
}
rescan_listen_set = False;
}
- /*
- * "fds" can be enlarged by event_add_to_poll_args
- * below. Shrink it again to what was given to us by
- * create_listen_pollfds.
- */
-
- fds = TALLOC_REALLOC_ARRAY(NULL, fds, struct pollfd, listen_number);
- if (fds == NULL) {
- return true;
- }
num_sockets = listen_number;
#ifndef SYNC_DNS
dns_fd = asyncdns_fd();
if (dns_fd != -1) {
- fds = TALLOC_REALLOC_ARRAY(NULL, fds, struct pollfd, num_sockets+1);
- if (fds == NULL) {
+ attrs = talloc_realloc(NULL,
+ attrs,
+ struct socket_attributes,
+ num_sockets + 1);
+ if (attrs == NULL) {
+ TALLOC_FREE(frame);
return true;
}
dns_pollidx = num_sockets;
- fds[num_sockets].fd = dns_fd;
+ attrs[dns_pollidx].fd = dns_fd;
+ /*
+ * dummy values, we only need
+ * fd and triggered.
+ */
+ attrs[dns_pollidx].type = NMB_PACKET;
+ attrs[dns_pollidx].broadcast = false;
num_sockets += 1;
}
#endif
for (i=0; i<num_sockets; i++) {
- fds[i].events = POLLIN|POLLHUP;
- }
-
- /* Process a signal and timer events now... */
- if (run_events_poll(nmbd_event_context(), 0, NULL, 0)) {
- return False;
+ struct tevent_fd *tfd = tevent_add_fd(nmbd_event_context(),
+ frame,
+ attrs[i].fd,
+ TEVENT_FD_READ,
+ nmbd_fd_handler,
+ &attrs[i]);
+ if (tfd == NULL) {
+ TALLOC_FREE(frame);
+ return true;
+ }
+ attrs[i].triggered = false;
}
/*
* the time we are expecting the next netbios packet.
*/
- timeout = ((run_election||num_response_packets)
- ? 1 : NMBD_SELECT_LOOP) * 1000;
+ if (run_election||num_response_packets) {
+ timeout_secs = 1;
+ } else {
+ timeout_secs = NMBD_SELECT_LOOP;
+ }
- event_add_to_poll_args(nmbd_event_context(), NULL,
- &fds, &num_sockets, &timeout);
+ te = tevent_add_timer(nmbd_event_context(),
+ frame,
+ tevent_timeval_current_ofs(timeout_secs, 0),
+ nmbd_timeout_handler,
+ &got_timeout);
+ if (te == NULL) {
+ TALLOC_FREE(frame);
+ return true;
+ }
- pollrtn = sys_poll(fds, num_sockets, timeout);
+ loop_rtn = tevent_loop_once(nmbd_event_context());
- if (run_events_poll(nmbd_event_context(), pollrtn, fds, num_sockets)) {
- return False;
+ if (loop_rtn == -1) {
+ TALLOC_FREE(frame);
+ return true;
}
- if (pollrtn == -1) {
- return False;
+ if (got_timeout) {
+ TALLOC_FREE(frame);
+ return false;
}
#ifndef SYNC_DNS
if ((dns_fd != -1) && (dns_pollidx != -1) &&
- (fds[dns_pollidx].revents & (POLLIN|POLLHUP|POLLERR))) {
- run_dns_queue();
+ attrs[dns_pollidx].triggered){
+ run_dns_queue(msg);
+ TALLOC_FREE(frame);
+ return false;
}
#endif
int client_fd;
int client_port;
- if ((fds[i].revents & (POLLIN|POLLHUP|POLLERR)) == 0) {
+ if (!attrs[i].triggered) {
continue;
}
client_port = DGRAM_PORT;
}
- packet = read_packet(fds[i].fd, packet_type);
+ packet = read_packet(attrs[i].fd, packet_type);
if (!packet) {
continue;
}
* only is set then check it came from one of our local nets.
*/
if (lp_bind_interfaces_only() &&
- (fds[i].fd == client_fd) &&
+ (attrs[i].fd == 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));
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;
- }
-
- 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;
+ if (!IS_DC) {
+ 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;
+ }
+
+ 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;
+ }
}
}
if (attrs[i].broadcast) {
/* this is a broadcast socket */
- packet->send_fd = fds[i-1].fd;
+ packet->send_fd = attrs[i-1].fd;
} else {
/* this is already a unicast socket */
- packet->send_fd = fds[i].fd;
+ packet->send_fd = attrs[i].fd;
}
queue_packet(packet);
}
free_processed_packet_list(&processed_packet_list);
+ TALLOC_FREE(frame);
return False;
}