s3-vfs: Use ENOATTR in errno comparison for getxattr
[garming/samba-autobuild/.git] / source4 / nbt_server / query.c
index 2d2e75d51eef207fded7c6918f554ec9f1fb6ab9..8cf387c2dcd040b13193aacbcecbc4f5d504d663 100644 (file)
@@ -7,7 +7,7 @@
    
    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/>.
 */
 
 #include "includes.h"
-#include "dlinklist.h"
+#include "../lib/util/dlinklist.h"
 #include "system/network.h"
 #include "nbt_server/nbt_server.h"
-
-/*
-  send a name query reply
-*/
-static void nbt_name_query_reply(struct nbt_name_socket *nbtsock, 
-                                struct nbt_name_packet *request_packet, 
-                                const char *src_address, int src_port,
-                                struct nbt_name *name, uint32_t ttl,
-                                uint16_t nb_flags, const char *address)
-{
-       struct nbt_name_packet *packet;
-
-       packet = talloc_zero(nbtsock, struct nbt_name_packet);
-       if (packet == NULL) return;
-
-       packet->name_trn_id = request_packet->name_trn_id;
-       packet->ancount = 1;
-       packet->operation = 
-               NBT_FLAG_REPLY | 
-               NBT_OPCODE_QUERY | 
-               NBT_FLAG_AUTHORITIVE |
-               NBT_FLAG_RECURSION_DESIRED |
-               NBT_FLAG_RECURSION_AVAIL;
-
-       packet->answers = talloc_array(packet, struct nbt_res_rec, 1);
-       if (packet->answers == NULL) goto failed;
-
-       packet->answers[0].name     = *name;
-       packet->answers[0].rr_type  = NBT_QTYPE_NETBIOS;
-       packet->answers[0].rr_class = NBT_QCLASS_IP;
-       packet->answers[0].ttl      = ttl;
-       packet->answers[0].rdata.netbios.length = 6;
-       packet->answers[0].rdata.netbios.addresses = talloc_array(packet->answers,
-                                                           struct nbt_rdata_address, 1);
-       if (packet->answers[0].rdata.netbios.addresses == NULL) goto failed;
-       packet->answers[0].rdata.netbios.addresses[0].nb_flags = nb_flags;
-       packet->answers[0].rdata.netbios.addresses[0].ipaddr = 
-               talloc_strdup(packet->answers, address);
-       if (packet->answers[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed;
-
-       DEBUG(7,("Sending name query reply for %s<%02x> at %s to %s:%d\n", 
-                name->name, name->type, src_address, address, src_port));
-       
-       nbt_name_reply_send(nbtsock, src_address, src_port, packet);
-
-failed:
-       talloc_free(packet);
-}
-
+#include "nbt_server/wins/winsserver.h"
+#include "smbd/service_task.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
+#include "lib/socket/socket.h"
+#include "param/param.h"
 
 /*
   answer a name query
 */
-void nbt_request_query(struct nbt_name_socket *nbtsock, 
-                      struct nbt_name_packet *packet, 
-                      const char *src_address, int src_port)
+void nbtd_request_query(struct nbt_name_socket *nbtsock, 
+                       struct nbt_name_packet *packet, 
+                       struct socket_address *src)
 {
-       struct nbt_interface *iface;
-       struct nbt_iface_name *iname;
+       struct nbtd_iface_name *iname;
        struct nbt_name *name;
+       struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
+                                                      struct nbtd_interface);
 
        /* see if its a node status query */
        if (packet->qdcount == 1 &&
            packet->questions[0].question_type == NBT_QTYPE_STATUS) {
-               nbt_query_status(nbtsock, packet, src_address, src_port);
-               return;
-       }
-
-       /* if its a WINS query then direct to our WINS server */
-       if ((packet->operation & NBT_FLAG_RECURSION_DESIRED) &&
-           !(packet->operation & NBT_FLAG_BROADCAST)) {
-               nbt_query_wins(nbtsock, packet, src_address, src_port);
+               nbtd_query_status(nbtsock, packet, src);
                return;
        }
 
-       /* find the interface for this query */
-       iface = nbt_iface_find(nbtsock, src_address);
-
-       NBT_ASSERT_PACKET(packet, src_address, packet->qdcount == 1);
-       NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
-       NBT_ASSERT_PACKET(packet, src_address, packet->questions[0].question_class == NBT_QCLASS_IP);
+       NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1);
+       NBTD_ASSERT_PACKET(packet, src, 
+                          packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
+       NBTD_ASSERT_PACKET(packet, src, 
+                          packet->questions[0].question_class == NBT_QCLASS_IP);
 
        /* see if we have the requested name on this interface */
        name = &packet->questions[0].name;
 
-       iname = nbt_find_iname(iface, name, NBT_NM_ACTIVE);
+       iname = nbtd_find_iname(iface, name, 0);
        if (iname == NULL) {
-               DEBUG(7,("Query for %s<%02x> from %s - not found on %s\n",
-                        name->name, name->type, src_address, iface->ip_address));
+               /* don't send negative replies to broadcast queries */
+               if (packet->operation & NBT_FLAG_BROADCAST) {
+                       return;
+               }
+
+               if (packet->operation & NBT_FLAG_RECURSION_DESIRED) {
+                       nbtd_winsserver_request(nbtsock, packet, src);
+                       return;
+               }
+
+               /* otherwise send a negative reply */
+               nbtd_negative_name_query_reply(nbtsock, packet, src);
+               return;
+       }
+
+       /*
+        * normally we should forward all queries with the
+        * recursion desired flag to the wins server, but this
+        * breaks are winsclient code, when doing mhomed registrations
+        */
+       if (!(packet->operation & NBT_FLAG_BROADCAST) &&
+          (packet->operation & NBT_FLAG_RECURSION_DESIRED) &&
+          (iname->nb_flags & NBT_NM_GROUP) &&
+          lpcfg_we_are_a_wins_server(iface->nbtsrv->task->lp_ctx)) {
+               nbtd_winsserver_request(nbtsock, packet, src);
+               return;
+       }
+
+       /* if the name is not yet active and its a broadcast query then
+          ignore it for now */
+       if (!(iname->nb_flags & NBT_NM_ACTIVE) && 
+           (packet->operation & NBT_FLAG_BROADCAST)) {
+               DEBUG(7,("Query for %s from %s - name not active yet on %s\n",
+                        nbt_name_string(packet, name), src->addr, iface->ip_address));
                return;
        }
 
-       nbt_name_query_reply(nbtsock, packet, src_address, src_port,
-                            &iname->name, iname->ttl, iname->nb_flags, 
-                            iface->ip_address);
+       nbtd_name_query_reply(nbtsock, packet, src,
+                             &iname->name, iname->ttl, iname->nb_flags, 
+                             nbtd_address_list(iface, packet));
 }