r26401: Don't cache interfaces context in libnetif.
[samba.git] / source4 / utils / nmblookup.c
index b9057d493463fb13d14f515300ec5169f74fecc9..6c849fc0dbde1e6d0d24b05813271aec8e72b91e 100644 (file)
@@ -8,7 +8,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,
@@ -17,8 +17,7 @@
    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 "lib/socket/socket.h"
 #include "system/network.h"
 #include "system/locale.h"
-#include "netif/netif.h"
+#include "lib/socket/netif.h"
 #include "librpc/gen_ndr/nbt.h"
 #include "libcli/nbt/libnbt.h"
+#include "param/param.h"
 
 /* command line options */
 static struct {
        const char *broadcast_address;
        const char *unicast_address;
-       BOOL find_master;
-       BOOL wins_lookup;
-       BOOL node_status;
-       BOOL root_port;
-       BOOL lookup_by_ip;
-       BOOL case_sensitive;
+       bool find_master;
+       bool wins_lookup;
+       bool node_status;
+       bool root_port;
+       bool lookup_by_ip;
+       bool case_sensitive;
 } options;
 
 /*
@@ -87,24 +87,24 @@ static char *node_status_flags(TALLOC_CTX *mem_ctx, uint16_t flags)
        ret = talloc_asprintf(mem_ctx, "%s %s", group, type);
 
        if (flags & NBT_NM_DEREGISTER) {
-               ret = talloc_asprintf_append(ret, " <DEREGISTERING>");
+               ret = talloc_asprintf_append_buffer(ret, " <DEREGISTERING>");
        }
        if (flags & NBT_NM_CONFLICT) {
-               ret = talloc_asprintf_append(ret, " <CONFLICT>");
+               ret = talloc_asprintf_append_buffer(ret, " <CONFLICT>");
        }
        if (flags & NBT_NM_ACTIVE) {
-               ret = talloc_asprintf_append(ret, " <ACTIVE>");
+               ret = talloc_asprintf_append_buffer(ret, " <ACTIVE>");
        }
        if (flags & NBT_NM_PERMANENT) {
-               ret = talloc_asprintf_append(ret, " <PERMANENT>");
+               ret = talloc_asprintf_append_buffer(ret, " <PERMANENT>");
        }
        
        return ret;
 }
 
 /* do a single node status */
-static BOOL do_node_status(struct nbt_name_socket *nbtsock,
-                          const char *addr)
+static bool do_node_status(struct nbt_name_socket *nbtsock,
+                          const char *addr, uint16_t port)
 {
        struct nbt_name_status io;
        NTSTATUS status;
@@ -113,6 +113,7 @@ static BOOL do_node_status(struct nbt_name_socket *nbtsock,
        io.in.name.type = NBT_NAME_CLIENT;
        io.in.name.scope = NULL;
        io.in.dest_addr = addr;
+       io.in.dest_port = port;
        io.in.timeout = 1;
        io.in.retries = 2;
 
@@ -134,18 +135,19 @@ static BOOL do_node_status(struct nbt_name_socket *nbtsock,
                       io.out.status.statistics.unit_id[3],
                       io.out.status.statistics.unit_id[4],
                       io.out.status.statistics.unit_id[5]);
-               return True;
+               return true;
        }
 
-       return False;
+       return false;
 }
 
 /* do a single node query */
 static NTSTATUS do_node_query(struct nbt_name_socket *nbtsock,
                              const char *addr, 
+                             uint16_t port,
                              const char *node_name, 
                              enum nbt_name_type node_type,
-                             BOOL broadcast)
+                             bool broadcast)
 {
        struct nbt_name_query io;
        NTSTATUS status;
@@ -155,6 +157,7 @@ static NTSTATUS do_node_query(struct nbt_name_socket *nbtsock,
        io.in.name.type = node_type;
        io.in.name.scope = NULL;
        io.in.dest_addr = addr;
+       io.in.dest_port = port;
        io.in.broadcast = broadcast;
        io.in.wins_lookup = options.wins_lookup;
        io.in.timeout = 1;
@@ -170,14 +173,15 @@ static NTSTATUS do_node_query(struct nbt_name_socket *nbtsock,
                       io.out.name.type);
        }
        if (options.node_status && io.out.num_addrs > 0) {
-               do_node_status(nbtsock, io.out.reply_addrs[0]);
+               do_node_status(nbtsock, io.out.reply_addrs[0], port);
        }
 
        return status;
 }
 
 
-static BOOL process_one(const char *name)
+static bool process_one(struct loadparm_context *lp_ctx, 
+                       struct interface *ifaces, const char *name, int nbt_port)
 {
        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
        enum nbt_name_type node_type = NBT_NAME_CLIENT;
@@ -185,7 +189,7 @@ static BOOL process_one(const char *name)
        struct socket_address *all_zero_addr;
        struct nbt_name_socket *nbtsock;
        NTSTATUS status = NT_STATUS_OK;
-       BOOL ret = True;
+       bool ret = true;
 
        if (!options.case_sensitive) {
                name = strupper_talloc(tmp_ctx, name);
@@ -215,40 +219,45 @@ static BOOL process_one(const char *name)
                
                if (!all_zero_addr) {
                        talloc_free(tmp_ctx);
-                       return False;
+                       return false;
                }
 
                status = socket_listen(nbtsock->sock, all_zero_addr, 0, 0);
                if (!NT_STATUS_IS_OK(status)) {
                        printf("Failed to bind to local port 137 - %s\n", nt_errstr(status));
                        talloc_free(tmp_ctx);
-                       return False;
+                       return false;
                }
        }
 
        if (options.lookup_by_ip) {
-               ret = do_node_status(nbtsock, name);
+               ret = do_node_status(nbtsock, name, nbt_port);
                talloc_free(tmp_ctx);
                return ret;
        }
 
        if (options.broadcast_address) {
-               status = do_node_query(nbtsock, options.broadcast_address, node_name, node_type, True);
+               status = do_node_query(nbtsock, options.broadcast_address, nbt_port,
+                                      node_name, node_type, true);
        } else if (options.unicast_address) {
-               status = do_node_query(nbtsock, options.unicast_address, node_name, node_type, False);
+               status = do_node_query(nbtsock, options.unicast_address, 
+                                      nbt_port, node_name, node_type, false);
        } else {
-               int i, num_interfaces = iface_count();
+               int i, num_interfaces;
+
+               num_interfaces = iface_count(ifaces);
                for (i=0;i<num_interfaces;i++) {
-                       const char *bcast = iface_n_bcast(i);
+                       const char *bcast = iface_n_bcast(ifaces, i);
                        if (bcast == NULL) continue;
-                       status = do_node_query(nbtsock, bcast, node_name, node_type, True);
+                       status = do_node_query(nbtsock, bcast, nbt_port, 
+                                              node_name, node_type, true);
                        if (NT_STATUS_IS_OK(status)) break;
                }
        }
 
        if (!NT_STATUS_IS_OK(status)) {
                printf("Lookup failed - %s\n", nt_errstr(status));
-               ret = False;
+               ret = false;
        }
 
        talloc_free(tmp_ctx);
@@ -258,45 +267,85 @@ static BOOL process_one(const char *name)
 /*
   main program
 */
-int main(int argc,char *argv[])
+int main(int argc, const char *argv[])
 {
-       BOOL ret = True;
+       bool ret = true;
+       struct interface *ifaces;
        poptContext pc;
+       int opt;
+       enum {
+               OPT_BROADCAST_ADDRESS   = 1000,
+               OPT_UNICAST_ADDRESS,
+               OPT_FIND_MASTER,
+               OPT_WINS_LOOKUP,
+               OPT_NODE_STATUS,
+               OPT_ROOT_PORT,
+               OPT_LOOKUP_BY_IP,
+               OPT_CASE_SENSITIVE
+       };
        struct poptOption long_options[] = {
                POPT_AUTOHELP
-               { "broadcast", 'B', POPT_ARG_STRING, &options.broadcast_address, 
-                 'B', "Specify address to use for broadcasts", "BROADCAST-ADDRESS" },
+               { "broadcast", 'B', POPT_ARG_STRING, NULL, OPT_BROADCAST_ADDRESS,
+                 "Specify address to use for broadcasts", "BROADCAST-ADDRESS" },
 
-               { "unicast", 'U', POPT_ARG_STRING, &options.unicast_address, 
-                 'U', "Specify address to use for unicast" },
+               { "unicast", 'U', POPT_ARG_STRING, NULL, OPT_UNICAST_ADDRESS,
+                 "Specify address to use for unicast", NULL },
 
-               { "master-browser", 'M', POPT_ARG_VAL, &options.find_master, 
-                 True, "Search for a master browser" },
+               { "master-browser", 'M', POPT_ARG_NONE, NULL, OPT_FIND_MASTER,
+                 "Search for a master browser", NULL },
 
-               { "wins", 'W', POPT_ARG_VAL, &options.wins_lookup, True, "Do a WINS lookup" },
+               { "wins", 'W', POPT_ARG_NONE, NULL, OPT_WINS_LOOKUP,
+                 "Do a WINS lookup", NULL },
 
-               { "status", 'S', POPT_ARG_VAL, &options.node_status
-                 True, "Lookup node status as well" },
+               { "status", 'S', POPT_ARG_NONE, NULL, OPT_NODE_STATUS
+                 "Lookup node status as well", NULL },
 
-               { "root-port", 'r', POPT_ARG_VAL, &options.root_port
-                 True, "Use root port 137 (Win95 only replies to this)" },
+               { "root-port", 'r', POPT_ARG_NONE, NULL, OPT_ROOT_PORT
+                 "Use root port 137 (Win95 only replies to this)", NULL },
 
-               { "lookup-by-ip", 'A', POPT_ARG_VAL, &options.lookup_by_ip
-                 True, "Do a node status on <name> as an IP Address" },
+               { "lookup-by-ip", 'A', POPT_ARG_NONE, NULL, OPT_LOOKUP_BY_IP
+                 "Do a node status on <name> as an IP Address", NULL },
 
-               { "case-sensitive", 0, POPT_ARG_VAL, &options.case_sensitive
-                 True, "Don't uppercase the name before sending" },
+               { "case-sensitive", 0, POPT_ARG_NONE, NULL, OPT_CASE_SENSITIVE
+                 "Don't uppercase the name before sending", NULL },
 
                POPT_COMMON_SAMBA
                { 0, 0, 0, 0 }
        };
        
-       pc = poptGetContext("nmblookup", argc, (const char **)argv, long_options, 
+       pc = poptGetContext("nmblookup", argc, argv, long_options, 
                            POPT_CONTEXT_KEEP_FIRST);
-       
+
        poptSetOtherOptionHelp(pc, "<NODE> ...");
 
-       while ((poptGetNextOpt(pc) != -1)) /* noop */ ;
+       while ((opt = poptGetNextOpt(pc)) != -1) {
+               switch(opt) {
+               case OPT_BROADCAST_ADDRESS:
+                       options.broadcast_address = poptGetOptArg(pc);
+                       break;
+               case OPT_UNICAST_ADDRESS:
+                       options.unicast_address = poptGetOptArg(pc);
+                       break;
+               case OPT_FIND_MASTER:
+                       options.find_master = true;
+                       break;
+               case OPT_WINS_LOOKUP:
+                       options.wins_lookup = true;
+                       break;
+               case OPT_NODE_STATUS:
+                       options.node_status = true;
+                       break;
+               case OPT_ROOT_PORT:
+                       options.root_port = true;
+                       break;
+               case OPT_LOOKUP_BY_IP:
+                       options.lookup_by_ip = true;
+                       break;
+               case OPT_CASE_SENSITIVE:
+                       options.case_sensitive = true;
+                       break;
+               }
+       }
 
        /* swallow argv[0] */
        poptGetArg(pc);
@@ -305,11 +354,13 @@ int main(int argc,char *argv[])
                poptPrintUsage(pc, stderr, 0);
                exit(1);
        }
+
+       load_interfaces(lp_interfaces(cmdline_lp_ctx), &ifaces);
        
        while (poptPeekArg(pc)) {
                const char *name = poptGetArg(pc);
 
-               ret &= process_one(name);
+               ret &= process_one(cmdline_lp_ctx, ifaces, name, lp_nbt_port(cmdline_lp_ctx));
        }
 
        poptFreeContext(pc);