TODO: nmbd... (doesn't compile yet)
[metze/samba/wip.git] / source3 / nmbd / nmbd_packets.c
index 0324c9dd4274402d31d2088785f79bd94f3a1762..fe21a6b509c0f9b179818c8aca282488c681febf 100644 (file)
@@ -29,8 +29,6 @@ extern int ClientNMB;
 extern int ClientDGRAM;
 extern int global_nmb_port;
 
-extern int num_response_packets;
-
 bool rescan_listen_set = False;
 
 static struct nb_packet_server *packet_server;
@@ -94,12 +92,12 @@ static int find_subnet_mailslot_fd_for_address( struct in_addr local_ip )
 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';
@@ -145,12 +143,12 @@ static void debug_browse_data(const char *outbuf, int len)
   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;
@@ -242,7 +240,7 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb
 **************************************************************************/
 
 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;
@@ -335,7 +333,7 @@ static bool initiate_name_query_packet_from_wins_server( struct packet_struct *p
 **************************************************************************/
 
 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;
 
@@ -359,7 +357,7 @@ static bool initiate_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)
+                                                    uint16_t nb_flags, struct in_addr *register_ip)
 {
        struct nmb_packet *nmb = &packet->packet.nmb;
        fstring second_ip_buf;
@@ -387,7 +385,7 @@ for name %s IP %s (bcast=%s) to IP %s\n",
 **************************************************************************/
 
 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;
 
@@ -411,7 +409,7 @@ static bool initiate_name_refresh_packet( struct packet_struct *packet,
 **************************************************************************/
 
 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;
 
@@ -484,7 +482,7 @@ struct response_record *queue_register_name( struct subnet_record *subrec,
                           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;
@@ -535,7 +533,7 @@ struct response_record *queue_register_name( struct subnet_record *subrec,
 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)
 {
@@ -602,7 +600,7 @@ struct response_record *queue_register_multihomed_name( struct subnet_record *su
                                                        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)
 {
@@ -660,7 +658,7 @@ struct response_record *queue_release_name( struct subnet_record *subrec,
                                            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)
 {
@@ -963,9 +961,10 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
                        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;
@@ -1032,7 +1031,7 @@ for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
 
 void queue_packet(struct packet_struct *packet)
 {
-       DLIST_ADD_END(packet_queue, packet, struct packet_struct *);
+       DLIST_ADD_END(packet_queue, packet);
 }
 
 /****************************************************************************
@@ -1435,15 +1434,17 @@ static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p
 
                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;
                }
 
@@ -1565,8 +1566,9 @@ static void process_nmb_response(struct packet_struct *p)
                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;
        }
 
@@ -1679,16 +1681,16 @@ on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_
 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 */
@@ -1712,29 +1714,21 @@ static bool create_listen_pollfds(struct pollfd **pfds,
                }
        }
 
-       fds = talloc_zero_array(NULL, struct pollfd, count);
-       if (fds == NULL) {
-               DEBUG(1, ("create_listen_pollfds: malloc fail for fds. "
-                         "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. "
+       attrs = talloc_zero_array(NULL, struct socket_attributes, count);
+       if (attrs == NULL) {
+               DEBUG(1, ("talloc 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;
@@ -1742,37 +1736,34 @@ static bool create_listen_pollfds(struct pollfd **pfds,
        for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
 
                if (subrec->nmb_sock != -1) {
-                       fds[num].fd = subrec->nmb_sock;
+                       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;
                }
 
                if (subrec->dgram_sock != -1) {
-                       fds[num].fd = subrec->dgram_sock;
+                       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;
 
@@ -1859,67 +1850,101 @@ static void free_processed_packet_list(struct processed_packet **pp_processed_pa
        }
 }
 
+/****************************************************************************
+ 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;
+}
+
 /****************************************************************************
   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(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(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;
        }
 
        /*
@@ -1929,26 +1954,40 @@ bool listen_for_packets(bool run_election)
         * 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
 
@@ -1959,7 +1998,7 @@ bool listen_for_packets(bool run_election)
                int client_fd;
                int client_port;
 
-               if ((fds[i].revents & (POLLIN|POLLHUP|POLLERR)) == 0) {
+               if (!attrs[i].triggered) {
                        continue;
                }
 
@@ -1977,7 +2016,7 @@ bool listen_for_packets(bool run_election)
                        client_port = DGRAM_PORT;
                }
 
-               packet = read_packet(fds[i].fd, packet_type);
+               packet = read_packet(attrs[i].fd, packet_type);
                if (!packet) {
                        continue;
                }
@@ -1987,7 +2026,7 @@ bool listen_for_packets(bool run_election)
                 * 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));
@@ -1995,21 +2034,23 @@ bool listen_for_packets(bool run_election)
                        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;
+                               }
                        }
                }
 
@@ -2024,16 +2065,17 @@ bool listen_for_packets(bool run_election)
 
                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;
 }