patch.
[ISC-Bugs #41267]
+- When handling an incorrect command line for dhcpd, dhclient or dhcrelay
+ print out a specific error message about the first error in addition
+ to the usage string. This may be disabled by editing includes/site.h.
+ [ISC-Bugs #40321]
+
Changes since 4.3.3b1
- None
DHCP Client. */
/*
- * Copyright (c) 2004-2015 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
void run_stateless(int exit_mode);
-static void usage(void);
-
static isc_result_t write_duid(struct data_string *duid);
static void add_reject(struct packet *packet);
static void dhclient_ddns_cb_free(dhcp_ddns_cb_t *ddns_cb,
char* file, int line);
+/*!
+ *
+ * \brief Print the generic usage message
+ *
+ * If the user has provided an incorrect command line print out
+ * the description of the command line. The arguments provide
+ * a way for the caller to request more specific information about
+ * the error be printed as well. Mostly this will be that some
+ * comamnd doesn't include its argument.
+ *
+ * \param sfmt - The basic string and format for the specific error
+ * \param sarg - Generally the offending argument from the comamnd line.
+ *
+ * \return Nothing
+ */
+
+#ifndef UNIT_TEST
+/* These are only used when we call usage() from the main routine
+ * which isn't compiled when building for unit tests
+ */
+static const char use_noarg[] = "No argument for command: %s";
+static const char use_v6command[] = "Command not used for DHCPv4: %s";
+#endif /* !UNIT_TEST */
+
+static void
+usage(const char *sfmt, const char *sarg)
+{
+ log_info("%s %s", message, PACKAGE_VERSION);
+ log_info(copyright);
+ log_info(arr);
+ log_info(url);
+
+ /* If desired print out the specific error message */
+#ifdef PRINT_SPECIFIC_CL_ERRORS
+ if (sfmt != NULL)
+ log_error(sfmt, sarg);
+#endif
+
+ log_fatal("Usage: %s "
+#ifdef DHCPv6
+ "[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
+#else /* DHCPv6 */
+ "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
+#endif /* DHCPv6 */
+ " [-s server-addr] [-cf config-file]\n"
+ " [-df duid-file] [-lf lease-file]\n"
+ " [-pf pid-file] [--no-pid] [-e VAR=val]\n"
+ " [-sf script-file] [interface]",
+ isc_file_basename(progname));
+}
+
#ifndef UNIT_TEST
int
main(int argc, char **argv) {
exit_mode = 1;
} else if (!strcmp(argv[i], "-p")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
local_port = validate_port(argv[i]);
log_debug("binding to user-specified port %d",
ntohs(local_port));
quiet = 0;
} else if (!strcmp(argv[i], "-pf")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
path_dhclient_pid = argv[i];
no_dhclient_pid = 1;
} else if (!strcmp(argv[i], "--no-pid")) {
no_pid_file = ISC_TRUE;
} else if (!strcmp(argv[i], "-cf")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
path_dhclient_conf = argv[i];
no_dhclient_conf = 1;
} else if (!strcmp(argv[i], "-df")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
path_dhclient_duid = argv[i];
} else if (!strcmp(argv[i], "-lf")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
path_dhclient_db = argv[i];
no_dhclient_db = 1;
} else if (!strcmp(argv[i], "-sf")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
path_dhclient_script = argv[i];
no_dhclient_script = 1;
} else if (!strcmp(argv[i], "-1")) {
quiet = 1;
} else if (!strcmp(argv[i], "-s")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
server = argv[i];
} else if (!strcmp(argv[i], "-g")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
mockup_relay = argv[i];
} else if (!strcmp(argv[i], "-nw")) {
nowait = 1;
} else if (!strcmp(argv[i], "-e")) {
struct string_list *tmp;
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
tmp = dmalloc(strlen(argv[i]) + sizeof *tmp, MDL);
if (!tmp)
log_fatal("No memory for %s", argv[i]);
#ifdef DHCPv6
} else if (!strcmp(argv[i], "-S")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
stateless = 1;
} else if (!strcmp(argv[i], "-N")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
wanted_ia_na++;
} else if (!strcmp(argv[i], "-T")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
wanted_ia_ta++;
} else if (!strcmp(argv[i], "-P")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
wanted_ia_pd++;
} else if (!strcmp(argv[i], "-R")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
} else if (!strcmp(argv[i], "-D")) {
duid_v4 = 1;
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
if (!strcasecmp(argv[i], "LL")) {
duid_type = DUID_LL;
} else if (!strcasecmp(argv[i], "LLT")) {
duid_type = DUID_LLT;
} else {
- usage();
+ usage("Unknown argument to -D: %s", argv[i]);
}
} else if (!strcmp(argv[i], "-i")) {
/* enable DUID support for DHCPv4 clients */
IGNORE_RET(write(STDERR_FILENO, "\n", 1));
exit(0);
} else if (argv[i][0] == '-') {
- usage();
+ usage("Unknown command: %s", argv[i]);
} else if (interfaces_requested < 0) {
- usage();
+ usage("No interfaces comamnd -n and "
+ " requested interface %s", argv[i]);
} else {
struct interface_info *tmp = NULL;
/* Support only one (requested) interface for Prefix Delegation. */
if (wanted_ia_pd && (interfaces_requested != 1)) {
- usage();
+ usage("PD %s only supports one requested interface", "-P");
}
if (!no_dhclient_conf && (s = getenv("PATH_DHCLIENT_CONF"))) {
if (release_mode || (wanted_ia_na > 0) ||
wanted_ia_ta || wanted_ia_pd ||
(interfaces_requested != 1)) {
- usage();
+ usage("Stateless commnad: %s incompatibile with "
+ "other commands", "-S");
}
run_stateless(exit_mode);
return 0;
}
#endif /* !UNIT_TEST */
-static void usage()
-{
- log_info("%s %s", message, PACKAGE_VERSION);
- log_info(copyright);
- log_info(arr);
- log_info(url);
-
-
- log_fatal("Usage: %s "
-#ifdef DHCPv6
- "[-4|-6] [-SNTPRI1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
-#else /* DHCPv6 */
- "[-I1dvrxi] [-nw] [-p <port>] [-D LL|LLT] \n"
-#endif /* DHCPv6 */
- " [-s server-addr] [-cf config-file]\n"
- " [-df duid-file] [-lf lease-file]\n"
- " [-pf pid-file] [--no-pid] [-e VAR=val]\n"
- " [-sf script-file] [interface]",
- isc_file_basename(progname));
-}
-
void run_stateless(int exit_mode)
{
#ifdef DHCPv6
discover_interfaces(DISCOVER_REQUESTED);
if (!interfaces)
- usage();
+ usage("No interfaces available for stateless command: %s", "-S");
/* Parse the dhclient.conf file. */
read_client_conf();
from a single server and there won't be a difference. */
/* #define USE_ORIGINAL_CLIENT_LEASE_WEIGHTS */
+/* Print out specific error messages for dhclient, dhcpd
+ or dhcrelay when processing an incorrect command line. This
+ is included for those that might require the exact error
+ messages, as we don't expect that is necessary it is on by
+ default. */
+#define PRINT_SPECIFIC_CL_ERRORS
+
/* Include definitions for various options. In general these
should be left as is, but if you have already defined one
of these and prefer your definition you can comment the
DHCP/BOOTP Relay Agent. */
/*
- * Copyright(c) 2004-2015 by Internet Systems Consortium, Inc.("ISC")
+ * Copyright(c) 2004-2016 by Internet Systems Consortium, Inc.("ISC")
* Copyright(c) 1997-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
" server0 [ ... serverN]\n\n"
#endif
-static void usage() {
+/*!
+ *
+ * \brief Print the generic usage message
+ *
+ * If the user has provided an incorrect command line print out
+ * the description of the command line. The arguments provide
+ * a way for the caller to request more specific information about
+ * the error be printed as well. Mostly this will be that some
+ * comamnd doesn't include its argument.
+ *
+ * \param sfmt - The basic string and format for the specific error
+ * \param sarg - Generally the offending argument from the comamnd line.
+ *
+ * \return Nothing
+ */
+static const char use_noarg[] = "No argument for command: %s";
+static const char use_badproto[] = "Protocol already set, %s inappropriate";
+static const char use_v4command[] = "Command not used for DHCPv6: %s";
+static const char use_v6command[] = "Command not used for DHCPv4: %s";
+
+static void
+usage(const char *sfmt, const char *sarg) {
+
+ /* If desired print out the specific error message */
+#ifdef PRINT_SPECIFIC_CL_ERRORS
+ if (sfmt != NULL)
+ log_error(sfmt, sarg);
+#endif
+
log_fatal(DHCRELAY_USAGE,
#ifdef DHCPv6
isc_file_basename(progname),
if (!strcmp(argv[i], "-4")) {
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
- usage();
+ usage(use_badproto, "-4");
}
local_family_set = 1;
local_family = AF_INET;
} else if (!strcmp(argv[i], "-6")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_badproto, "-6");
}
local_family_set = 1;
local_family = AF_INET6;
quiet_interface_discovery = 1;
} else if (!strcmp(argv[i], "-p")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
local_port = validate_port(argv[i]);
log_debug("binding to user-specified port %d",
ntohs(local_port));
} else if (!strcmp(argv[i], "-c")) {
int hcount;
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
hcount = atoi(argv[i]);
if (hcount <= 255)
max_hop_count= hcount;
else
- usage();
+ usage("Bad hop count to -c: %s", argv[i]);
} else if (!strcmp(argv[i], "-i")) {
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
- usage();
+ usage(use_v4command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET;
#endif
if (++i == argc) {
- usage();
+ usage(use_noarg, argv[i-1]);
}
if (strlen(argv[i]) >= sizeof(tmp->name)) {
log_fatal("%s: interface name too long "
} else if (!strcmp(argv[i], "-a")) {
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
- usage();
+ usage(use_v4command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET;
} else if (!strcmp(argv[i], "-A")) {
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
- usage();
+ usage(use_v4command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET;
#endif
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
dhcp_max_agent_option_packet_length = atoi(argv[i]);
} else if (!strcmp(argv[i], "-m")) {
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
- usage();
+ usage(use_v4command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET;
#endif
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
if (!strcasecmp(argv[i], "append")) {
agent_relay_mode = forward_and_append;
} else if (!strcasecmp(argv[i], "replace")) {
} else if (!strcasecmp(argv[i], "discard")) {
agent_relay_mode = discard;
} else
- usage();
+ usage("Unknown argument to -m: %s", argv[i]);
} else if (!strcmp(argv[i], "-D")) {
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
- usage();
+ usage(use_v4command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET;
#ifdef DHCPv6
} else if (!strcmp(argv[i], "-I")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
use_if_id = ISC_TRUE;
} else if (!strcmp(argv[i], "-l")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
if (downstreams != NULL)
use_if_id = ISC_TRUE;
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
sl = parse_downstream(argv[i]);
sl->next = downstreams;
downstreams = sl;
} else if (!strcmp(argv[i], "-u")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
sl = parse_upstream(argv[i]);
sl->next = upstreams;
upstreams = sl;
} else if (!strcmp(argv[i], "-s")) {
if (local_family_set && (local_family == AF_INET)) {
- usage();
+ usage(use_v6command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET6;
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
dhcrelay_sub_id = argv[i];
#endif
} else if (!strcmp(argv[i], "-pf")) {
if (++i == argc)
- usage();
+ usage(use_noarg, argv[i-1]);
path_dhcrelay_pid = argv[i];
no_dhcrelay_pid = ISC_TRUE;
} else if (!strcmp(argv[i], "--no-pid")) {
isc_file_basename(progname));
exit(0);
} else if (argv[i][0] == '-') {
- usage();
+ usage("Unknown command: %s", argv[i]);
} else {
struct hostent *he;
struct in_addr ia, *iap = NULL;
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
- usage();
+ usage(use_v4command, argv[i]);
}
local_family_set = 1;
local_family = AF_INET;
if (upstreams == NULL || downstreams == NULL) {
log_info("Must specify at least one lower "
"and one upper interface.\n");
- usage();
+ usage(NULL, NULL);
}
/* Set up the initial dhcp option universe. */
*iid++ = '\0';
}
if (strlen(ifname) >= sizeof(ifp->name)) {
- log_error("Interface name '%s' too long", ifname);
- usage();
+ usage("Interface name '%s' too long", ifname);
}
/* Don't declare twice. */
DHCP Server Daemon. */
/*
- * Copyright (c) 2004-2015 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2016 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
gid_t set_gid = 0;
#endif /* PARANOIA */
-#ifndef UNIT_TEST
-static void usage(void);
-#endif
-
struct iaddr server_identifier;
int server_identifier_matched;
#ifndef UNIT_TEST
+/*!
+ *
+ * \brief Print the generic usage message
+ *
+ * If the user has provided an incorrect command line print out
+ * the description of the command line. The arguments provide
+ * a way for the caller to request more specific information about
+ * the error be printed as well. Mostly this will be that some
+ * comamnd doesn't include its argument.
+ *
+ * \param sfmt - The basic string and format for the specific error
+ * \param sarg - Generally the offending argument from the comamnd line.
+ *
+ * \return Nothing
+ */
+static char use_noarg[] = "No argument for command: %s ";
+
+static void
+usage(const char *sfmt, const char *sarg) {
+ log_info("%s %s", message, PACKAGE_VERSION);
+ log_info(copyright);
+ log_info(arr);
+
+ /* If desired print out the specific error message */
+#ifdef PRINT_SPECIFIC_CL_ERRORS
+ if (sfmt != NULL)
+ log_error(sfmt, sarg);
+#endif
+
+ log_fatal("Usage: %s [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
+#ifdef DHCPv6
+ " [-4|-6] [-cf config-file] [-lf lease-file]\n"
+#else /* !DHCPv6 */
+ " [-cf config-file] [-lf lease-file]\n"
+#endif /* DHCPv6 */
+#if defined (PARANOIA)
+ /* meld into the following string */
+ " [-user user] [-group group] [-chroot dir]\n"
+#endif /* PARANOIA */
+#if defined (TRACING)
+ " [-tf trace-output-file]\n"
+ " [-play trace-input-file]\n"
+#endif /* TRACING */
+ " [-pf pid-file] [--no-pid] [-s server]\n"
+ " [if0 [...ifN]]",
+ isc_file_basename(progname));
+}
+
/* Note: If we add unit tests to test setup_chroot it will
* need to be moved to be outside the ifndef UNIT_TEST block.
*/
for (i = 1; i < argc; i++) {
if (!strcmp (argv [i], "-p")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
local_port = validate_port (argv [i]);
log_debug ("binding to user-specified port %d",
ntohs (local_port));
log_perror = -1;
} else if (!strcmp (argv [i], "-s")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
server = argv [i];
#if defined (PARANOIA)
} else if (!strcmp (argv [i], "-user")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
set_user = argv [i];
} else if (!strcmp (argv [i], "-group")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
set_group = argv [i];
} else if (!strcmp (argv [i], "-chroot")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
set_chroot = argv [i];
#endif /* PARANOIA */
} else if (!strcmp (argv [i], "-cf")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
path_dhcpd_conf = argv [i];
no_dhcpd_conf = 1;
} else if (!strcmp (argv [i], "-lf")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
path_dhcpd_db = argv [i];
no_dhcpd_db = 1;
} else if (!strcmp (argv [i], "-pf")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
path_dhcpd_pid = argv [i];
no_dhcpd_pid = 1;
} else if (!strcmp(argv[i], "--no-pid")) {
#if defined (TRACING)
} else if (!strcmp (argv [i], "-tf")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
traceoutfile = argv [i];
} else if (!strcmp (argv [i], "-play")) {
if (++i == argc)
- usage ();
+ usage(use_noarg, argv[i-1]);
traceinfile = argv [i];
trace_replay_init ();
#endif /* TRACING */
} else if (argv [i][0] == '-') {
- usage ();
+ usage("Unknown command %s", argv[i]);
} else {
struct interface_info *tmp =
(struct interface_info *)0;
schedule_all_ipv6_lease_timeouts();
}
-/* Print usage message. */
-#ifndef UNIT_TEST
-static void
-usage(void) {
- log_info("%s %s", message, PACKAGE_VERSION);
- log_info(copyright);
- log_info(arr);
-
- log_fatal("Usage: %s [-p <UDP port #>] [-f] [-d] [-q] [-t|-T]\n"
-#ifdef DHCPv6
- " [-4|-6] [-cf config-file] [-lf lease-file]\n"
-#else /* !DHCPv6 */
- " [-cf config-file] [-lf lease-file]\n"
-#endif /* DHCPv6 */
-#if defined (PARANOIA)
- /* meld into the following string */
- " [-user user] [-group group] [-chroot dir]\n"
-#endif /* PARANOIA */
-#if defined (TRACING)
- " [-tf trace-output-file]\n"
- " [-play trace-input-file]\n"
-#endif /* TRACING */
- " [-pf pid-file] [--no-pid] [-s server]\n"
- " [if0 [...ifN]]",
- isc_file_basename(progname));
-}
-#endif
-
void lease_pinged (from, packet, length)
struct iaddr from;
u_int8_t *packet;