r25175: Change to talloc_asprintf_append_buffer().
[jelmer/samba4-debian.git] / source / utils / nmblookup.c
index bf034b26a39b5ec9a92f7ce23c9c0b8d7da51fa2..affc38e3e7744355ef477e15332da4f2ac5e52ef 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,
    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 "dynconfig.h"
-#include "libcli/nbt/libnbt.h"
 #include "lib/cmdline/popt_common.h"
-#include "system/iconv.h"
 #include "lib/socket/socket.h"
+#include "system/network.h"
+#include "system/locale.h"
+#include "lib/socket/netif.h"
+#include "librpc/gen_ndr/nbt.h"
+#include "libcli/nbt/libnbt.h"
 
 /* command line options */
 static struct {
@@ -49,7 +50,7 @@ static const char *clean_name(TALLOC_CTX *mem_ctx, const char *name)
        char *ret = talloc_strdup(mem_ctx, name);
        int i;
        for (i=0;ret[i];i++) {
-               if (!isprint(ret[i])) ret[i] = '.';
+               if (!isprint((unsigned char)ret[i])) ret[i] = '.';
        }
        return ret;
 }
@@ -85,23 +86,23 @@ 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 void do_node_status(struct nbt_name_socket *nbtsock,
+static BOOL do_node_status(struct nbt_name_socket *nbtsock,
                           const char *addr)
 {
        struct nbt_name_status io;
@@ -132,7 +133,10 @@ static void 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 False;
 }
 
 /* do a single node query */
@@ -172,13 +176,15 @@ static NTSTATUS do_node_query(struct nbt_name_socket *nbtsock,
 }
 
 
-static void process_one(const char *name)
+static BOOL process_one(const char *name)
 {
        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
        enum nbt_name_type node_type = NBT_NAME_CLIENT;
        char *node_name, *p;
+       struct socket_address *all_zero_addr;
        struct nbt_name_socket *nbtsock;
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
+       BOOL ret = True;
 
        if (!options.case_sensitive) {
                name = strupper_talloc(tmp_ctx, name);
@@ -186,7 +192,7 @@ static void process_one(const char *name)
        
        if (options.find_master) {
                node_type = NBT_NAME_MASTER;
-               if (*name == '-') {
+               if (*name == '-' || *name == '_') {
                        name = "\01\02__MSBROWSE__\02";
                        node_type = NBT_NAME_MS;
                }
@@ -201,19 +207,28 @@ static void process_one(const char *name)
        }
 
        nbtsock = nbt_name_socket_init(tmp_ctx, NULL);
-
+       
        if (options.root_port) {
-               status = socket_listen(nbtsock->sock, "0.0.0.0", NBT_NAME_SERVICE_PORT, 0, 0);
+               all_zero_addr = socket_address_from_strings(tmp_ctx, nbtsock->sock->backend_name, 
+                                                           "0.0.0.0", NBT_NAME_SERVICE_PORT);
+               
+               if (!all_zero_addr) {
+                       talloc_free(tmp_ctx);
+                       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));
-                       return;
+                       talloc_free(tmp_ctx);
+                       return False;
                }
        }
 
        if (options.lookup_by_ip) {
-               do_node_status(nbtsock, name);
+               ret = do_node_status(nbtsock, name);
                talloc_free(tmp_ctx);
-               return;
+               return ret;
        }
 
        if (options.broadcast_address) {
@@ -224,6 +239,7 @@ static void process_one(const char *name)
                int i, num_interfaces = iface_count();
                for (i=0;i<num_interfaces;i++) {
                        const char *bcast = iface_n_bcast(i);
+                       if (bcast == NULL) continue;
                        status = do_node_query(nbtsock, bcast, node_name, node_type, True);
                        if (NT_STATUS_IS_OK(status)) break;
                }
@@ -231,54 +247,94 @@ static void process_one(const char *name)
 
        if (!NT_STATUS_IS_OK(status)) {
                printf("Lookup failed - %s\n", nt_errstr(status));
+               ret = False;
        }
 
        talloc_free(tmp_ctx);
- }
+       return ret;
+}
 
 /*
   main program
 */
-int main(int argc,char *argv[])
+int main(int argc, const char *argv[])
 {
+       BOOL ret = True;
        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 }
        };
        
-       setup_logging(argv[0], True);
-
-       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);
@@ -288,16 +344,17 @@ int main(int argc,char *argv[])
                exit(1);
        }
        
-       lp_load(dyn_CONFIGFILE,True,False,False);
-       load_interfaces();
-       
        while (poptPeekArg(pc)) {
                const char *name = poptGetArg(pc);
 
-               process_one(name);
+               ret &= process_one(name);
        }
 
        poptFreeContext(pc);
 
+       if (!ret) {
+               return 1;
+       }
+
        return 0;
 }