Browse Source

[1324]
Added braces around some single-line if blocks missed in the previous
coding-guidelines changes
Further work on BIND9 style conformance, where it doesn't contradict BIND10
style. Not yet complete.
Added comments in headers and source files
Added BIND10 headers to remaining files
Removed debugging code left in
Added more gtests, for option combinations
Removed files that are not part of currently tested code base
Addressed other requirements from code review (not yet complete)

John DuBois 13 years ago
parent
commit
d85912df5e

+ 0 - 27
tests/tools/perfdhcp/Makefile.am

@@ -1,28 +1 @@
 SUBDIRS = . tests
-
-AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
-AM_CPPFLAGS += -I$(top_srcdir)/src/lib/log -I$(top_builddir)/src/lib/log
-AM_CPPFLAGS += $(BOOST_INCLUDES)
-
-AM_CXXFLAGS = $(B10_CXXFLAGS)
-
-if USE_STATIC_LINK
-AM_LDFLAGS = -static
-endif
-
-CLEANFILES = *.gcno *.gcda
-
-noinst_PROGRAMS  = perfdhcp
-perfdhcp_SOURCES  = perfdhcp.cc
-perfdhcp_SOURCES += packetdisp.c
-perfdhcp_SOURCES += externals.cc
-perfdhcp_SOURCES += perfdhcp.h
-perfdhcp_SOURCES += dhcp.h dhcp6.h
-perfdhcp_SOURCES += cloptions.cc
-perfdhcp_SOURCES += dkdebug.cc dkdebug.h
-perfdhcp_SOURCES += procconf.h procconf.cc
-
-perfdhcp_CXXFLAGS = $(AM_CXXFLAGS)
-if USE_CLANGPP
-perfdhcp_CXXFLAGS += -Wno-error
-endif

+ 27 - 24
tests/tools/perfdhcp/cloptions.cc

@@ -46,53 +46,56 @@ perfdhcp [-hv] [-4|-6] [-r<rate>] [-n<num-request>] [-p<test-period>]\n\
 
     /* Names of configuration variables, for defaults file processor */
     confvar_t optConf[] = {
-        { 'h', NULL,        CF_SWITCH,  NULL,       0 },
-        { 'v', NULL,        CF_SWITCH,  NULL,       0 },
-        { '4', NULL,        CF_SWITCH,  &v4,        1 },
-        { '6', NULL,        CF_SWITCH,  &v6,        1 },
-        { 'i', NULL,        CF_SWITCH,  NULL,       1 },
-        { 'l', NULL,        CF_NE_STRING,   &localName, 0 },
-        { 'r', NULL,        CF_POS_INT, NULL,       0 },
-        { 'x', NULL,        CF_STRING,  NULL,       0 },
-        { 'd', NULL,        CF_POS_FLOAT,   &dropTime,  0 },
-        { 'D', NULL,        CF_NE_STRING,   &maxDropOpt,    0 },
-        { 'n', NULL,        CF_POS_INT, NULL,       0 },
-        { 'p', NULL,        CF_POS_FLOAT,   &testPeriod,    0 },
-        { '\0', NULL,           CF_ENDLIST, NULL,       0 }
+        { 'h', NULL,        CF_SWITCH,    NULL,        0 },
+        { 'v', NULL,        CF_SWITCH,    NULL,        0 },
+        { '4', NULL,        CF_SWITCH,    &v4,         1 },
+        { '6', NULL,        CF_SWITCH,    &v6,         1 },
+        { 'i', NULL,        CF_SWITCH,    NULL,        1 },
+        { 'l', NULL,        CF_NE_STRING, &localName,  0 },
+        { 'r', NULL,        CF_POS_INT,   NULL,        0 },
+        { 'x', NULL,        CF_STRING,    NULL,        0 },
+        { 'd', NULL,        CF_POS_FLOAT, &dropTime,   0 },
+        { 'D', NULL,        CF_NE_STRING, &maxDropOpt, 0 },
+        { 'n', NULL,        CF_POS_INT,   NULL,        0 },
+        { 'p', NULL,        CF_POS_FLOAT, &testPeriod, 0 },
+        { '\0', NULL,       CF_ENDLIST,   NULL,        0 }
     };
 
     /* Process command line options and config file */
-    msg = procOpts(&argc, &argv, optConf, confdata, NULL, progName, NULL);
+    msg = procOpts(&argc, &argv, optConf, confdata, progName, NULL);
     if (msg != NULL) {
         fprintf(stderr, "%s: %s\n", progName, msg);
-        return 2;
+        return(2);
     }
 
     if (confdata->map['h']->num > 0) {
         printHelp(progName, usage);
-        return 0;
+        return(0);
     }
     if (confdata->map['v']->num > 0) {
         printf("dhcpperf v1.0 2011-10-30\n");
-        return 0;
+        return(0);
     }
 
     if (v4 && v6) {
         fprintf(stderr, "%s: Must not give -4 and -6 together.\n", progName);
-        return 2;
+        return(2);
     }
     switch (argc) {
     case 0:
         if (v6 && localName != NULL) {
             *server = "all";
         } else {
-            if (v6)
-                fprintf(stderr, "%s: Use -l to specify an interface name.\n\%s\n",
+            if (v6) {
+                fprintf(stderr,
+                        "%s: Use -l to specify an interface name.\n\%s\n",
                         progName, usage);
+            }
             else {
-                fprintf(stderr, "%s: Must specify a DHCP server.\n\%s\n", progName, usage);
+                fprintf(stderr, "%s: Must specify a DHCP server.\n\%s\n",
+                        progName, usage);
             }
-            return 2;
+            return(2);
         }
         break;
     case 1:
@@ -100,9 +103,9 @@ perfdhcp [-hv] [-4|-6] [-r<rate>] [-n<num-request>] [-p<test-period>]\n\
         break;
     default:
         fprintf(stderr, "%s: Too many arguments.\n\%s\n", progName, usage);
-        return 2;
+        return(2);
     }
-    return 1;
+    return(1);
 }
 
 static void

+ 37 - 0
tests/tools/perfdhcp/cloptions.h

@@ -1,5 +1,42 @@
+/*
+ * Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef CLOPTIONS_H
+#define CLOPTIONS_H
+
 #include <stdint.h>
 #include "procconf.h"
 
+/*
+ * Process the options/arguments passed to the program.
+ *
+ * Input varibles:
+ * argc, argv: Command line data.
+ *
+ * Output variables:
+ * confdata; Processed command line data.
+ * server: The server to contact.  This will always be set, either to the given
+ *     value or to "all" (see usage).
+ *
+ * Return value:
+ * 0 if the command has been satisfied and the program should exit 0.
+ * 2 for usage error, in which case an error message will have been printed.
+ * 1 if argument processing was successful and the program should continue.
+ */
 int procArgs(int argc, const char* argv[], confdata_t* confdata,
              const char** server);
+
+#endif

+ 3 - 3
tests/tools/perfdhcp/dkdebug.cc

@@ -32,10 +32,10 @@ dk_setup(const char* diag_str, const struct dkdesc* diags) {
                 break;
             }
             if (diags[i].keyletter == '\0') {
-                return 0;
+                return(0);
             }
         }
-    return 1;
+    return(1);
 }
 
 void
@@ -56,5 +56,5 @@ vdkprintf(unsigned diag_req, const char format[], va_list ap) {
 
 int
 dk_set(unsigned diag_req) {
-    return diag_req & dk_diag_mask;
+    return(diag_req & dk_diag_mask);
 }

+ 21 - 0
tests/tools/perfdhcp/dkdebug.h

@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef DKDEBUG_H
+#define DKDEBUG_H
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -19,3 +38,5 @@ int dk_set(unsigned diag_req);
 #ifdef __cplusplus
 }
 #endif
+
+#endif

+ 0 - 24
tests/tools/perfdhcp/externals.cc

@@ -1,24 +0,0 @@
-// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include "perfdhcp.h"
-#include "cloptions.h"
-
-int v6 = 0;
-int initialOnly = 0;
-const char *localName = NULL;
-unsigned rate = 0;
-unsigned numRequest = 0;
-const char *server = NULL;
-const char *diagSelector = "";

+ 0 - 404
tests/tools/perfdhcp/packetdisp.c

@@ -1,404 +0,0 @@
-/*
- * Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <strings.h>
-#include <string.h>
-#include "perfdhcp.h"
-#include "dkdebug.h"
-
-static const char * enum_lookup(const char * const table[], size_t size, unsigned index);
-static const char *optionName(int v6, unsigned optnum);
-static void printOption(int v6, unsigned optnum, size_t len, const unsigned char *value);
-static void print_dhcpv4_packet(const struct dhcp_packet *pkt, size_t len);
-static void print_dhcpv6_packet(const struct dhcpv6_packet *pkt, size_t len);
-
-typedef enum {
-    T_UNK,
-    T_STRING,
-    T_PERIOD,
-    T_IPADDR,
-    T_MTYPE,
-    T_STATUS
-} opt_type;
-
-struct dhcp_option_desc {
-    char *name;
-    opt_type type;
-};
-
-static struct dhcp_option_desc option_desc[] = {
-[DHO_PAD] = { "PAD", T_UNK },
-[DHO_SUBNET_MASK] = { "SUBNET_MASK", T_UNK },
-[DHO_TIME_OFFSET] = { "TIME_OFFSET", T_PERIOD },
-[DHO_ROUTERS] = { "ROUTERS", T_IPADDR },
-[DHO_TIME_SERVERS] = { "TIME_SERVERS", T_UNK },
-[DHO_NAME_SERVERS] = { "NAME_SERVERS", T_UNK },
-[DHO_DOMAIN_NAME_SERVERS] = { "DOMAIN_NAME_SERVERS", T_IPADDR },
-[DHO_LOG_SERVERS] = { "LOG_SERVERS", T_UNK },
-[DHO_COOKIE_SERVERS] = { "COOKIE_SERVERS", T_UNK },
-[DHO_LPR_SERVERS] = { "LPR_SERVERS", T_IPADDR },
-[DHO_IMPRESS_SERVERS] = { "IMPRESS_SERVERS", T_UNK },
-[DHO_RESOURCE_LOCATION_SERVERS] = { "RESOURCE_LOCATION_SERVERS", T_UNK },
-[DHO_HOST_NAME] = { "HOST_NAME", T_UNK },
-[DHO_BOOT_SIZE] = { "BOOT_SIZE", T_UNK },
-[DHO_MERIT_DUMP] = { "MERIT_DUMP", T_UNK },
-[DHO_DOMAIN_NAME] = { "DOMAIN_NAME", T_STRING },
-[DHO_SWAP_SERVER] = { "SWAP_SERVER", T_UNK },
-[DHO_ROOT_PATH] = { "ROOT_PATH", T_UNK },
-[DHO_EXTENSIONS_PATH] = { "EXTENSIONS_PATH", T_UNK },
-[DHO_IP_FORWARDING] = { "IP_FORWARDING", T_UNK },
-[DHO_NON_LOCAL_SOURCE_ROUTING] = { "NON_LOCAL_SOURCE_ROUTING", T_UNK },
-[DHO_POLICY_FILTER] = { "POLICY_FILTER", T_UNK },
-[DHO_MAX_DGRAM_REASSEMBLY] = { "MAX_DGRAM_REASSEMBLY", T_UNK },
-[DHO_DEFAULT_IP_TTL] = { "DEFAULT_IP_TTL", T_UNK },
-[DHO_PATH_MTU_AGING_TIMEOUT] = { "PATH_MTU_AGING_TIMEOUT", T_UNK },
-[DHO_PATH_MTU_PLATEAU_TABLE] = { "PATH_MTU_PLATEAU_TABLE", T_UNK },
-[DHO_INTERFACE_MTU] = { "INTERFACE_MTU", T_UNK },
-[DHO_ALL_SUBNETS_LOCAL] = { "ALL_SUBNETS_LOCAL", T_UNK },
-[DHO_BROADCAST_ADDRESS] = { "BROADCAST_ADDRESS", T_UNK },
-[DHO_PERFORM_MASK_DISCOVERY] = { "PERFORM_MASK_DISCOVERY", T_UNK },
-[DHO_MASK_SUPPLIER] = { "MASK_SUPPLIER", T_UNK },
-[DHO_ROUTER_DISCOVERY] = { "ROUTER_DISCOVERY", T_UNK },
-[DHO_ROUTER_SOLICITATION_ADDRESS] = { "ROUTER_SOLICITATION_ADDRESS", T_UNK },
-[DHO_STATIC_ROUTES] = { "STATIC_ROUTES", T_UNK },
-[DHO_TRAILER_ENCAPSULATION] = { "TRAILER_ENCAPSULATION", T_UNK },
-[DHO_ARP_CACHE_TIMEOUT] = { "ARP_CACHE_TIMEOUT", T_UNK },
-[DHO_IEEE802_3_ENCAPSULATION] = { "IEEE802_3_ENCAPSULATION", T_UNK },
-[DHO_DEFAULT_TCP_TTL] = { "DEFAULT_TCP_TTL", T_UNK },
-[DHO_TCP_KEEPALIVE_INTERVAL] = { "TCP_KEEPALIVE_INTERVAL", T_UNK },
-[DHO_TCP_KEEPALIVE_GARBAGE] = { "TCP_KEEPALIVE_GARBAGE", T_UNK },
-[DHO_NIS_DOMAIN] = { "NIS_DOMAIN", T_UNK },
-[DHO_NIS_SERVERS] = { "NIS_SERVERS", T_UNK },
-[DHO_NTP_SERVERS] = { "NTP_SERVERS", T_IPADDR },
-[DHO_VENDOR_ENCAPSULATED_OPTIONS] = { "VENDOR_ENCAPSULATED_OPTIONS", T_UNK },
-[DHO_NETBIOS_NAME_SERVERS] = { "NETBIOS_NAME_SERVERS", T_UNK },
-[DHO_NETBIOS_DD_SERVER] = { "NETBIOS_DD_SERVER", T_UNK },
-[DHO_NETBIOS_NODE_TYPE] = { "NETBIOS_NODE_TYPE", T_UNK },
-[DHO_NETBIOS_SCOPE] = { "NETBIOS_SCOPE", T_UNK },
-[DHO_FONT_SERVERS] = { "FONT_SERVERS", T_UNK },
-[DHO_X_DISPLAY_MANAGER] = { "X_DISPLAY_MANAGER", T_UNK },
-[DHO_DHCP_REQUESTED_ADDRESS] = { "DHCP_REQUESTED_ADDRESS", T_IPADDR },
-[DHO_DHCP_LEASE_TIME] = { "DHCP_LEASE_TIME", T_PERIOD },
-[DHO_DHCP_OPTION_OVERLOAD] = { "DHCP_OPTION_OVERLOAD", T_UNK },
-[DHO_DHCP_MESSAGE_TYPE] = { "DHCP_MESSAGE_TYPE", T_MTYPE },
-[DHO_DHCP_SERVER_IDENTIFIER] = { "DHCP_SERVER_IDENTIFIER", T_UNK },
-[DHO_DHCP_PARAMETER_REQUEST_LIST] = { "DHCP_PARAMETER_REQUEST_LIST", T_UNK },
-[DHO_DHCP_MESSAGE] = { "DHCP_MESSAGE", T_UNK },
-[DHO_DHCP_MAX_MESSAGE_SIZE] = { "DHCP_MAX_MESSAGE_SIZE", T_UNK },
-[DHO_DHCP_RENEWAL_TIME] = { "DHCP_RENEWAL_TIME", T_UNK },
-[DHO_DHCP_REBINDING_TIME] = { "DHCP_REBINDING_TIME", T_UNK },
-[DHO_VENDOR_CLASS_IDENTIFIER] = { "VENDOR_CLASS_IDENTIFIER", T_UNK },
-[DHO_DHCP_CLIENT_IDENTIFIER] = { "DHCP_CLIENT_IDENTIFIER", T_UNK },
-[DHO_NWIP_DOMAIN_NAME] = { "NWIP_DOMAIN_NAME", T_UNK },
-[DHO_NWIP_SUBOPTIONS] = { "NWIP_SUBOPTIONS", T_UNK },
-[DHO_USER_CLASS] = { "USER_CLASS", T_UNK },
-[DHO_USER_CLASS] = { "USER_CLASS", T_UNK },
-[DHO_FQDN] = { "FQDN", T_UNK },
-[DHO_DHCP_AGENT_OPTIONS] = { "DHCP_AGENT_OPTIONS", T_UNK },
-[DHO_AUTHENTICATE] = { "AUTHENTICATE", T_UNK },
-[DHO_CLIENT_LAST_TRANSACTION_TIME] = { "CLIENT_LAST_TRANSACTION_TIME", T_UNK },
-[DHO_ASSOCIATED_IP] = { "ASSOCIATED_IP", T_UNK },
-[DHO_SUBNET_SELECTION] = { "SUBNET_SELECTION", T_UNK },
-[DHO_DOMAIN_SEARCH] = { "DOMAIN_SEARCH", T_UNK },
-[DHO_VIVCO_SUBOPTIONS] = { "VIVCO_SUBOPTIONS", T_UNK },
-[DHO_VIVSO_SUBOPTIONS] = { "VIVSO_SUBOPTIONS", T_UNK },
-[DHO_END] = { "END", T_UNK },
-[64] = { "NIS Domain", T_UNK },
-[65] = { "NIS Servers", T_UNK },
-[66] = { "TFTP Server", T_UNK },
-[67] = { "Bootfile name", T_UNK },
-[68] = { "Mobile IP Home Agent", T_UNK },
-[69] = { "SMTP Server", T_IPADDR },
-[70] = { "POP Server", T_IPADDR },
-[71] = { "NNTP Server", T_IPADDR },
-[72] = { "WWW Server", T_IPADDR },
-[73] = { "Finger Server", T_IPADDR },
-[74] = { "IRC Server", T_IPADDR },
-[75] = { "StreetTalk Server", T_IPADDR },
-[76] = { "StreetTalk Directory Assistance Server", T_IPADDR }
-};
-
-static const char * const message_types[] = {
-    [DHCPDISCOVER] = "DHCPDISCOVER",
-    [DHCPOFFER] = "DHCPOFFER",
-    [DHCPREQUEST] = "DHCPREQUEST",
-    [DHCPDECLINE] = "DHCPDECLINE",
-    [DHCPACK] = "DHCPACK",
-    [DHCPNAK] = "DHCPNAK",
-    [DHCPRELEASE] = "DHCPRELEASE",
-    [DHCPINFORM] = "DHCPINFORM",
-    [DHCPLEASEQUERY] = "DHCPLEASEQUERY",
-    [DHCPLEASEUNASSIGNED] = "DHCPLEASEUNASSIGNED",
-    [DHCPLEASEUNKNOWN] = "DHCPLEASEUNKNOWN",
-    [DHCPLEASEACTIVE] = "DHCPLEASEACTIVE"
-};
-
-static struct dhcp_option_desc option6_desc[] = {
-    [D6O_CLIENTID] = { "D6O_CLIENTID", T_UNK },
-    [D6O_SERVERID] = { "D6O_SERVERID", T_UNK },
-    [D6O_IA_NA] = { "D6O_IA_NA", T_UNK },
-    [D6O_IA_TA] = { "D6O_IA_TA", T_UNK },
-    [D6O_IAADDR] = { "D6O_IAADDR", T_UNK },
-    [D6O_ORO] = { "D6O_ORO", T_UNK },
-    [D6O_PREFERENCE] = { "D6O_PREFERENCE", T_UNK },
-    [D6O_ELAPSED_TIME] = { "D6O_ELAPSED_TIME", T_PERIOD },
-    [D6O_RELAY_MSG] = { "D6O_RELAY_MSG", T_UNK },
-    [D6O_AUTH] = { "D6O_AUTH", T_UNK },
-    [D6O_UNICAST] = { "D6O_UNICAST", T_UNK },
-    [D6O_STATUS_CODE] = { "D6O_STATUS_CODE", T_STATUS },
-    [D6O_RAPID_COMMIT] = { "D6O_RAPID_COMMIT", T_UNK },
-    [D6O_USER_CLASS] = { "D6O_USER_CLASS", T_UNK },
-    [D6O_VENDOR_CLASS] = { "D6O_VENDOR_CLASS", T_UNK },
-    [D6O_VENDOR_OPTS] = { "D6O_VENDOR_OPTS", T_UNK },
-    [D6O_INTERFACE_ID] = { "D6O_INTERFACE_ID", T_UNK },
-    [D6O_RECONF_MSG] = { "D6O_RECONF_MSG", T_UNK },
-    [D6O_RECONF_ACCEPT] = { "D6O_RECONF_ACCEPT", T_UNK },
-    [D6O_SIP_SERVERS_DNS] = { "D6O_SIP_SERVERS_DNS", T_UNK },
-    [D6O_SIP_SERVERS_ADDR] = { "D6O_SIP_SERVERS_ADDR", T_UNK },
-    [D6O_NAME_SERVERS] = { "D6O_NAME_SERVERS", T_IPADDR },
-    [D6O_DOMAIN_SEARCH] = { "D6O_DOMAIN_SEARCH", T_UNK },
-    [D6O_IA_PD] = { "D6O_IA_PD", T_UNK },
-    [D6O_IAPREFIX] = { "D6O_IAPREFIX", T_UNK },
-    [D6O_NIS_SERVERS] = { "D6O_NIS_SERVERS", T_UNK },
-    [D6O_NISP_SERVERS] = { "D6O_NISP_SERVERS", T_UNK },
-    [D6O_NIS_DOMAIN_NAME] = { "D6O_NIS_DOMAIN_NAME", T_UNK },
-    [D6O_NISP_DOMAIN_NAME] = { "D6O_NISP_DOMAIN_NAME", T_UNK },
-    [D6O_SNTP_SERVERS] = { "D6O_SNTP_SERVERS", T_UNK },
-    [D6O_INFORMATION_REFRESH_TIME] = { "D6O_INFORMATION_REFRESH_TIME", T_UNK },
-    [D6O_BCMCS_SERVER_D] = { "D6O_BCMCS_SERVER_D", T_UNK },
-    [D6O_BCMCS_SERVER_A] = { "D6O_BCMCS_SERVER_A", T_UNK },
-    [D6O_GEOCONF_CIVIC] = { "D6O_GEOCONF_CIVIC", T_UNK },
-    [D6O_REMOTE_ID] = { "D6O_REMOTE_ID", T_UNK },
-    [D6O_SUBSCRIBER_ID] = { "D6O_SUBSCRIBER_ID", T_UNK },
-    [D6O_CLIENT_FQDN] = { "D6O_CLIENT_FQDN", T_UNK },
-    [D6O_PANA_AGENT] = { "D6O_PANA_AGENT", T_UNK },
-    [D6O_NEW_POSIX_TIMEZONE] = { "D6O_NEW_POSIX_TIMEZONE", T_UNK },
-    [D6O_NEW_TZDB_TIMEZONE] = { "D6O_NEW_TZDB_TIMEZONE", T_UNK },
-    [D6O_ERO] = { "D6O_ERO", T_UNK },
-    [D6O_LQ_QUERY] = { "D6O_LQ_QUERY", T_UNK },
-    [D6O_CLIENT_DATA] = { "D6O_CLIENT_DATA", T_UNK },
-    [D6O_CLT_TIME] = { "D6O_CLT_TIME", T_UNK },
-    [D6O_LQ_RELAY_DATA] = { "D6O_LQ_RELAY_DATA", T_UNK },
-    [D6O_LQ_CLIENT_LINK] = { "D6O_LQ_CLIENT_LINK", T_UNK }
-};
-
-static const char * const message6_types[] = {
-    [DHCPV6_SOLICIT] = "DHCPV6_SOLICIT",
-    [DHCPV6_ADVERTISE] = "DHCPV6_ADVERTISE",
-    [DHCPV6_REQUEST] = "DHCPV6_REQUEST",
-    [DHCPV6_CONFIRM] = "DHCPV6_CONFIRM",
-    [DHCPV6_RENEW] = "DHCPV6_RENEW",
-    [DHCPV6_REBIND] = "DHCPV6_REBIND",
-    [DHCPV6_REPLY] = "DHCPV6_REPLY",
-    [DHCPV6_RELEASE] = "DHCPV6_RELEASE",
-    [DHCPV6_DECLINE] = "DHCPV6_DECLINE",
-    [DHCPV6_RECONFIGURE] = "DHCPV6_RECONFIGURE",
-    [DHCPV6_INFORMATION_REQUEST] = "DHCPV6_INFORMATION_REQUEST",
-    [DHCPV6_RELAY_FORW] = "DHCPV6_RELAY_FORW",
-    [DHCPV6_RELAY_REPL] = "DHCPV6_RELAY_REPL",
-    [DHCPV6_LEASEQUERY] = "DHCPV6_LEASEQUERY",
-    [DHCPV6_LEASEQUERY_REPLY] = "DHCPV6_LEASEQUERY_REPLY"
-};
-
-static const char * const status_codes[] = {
-    [STATUS_Success] = "Success",
-    [STATUS_UnspecFail] = "UnspecFail",
-    [STATUS_NoAddrsAvail] = "NoAddrsAvail",
-    [STATUS_NoBinding] = "NoBinding",
-    [STATUS_NotOnLink] = "NotOnLink",
-    [STATUS_UseMulticast] = "UseMulticast",
-    [STATUS_NoPrefixAvail] = "NoPrefixAvail",
-    [STATUS_UnknownQueryType] = "UnknownQueryType",
-    [STATUS_MalformedQuery] = "MalformedQuery",
-    [STATUS_NotConfigured] = "NotConfigured",
-    [STATUS_NotAllowed] = "NotAllowed",
-};
-
-void
-print_dhcp_packet(int v6, const void *pkt, size_t len)
-{
-    if (v6)
-	print_dhcpv6_packet((struct dhcpv6_packet *)pkt, len);
-    else
-	print_dhcpv4_packet((struct dhcp_packet *)pkt, len);
-
-    if (dk_set(DK_PACKET)) {
-	unsigned i;
-
-	fprintf(stderr, "Raw packet contents (%zu bytes):\n", len);
-	for (i = 0; i < len; i++)
-	    fprintf(stderr, "%02x ", ((unsigned char *)pkt)[i]);
-	fputc('\n', stderr);
-    }
-}
-
-/*
- * Note: Not reentrant
- */
-static const char *
-enum_lookup(const char * const table[], size_t size, unsigned index)
-{
-    static char numbuf[10];
-
-    if (index < (size / sizeof(char *)) && table[index] != NULL)
-	return table[index];
-    else {
-	snprintf(numbuf, sizeof(numbuf), "%u", index);
-	return numbuf;
-    }
-}
-
-/*
- * Note: Not reentrant
- */
-static const char *
-optionName(int v6, unsigned optnum)
-{
-    static char numbuf[16];
-    unsigned maxOpt = ((v6 ? sizeof(option6_desc) : sizeof(option_desc)) - 1) /
-	    sizeof(struct dhcp_option_desc);
-    struct dhcp_option_desc *descTable;
-
-    if (optnum > maxOpt) {
-	snprintf(numbuf, sizeof(numbuf), "invalid (%u)", optnum);
-	return numbuf;
-    }
-    descTable = v6 ? option6_desc : option_desc;
-    if (descTable[optnum].name == NULL) {
-	snprintf(numbuf, sizeof(numbuf), "%u", optnum);
-	return numbuf;
-    }
-    else
-	return descTable[optnum].name;
-}
-
-/*
- *
- * Output variables: None
- */
-static void
-printOption(int v6, unsigned optnum, size_t len, const unsigned char *value)
-{
-    struct dhcp_option_desc *descTable = v6 ? option6_desc : option_desc;
-    char buf[ADDR_NAME_BUFSIZE];
-    unsigned i;
-    unsigned maxOpt = ((v6 ? sizeof(option6_desc) : sizeof(option_desc)) - 1) / sizeof(struct dhcp_option_desc);
-    unsigned statusCode;
-
-    fprintf(stderr, "Option %s (%d) length %zu value ", optionName(v6, optnum), optnum, len);
-
-    switch (optnum > maxOpt ? T_UNK : descTable[optnum].type) {
-    case T_STRING:
-	fprintf(stderr, "\"%.*s\"\n", (int) len, value);
-	break;
-    case T_PERIOD:
-	fprintf(stderr, "%d seconds\n", ntohl(*(int *)value));
-	break;
-    case T_MTYPE:
-	fprintf(stderr, "%s\n", enum_lookup(message_types, sizeof(message_types), *value));
-	break;
-    case T_IPADDR:
-	for (i = 0; len - i >= 4; i += 4)
-	    fprintf(stderr, "%s%s", addrtoa(AF_INET, (struct in_addr *)(value+i), buf), len - i > 4 ? ", " : "\n");
-	break;
-    case T_STATUS:
-	statusCode = ntohs(*(uint16_t *)value);
-	fprintf(stderr, "%s: %*.*s\n", 
-		enum_lookup(status_codes, sizeof(status_codes), statusCode),
-		(int)len - 2, (int)len - 2, value + 2);
-	break;
-    default:
-	for (i = 0; i < len; i++)
-	    fprintf(stderr, "%02x", value[i]);
-	fputc('\n', stderr);
-	break;
-    }
-}
-
-static void
-print_dhcpv4_packet(const struct dhcp_packet *pkt, size_t msglen)
-{
-    int i;
-    const unsigned char *p;
-    aaddr_buf buf1, buf2, buf3, buf4;
-
-    fprintf(stderr, 
-"opcode	%u\n\
-htype	%u\n\
-hlen	%u\n\
-hops	%u\n\
-xid	0x%0x\n\
-secs	%u\n\
-flags	0x%x\n\
-ciaddr	%s\n\
-yiaddr	%s\n\
-siaddr	%s\n\
-giaddr	%s\n\
-chaddr	",
-	pkt->op,
-	pkt->htype,
-	pkt->hlen,
-	pkt->hops,
-	pkt->xid,
-	pkt->secs,
-	pkt->flags,
-	addrtoa(AF_INET, &pkt->ciaddr, buf1),
-	addrtoa(AF_INET, &pkt->yiaddr, buf2),
-	addrtoa(AF_INET, &pkt->siaddr, buf3),
-	addrtoa(AF_INET, &pkt->giaddr, buf4));
-    for (i = 0; i < pkt->hlen; i++)
-	fprintf(stderr, "%02x", pkt->chaddr[i]);
-    fputc('\n', stderr);
-    fprintf(stderr, "magic	0x%x\n", *(unsigned int *)&pkt->options);
-    p = &pkt->options[4];
-    while ((unsigned) (p - (unsigned char *)pkt) < msglen && *p != DHO_END) {
-	if (*p == DHO_PAD) {
-	    fprintf(stderr, "Option PAD\n");
-	    p++;
-	}
-	else {
-	    unsigned optnum = *p++;
-	    size_t len = *p++;
-
-	    printOption(0, optnum, len, p);
-	    p += len;
-	}
-    }
-}
-
-static void
-print_dhcpv6_packet(const struct dhcpv6_packet *pkt, size_t msglen)
-{
-    int i;
-    const unsigned char *p;
-    struct v6_option *opt;
-
-    fprintf(stderr, "msgtype\t%s\ntid\t", enum_lookup(message6_types, sizeof(message6_types), pkt->msg_type));
-    for (i = 0; i <= 2; i++)
-	fprintf(stderr, "%02x", pkt->transaction_id[i]);
-    fputc('\n', stderr);
-
-    p = pkt->options;
-    opt = (struct v6_option *)p;
-    while ((unsigned) (p - (unsigned char *)pkt) < msglen && opt->code != 0) {
-	unsigned optlen = ntohs(opt->len);
-	printOption(1, ntohs(opt->code), optlen, &opt->value);
-	p += 4 + optlen;
-	opt = (struct v6_option *)p;
-    }
-}

+ 0 - 697
tests/tools/perfdhcp/perfdhcp.cc

@@ -1,697 +0,0 @@
-/*
- * Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <net/if_arp.h>
-#include <ifaddrs.h>
-#include <strings.h>
-#include <string.h>
-#include <stdarg.h>
-#include <netdb.h>
-#include <errno.h>
-#include <time.h>
-#include "perfdhcp.h"
-#include "cloptions.h"
-#include "dkdebug.h"
-
-struct duid {
-    uint16_t duid_type;
-    uint16_t htype;
-    unsigned char hwaddr[6];
-};
-
-struct addrinfo* getaddr(int addr_fam, const char* hostname, const char* port);
-char* addrName(const struct sockaddr_storage* addr, char* buf, size_t bufsize);
-void add_option(int v6, unsigned optnum, unsigned count,
-                size_t size, int direct, unsigned char options[], size_t* buffer_used,
-                ...);
-int get_linklocal_addr(const char if_name[], struct sockaddr_storage* addr);
-const char* optionName(int v6, unsigned optnum);
-const unsigned char* find_option(const struct dhcp_packet* pkt, int search_opt);
-int socket_setup(int addr_fam, const char* localAddr, const char* port,
-                 const char* type, struct sockaddr_storage* l_addr);
-void gen_discover(struct dhcp_packet* discover_pkt, const struct in_addr* giaddr);
-void gen_request(struct dhcp_packet* dhcp_pkt, const struct in_addr* giaddr,
-                 const struct in_addr* yiaddr, const unsigned char* server_id);
-void dhcp_recv(int v6, void* msg, int recv_fd, const struct sockaddr_storage* recv_laddr);
-void dora(const char* server, const char* localAddr);
-void sarr(const char* server, const char* if_name);
-void print_addrinfo(FILE* f, const struct addrinfo* addr);
-void print_sa6_info(FILE* f, const struct sockaddr_in6* sa);
-void gen_solicit(struct dhcpv6_packet* dhcp_pkt, const struct duid* client_id);
-void dhcp_send(int v6, const unsigned char* msg, int send_fd, const struct
-               sockaddr* r_addr, const struct sockaddr_storage* send_laddr);
-
-static const struct dkdesc diagLetters[] = {
-    { 's', DK_SOCK },
-    { 'm', DK_MSG },
-    { 'p', DK_PACKET },
-    { 'a', DK_ALL },
-    { '\0', 0 }
-};
-
-int
-main(int argc, const char* argv[]) {
-    int ret;
-    int v6;
-    // int initialOnly;
-    const char* localName = NULL;
-    // unsigned rate;
-    // unsigned numRequest;
-    const char* server;
-    const char* diagSelector = "";
-    confdata_t confdata;
-
-    if ((ret = procArgs(argc, argv, &confdata, &server)) != 1) {
-        exit(ret);
-    }
-
-    v6 = confdata.map['6']->num > 0;
-    if (confdata.map['l']->num > 0) {
-        localName = confdata.map['l']->values[0]->value.string;
-    }
-    if (confdata.map['x']->num > 0) {
-        diagSelector = confdata.map['x']->values[0]->value.string;
-    }
-
-    srand(time(NULL));
-    if (v6) {
-        sarr(server, localName);
-    } else {
-        dora(server, localName);
-    }
-    dk_setup(diagSelector, diagLetters);
-
-    exit(0);
-}
-
-/*
- * Create a socket for communication with dhcp server:
- * - Create socket
- * - Bind it to given local address and port, UDP.
- *
- * Input variables:
- * addr_fam is the address family to use, e.g. AF_INET
- * localAddr is the local address to bind to.
- * port is the port to bind to.
- * type is a string giving the purpose of the socket, for verbose output.
- * If localAddr is null, the local address etc. is taken from l_addr.
- *
- * Output variables:
- * Socket details are stored in l_addr.
- *
- * Return value: The network fd.
- */
-int
-socket_setup(int addr_fam, const char* localAddr, const char* port,
-             const char* type, struct sockaddr_storage* l_addr) {
-    char addrbuf[ADDR_NAME_BUFSIZE];
-    int net_fd;
-    struct addrinfo* addrs;
-
-    if ((addrs = getaddr(addr_fam, localAddr, port)) == NULL) {
-        fprintf(stderr, "No addresses for %s\n", localAddr);
-        exit(1);
-    }
-    if (localAddr == NULL) {
-        if (dk_set(DK_SOCK)) {
-            fprintf(stderr, "local address:\n");
-            print_sa6_info(stderr, (struct sockaddr_in6*)l_addr);
-        }
-        memcpy(&((struct sockaddr_in6*)addrs->ai_addr)->sin6_addr,
-               &((struct sockaddr_in6*)l_addr)->sin6_addr,
-               sizeof(struct in6_addr));
-        ((struct sockaddr_in6*)addrs->ai_addr)->sin6_flowinfo =
-            ((struct sockaddr_in6*)l_addr)->sin6_flowinfo;
-        ((struct sockaddr_in6*)addrs->ai_addr)->sin6_scope_id =
-            ((struct sockaddr_in6*)l_addr)->sin6_scope_id;
-    }
-    if (dk_set(DK_SOCK)) {
-        print_addrinfo(stderr, addrs);
-        fprintf(stderr, "Creating socket from addrinfo:\n");
-        print_addrinfo(stderr, addrs);
-    }
-    net_fd = socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
-    if (net_fd < 0) {
-        perror("socket");
-        exit(1);
-    }
-    if (bind(net_fd, addrs->ai_addr, addrs->ai_addrlen) == -1) {
-        int s_errno = errno;
-        fprintf(stderr, "Could not bind to %s: %s\n",
-                addrName((struct sockaddr_storage*)addrs->ai_addr, addrbuf,
-                         sizeof(addrbuf)), strerror(s_errno));
-        exit(1);
-    }
-    dkprintf(DK_SOCK, "%s fd %d bound to %s\n", type, net_fd, addrName((struct sockaddr_storage*)addrs->ai_addr, addrbuf, sizeof(addrbuf)));
-    memcpy(l_addr, addrs->ai_addr, sizeof(struct sockaddr_storage));
-    freeaddrinfo(addrs);
-    return net_fd;
-}
-
-/*
- * gen_discover: Generate a DHCP discover packet.
- *
- * Input variables:
- * giaddr is the address to be copied into the giaddr (gateway addr) element.
- *
- * Output variables:
- * discover_packet is a pointer to storage for the packet to be generated.
- */
-void
-gen_discover(struct dhcp_packet* discover_pkt, const struct in_addr* giaddr) {
-    size_t options_len;
-
-    bzero((char*) discover_pkt, sizeof(struct dhcp_packet));
-    discover_pkt->op = BOOTREQUEST;
-    discover_pkt->htype = HTYPE_ETHER;
-    discover_pkt->hlen = 6;
-    discover_pkt->hops = 1;
-    discover_pkt->xid = 0x12345678; /* transaction id - fix */
-    discover_pkt->secs = 0;
-    discover_pkt->flags = 0;
-    memcpy(&discover_pkt->giaddr, giaddr, sizeof((*discover_pkt).giaddr));
-    strncpy((char*)discover_pkt->chaddr, "\x12\x34\x56\x78\x9a\xbc", 6);    /* client hardware addr - fix */
-    memset(discover_pkt->options, DHO_PAD, DHCP_MAX_OPTION_LEN);
-    strncpy((char*)discover_pkt->options, "\x63\x82\x53\x63", 4);       /* magic cookie */
-    options_len = 4;
-    add_option(0, DHO_DHCP_MESSAGE_TYPE, 1, 1, 1, discover_pkt->options, &options_len,
-               DHCPDISCOVER);
-    add_option(0, DHO_DHCP_PARAMETER_REQUEST_LIST, 4, 1, 1, discover_pkt->options,
-               &options_len, DHO_SUBNET_MASK, DHO_ROUTERS, DHO_DOMAIN_NAME,
-               DHO_DOMAIN_NAME_SERVERS);
-    add_option(0, DHO_DHCP_LEASE_TIME, 1, 4, 1, discover_pkt->options, &options_len,
-               htonl(60));
-
-    if (options_len < DHCP_MAX_OPTION_LEN) {
-        discover_pkt->options[options_len++] = DHO_END;
-    }
-}
-
-/*
- * gen_request(): Generate a DHCPv4 request packet.
- *
- * Input variables
- * giaddr is the address to copy into the giaddr element.
- * yiaddr is the address to store in the DHO_DHCP_REQUESTED_ADDRESS option.
- * server_id is the ID to store in the DHO_DHCP_SERVER_IDENTIFIER option.
- *
- * Output variables:
- * dhcp_pkt points to storage for the packet to be generated.
- */
-void
-gen_request(struct dhcp_packet* dhcp_pkt, const struct in_addr* giaddr,
-            const struct in_addr* yiaddr, const unsigned char* server_id) {
-    size_t options_len;
-
-    bzero((char*) dhcp_pkt, sizeof(struct dhcp_packet));
-    dhcp_pkt->op = BOOTREQUEST;
-    dhcp_pkt->htype = HTYPE_ETHER;
-    dhcp_pkt->hlen = 6;
-    dhcp_pkt->hops = 1;
-    dhcp_pkt->xid = 0x12345678; /* transaction id - fix */
-    dhcp_pkt->secs = 0;
-    dhcp_pkt->flags = 0;
-    memcpy(&dhcp_pkt->giaddr, giaddr, sizeof((*dhcp_pkt).giaddr));
-    /*memcpy(&dhcp_pkt->yiaddr, yiaddr, sizeof((*dhcp_pkt).yiaddr));*/
-    strncpy((char*)dhcp_pkt->chaddr, "\x12\x34\x56\x78\x9a\xbc", 6);    /* client hardware addr - fix */
-    memset(dhcp_pkt->options, DHO_PAD, DHCP_MAX_OPTION_LEN);
-    strncpy((char*)dhcp_pkt->options, "\x63\x82\x53\x63", 4);       /* magic cookie */
-    options_len = 4;
-    add_option(0, DHO_DHCP_MESSAGE_TYPE, 1, 1, 1, dhcp_pkt->options, &options_len,
-               DHCPREQUEST);
-    add_option(0, DHO_DHCP_SERVER_IDENTIFIER, 1, 4, 0, dhcp_pkt->options,
-               &options_len, server_id);
-    add_option(0, DHO_DHCP_REQUESTED_ADDRESS, 1, 4, 1, dhcp_pkt->options,
-               &options_len, *yiaddr);
-    add_option(0, DHO_DHCP_LEASE_TIME, 1, 4, 1, dhcp_pkt->options, &options_len,
-               htonl(60));
-
-    if (options_len < DHCP_MAX_OPTION_LEN) {
-        dhcp_pkt->options[options_len++] = DHO_END;
-    }
-}
-
-/*
- * dhcp_send: Send a DHCP packet.
- * If the send fails, the program exits with an error message.
- *
- * Input variables:
- * dhcp_packet: DHCP message to send.
- * send_fd: Socket to send message on.
- * r_addr: Remote address to send message to.
- * send_laddr: Local address of socket, for informational messages only.
- */
-void
-dhcp_send(int v6, const unsigned char* msg, int send_fd, const struct sockaddr* r_addr,
-          const struct sockaddr_storage* send_laddr) {
-
-    size_t num_octets;
-    ssize_t num_written;
-    char addrbuf[ADDR_NAME_BUFSIZE];
-    char addrbuf2[ADDR_NAME_BUFSIZE];
-
-    num_octets = v6 ? sizeof(struct dhcpv6_packet) : sizeof(struct dhcp_packet);
-    if (dk_set(DK_MSG)) {
-        fprintf(stderr, "Sending %zu octets to socket fd %u, local %s remote %s",
-                num_octets, send_fd,
-                addrName((struct sockaddr_storage*)send_laddr, addrbuf, sizeof(addrbuf)),
-                addrName((struct sockaddr_storage*)r_addr, addrbuf2, sizeof(addrbuf2)));
-        fprintf(stderr, "Packet contents:\n");
-        print_dhcp_packet(v6, msg, num_octets);
-    }
-    num_written = sendto(send_fd, msg, num_octets, 0,
-                         r_addr, sizeof(struct sockaddr_storage));
-    if (num_written < 0) {
-        int s_errno = errno;
-        fprintf(stderr, "Send failed: %s\n", strerror(s_errno));
-        exit(1);
-    }
-    if ((size_t) num_written != num_octets) {
-        fprintf(stderr, "Only %d of %u octets written\n", (int) num_written, (unsigned) num_octets);
-    }
-}
-
-/*
- * dhcp_recv: Receive a DHCP packet.
- *
- * Input variables:
- * recv_fd is the socket to receive on.
- * recv_laddr is the socket's address, solely for informational messages.
- *
- * Output variables:
- * msg points to storage for the received message.
- */
-void
-dhcp_recv(int v6, void* msg, int recv_fd,
-          const struct sockaddr_storage* recv_laddr) {
-
-    ssize_t num_octets;
-    struct sockaddr_storage sourceAddr;
-    socklen_t addrSize;
-    char addrbuf[ADDR_NAME_BUFSIZE];
-
-    dkprintf(DK_SOCK, "Waiting for response on socket fd %u, %s",
-             recv_fd,
-             addrName(recv_laddr, addrbuf, sizeof(addrbuf)));
-    addrSize = sizeof(sourceAddr);
-    num_octets = recvfrom(recv_fd, msg, v6 ? sizeof(struct dhcpv6_packet) : sizeof(struct dhcp_packet), 0, (struct sockaddr*)&sourceAddr, &addrSize);
-    /* TODO: check for recvfrom failure status here */
-    if (dk_set(DK_MSG)) {
-        fprintf(stderr, "Got %zd octets from fd %u, %s", num_octets, recv_fd,
-                addrName(&sourceAddr, addrbuf, sizeof(addrbuf)));
-        fprintf(stderr, "Received packet contents:\n");
-        print_dhcp_packet(v6, msg, num_octets);
-    }
-}
-
-void
-dora(const char* server, const char* localAddr) {
-    struct sockaddr_storage send_laddr, recv_laddr;
-    struct dhcp_packet discover_pkt, offer_pkt, request_pkt, ack_pkt;
-    int send_fd, recv_fd;
-    const unsigned char* type, *server_id;
-    aaddr_buf a_yiaddr;
-    struct addrinfo* remote;
-    struct in_addr* local_address;
-
-    send_fd = socket_setup(AF_INET, localAddr, "bootpc", "Send", &send_laddr);
-    recv_fd = socket_setup(AF_INET, localAddr, "bootps", "Recv", &recv_laddr);
-
-    if ((remote = getaddr(AF_INET, server, "bootps")) == NULL) {
-        fprintf(stderr, "No addresses for %s\n", server);
-        exit(1);
-    }
-
-    local_address = &((struct sockaddr_in*)&send_laddr)->sin_addr;
-    gen_discover(&discover_pkt, local_address);
-
-    dhcp_send(0, (unsigned char*)&discover_pkt, send_fd, remote->ai_addr, &send_laddr);
-    dhcp_recv(0, &offer_pkt, recv_fd, &recv_laddr);
-    type = find_option(&offer_pkt, DHO_DHCP_MESSAGE_TYPE);
-    if (type == NULL) {
-        fprintf(stderr, "DHCP reponse did not include message type option\n");
-        exit(1);
-    }
-    if (type[2] != DHCPOFFER) {
-        fprintf(stderr, "DHCP reponse had message type %d; expecting DHCPOFFER\n", type[2]);
-        exit(1);
-    }
-    server_id = find_option(&offer_pkt, DHO_DHCP_SERVER_IDENTIFIER);
-    if (type == NULL) {
-        fprintf(stderr, "DHCP reponse did not include server identifier option\n");
-        exit(1);
-    }
-    server_id += 2;
-    printf("Server identifier: %08x\n", ntohl(*(int*)server_id));
-    printf("Offered address: %s\n", addrtoa(AF_INET, &offer_pkt.yiaddr, a_yiaddr));
-    gen_request(&request_pkt, local_address, &offer_pkt.yiaddr, server_id);
-    dhcp_send(0, (unsigned char*)&request_pkt, send_fd, remote->ai_addr, &send_laddr);
-    dhcp_recv(0, &ack_pkt, recv_fd, &recv_laddr);
-}
-
-/*
-    client 546, server 547
-    All_DHCP_Relay_Agents_and_Servers FF02::1:2
-    DHCPV6_SOLICIT
-    DHCPV6_ADVERTISE
-    DHCPV6_REQUEST
-    DHCPV6_REPLY
-
-DUID option must be present
-A client SHOULD generate a random number that cannot easily be guessed or
-predicted to use as the transaction ID for each new message it sends
-Discard ADVERTISE messages in which the Client Identifier option does not match the
-      client's DUID, or in which the transaction ID does not match the SOLICIT transaction ID.
-Discard REPLY messsages in whhich the "transaction-id" field in the message does not match the value
-      used in the original message.
-*/
-void
-sarr(const char* server, const char* if_name) {
-    struct sockaddr_storage send_laddr, recv_laddr;
-    struct dhcpv6_packet solicit_pkt, advertise_pkt;
-    int send_fd, recv_fd;
-    struct in6_addr* local_address;
-    struct addrinfo* remote;
-    struct duid client_id;
-
-    get_linklocal_addr(if_name, &send_laddr);
-    memcpy(&recv_laddr, &send_laddr, sizeof(recv_laddr));
-    send_fd = socket_setup(AF_INET6, NULL, "546", "Send", &send_laddr);
-    /*
-    recv_fd = socket_setup(AF_INET6, NULL, "547", "Recv", &recv_laddr);
-    */
-    recv_fd = send_fd;
-
-    if (server != NULL) {
-        if (strcmp(server, "all")) {
-            server = All_DHCP_Relay_Agents_and_Servers;
-        } else if (strcmp(server, "server")) {
-            server = All_DHCP_Servers;
-        }
-    }
-    if ((remote = getaddr(AF_INET6, server, "547")) == NULL) {
-        fprintf(stderr, "Conversion failed for %s\n", server);
-        exit(1);
-    }
-
-    local_address = &((struct sockaddr_in6*)&send_laddr)->sin6_addr;
-
-    client_id.duid_type = htons(DUID_LL);
-    client_id.htype = htons(HTYPE_ETHER);
-    memset(client_id.hwaddr, 0xA, 6);   /* TEMPORARY - FIX */
-
-    gen_solicit(&solicit_pkt, &client_id);
-    dhcp_send(1, (unsigned char*)&solicit_pkt, send_fd, remote->ai_addr, &send_laddr);
-    dhcp_recv(1, &advertise_pkt, recv_fd, &recv_laddr);
-    /*
-     *
-     *    type = find_option(&offer_pkt, DHO_DHCP_MESSAGE_TYPE);
-     *    if (type == NULL) {
-     *  fprintf(stderr, "DHCP reponse did not include message type option\n");
-     *  exit(1);
-     *    }
-     *    if (type[2] != DHCPOFFER) {
-     *  fprintf(stderr, "DHCP reponse had message type %d; expecting DHCPOFFER\n", type[2]);
-     *  exit(1);
-     *    }
-     *    server_id = find_option(&offer_pkt, DHO_DHCP_SERVER_IDENTIFIER);
-     *    if (type == NULL) {
-     *  fprintf(stderr, "DHCP reponse did not include server identifier option\n");
-     *  exit(1);
-     *    }
-     *    server_id += 2;
-     *    printf("Server identifier: %08x\n", ntohl(*(int *)server_id));
-     *    printf("Offered address: %s\n", addrtoa(AF_INET, &offer_pkt.yiaddr, a_yiaddr));
-     *    gen_request(&request_pkt, local_address, &offer_pkt.yiaddr, server_id);
-     *    dhcp_send(&request_pkt, send_fd, remote->ai_addr, &send_laddr);
-     *    dhcp_recv(&ack_pkt, recv_fd, &recv_laddr);
-     */
-}
-
-/*
- * Must include client identifier, server identifier, IA, DUID?
- * Solitication: Create an IA.  Assign it an IAID.  Transmit a Solicit
- * message containing an IA option describing the IA.
- * Use IA_TA to request temporary addresses
- */
-void
-gen_solicit(struct dhcpv6_packet* dhcp_pkt, const struct duid* client_id) {
-    int tid;
-    int i;
-    size_t options_len = 0;
-
-    bzero((char*) dhcp_pkt, sizeof(struct dhcpv6_packet));
-    dhcp_pkt->msg_type = DHCPV6_SOLICIT;
-    tid = rand();
-    for (i = 0; i < 2; i++) {
-        dhcp_pkt->transaction_id[i] = (unsigned char)tid;
-        tid >>= 8;
-    }
-    add_option(1, D6O_CLIENTID, 1, sizeof(struct duid), 0, dhcp_pkt->options,
-               &options_len, client_id);
-    add_option(1, D6O_IA_TA, 1, 4, 1, dhcp_pkt->options,
-               &options_len, "0xabcd");    /* Temporary - FIX */
-    /* D60_ORO: Option Request Option */
-    add_option(1, D6O_ORO, 1, 2, 1, dhcp_pkt->options,
-               &options_len, D6O_NAME_SERVERS);
-}
-
-/*
- * Add an option to a DHCP packet.
- *
- * Input variables:
- * If buffer_size is nonzero, options are added to a DHCP6 packet, and
- *     buffer_size specifies the size of the buffer.  If it is zero, options
- *     are added to a DHCP4 packet.
- * optnum is the option number.
- * count is the number of option parameters passed.
- * size is the size of each parameter, in bytes.
- * direct is true if the options are passed by value, false if they are passed
- * by address.
- *
- * Output variables:
- * options[] is the buffer in which to store the option.
- *
- * Input/output variables:
- * buffer_used is the amount of buffer space currently used.
- */
-void
-add_option(int v6, unsigned optnum, unsigned count, size_t size,
-           int direct, unsigned char options[], size_t* buffer_used, ...) {
-    va_list ap;
-    unsigned i;
-    size_t buffer_size = v6 ? sizeof(struct dhcpv6_packet) : DHCP_MAX_OPTION_LEN;
-
-    if ((*buffer_used + (v6 ? 4 : 2) + count * size) > buffer_size) {
-        fprintf(stderr, "%s: Insufficient option space\n", progName);
-        exit(1);
-    }
-    if (v6) {
-        struct v6_option* opt = (struct v6_option*)&options[(*buffer_used)];
-        opt->code = htons(optnum);
-        opt->len = htons(count * size);
-        *buffer_used += 4;
-    } else {
-        options[(*buffer_used)++] = optnum;
-        options[(*buffer_used)++] = count * size;
-    }
-    va_start(ap,buffer_used);
-    for (i = 1; i <= count; i++) {
-        if (direct) {
-            int value = va_arg(ap, int);
-            memcpy(&options[*buffer_used], (char*)&value, size);
-        } else {
-            char* p = va_arg(ap, char*);
-            memcpy(&options[*buffer_used], p, size);
-        }
-        (*buffer_used) += size;
-    }
-    /* ap */
-    va_end(ap);
-}
-
-/*
- * Return value:
- * buf is returned.
- */
-char*
-addrtoa(int addr_fam, const struct in_addr* addr, aaddr_buf buf) {
-    if (inet_ntop(addr_fam, addr, buf, ADDR_NAME_BUFSIZE) == NULL) {
-        strcpy(buf, "untranslatable");
-    }
-    return buf;
-}
-
-/*
- * getaddr: generate an addrinfo list for a given hostname and port, UDP.
- * If getaddrinfo() fails with the provided information, an error message
- * is printed and the program exits with status 2.
- *
- * Input variables:
- * hostname: The host name to look up.  This can be either a name or an IPv4
- *     dotted-quad address, or null to not fill in the address.
- * port: The port to include in addrinfo.  This can be either a service name or
- *     an ASCII decimal number, or null to not fill in the port number.
- *
- * Globals:
- * progName, for error messages.
- *
- * Return value:
- * A pointer to the addrinfo list.  This must be freed by the caller with
- * freeaddrinfo().
- */
-struct addrinfo*
-getaddr(int addr_fam, const char* hostname, const char* port) {
-    struct addrinfo* ai;
-    struct addrinfo hints;
-    int ret;
-
-    memset (&hints, '\0', sizeof(hints));
-    hints.ai_family = addr_fam;
-    hints.ai_socktype = SOCK_DGRAM;
-    hints.ai_protocol = IPPROTO_UDP;
-
-    if ((ret = getaddrinfo(hostname, port, &hints, &ai)) != 0) {
-        fprintf(stderr, "%s: %s: getaddrinfo: %s/%s\n", progName,
-                hostname == NULL ? "" : hostname, port == NULL ? "" : port, gai_strerror(ret));
-        exit(2);
-    }
-    return ai;
-}
-
-/*
- * addrName(): Convert the address and port associated with a socket into an a
- * hostname and numeric string and store them in a buffer.
- *
- * Input variables:
- * addr is the socket to operate on.
- * bufsize is the size of the buffer.
- *
- * Output variables:
- * name is the buffer to store in.
- *
- * Return value:
- * buf is returned.
- */
-char*
-addrName(const struct sockaddr_storage* addr, char* name, size_t bufsize) {
-    char* buf = name;
-    char servbuf[30];
-
-    if (getnameinfo((struct sockaddr*)addr, sizeof(struct sockaddr_storage),
-                    name, bufsize, servbuf, 30, 0) != 0) {
-        strncpy(buf, "untranslatable", bufsize-1);
-    } else {
-        size_t len = strlen(buf);
-        if (len < bufsize) {
-            snprintf(name + len, bufsize - len, " port %s", servbuf);
-        }
-    }
-    return buf;
-}
-
-/*
- *
- * Input variables:
- * if_name is the name of the interface to search for.
- *
- * Output variables:
- * The link-local address for the interface is stored in addr.
- *
- * Return value:
- * 1 on success, 0 if no link-local address is found.
- *
- * If retrieval of the interface address list fails, an error message is
- * printed and the program is exited with status 2.
- */
-int
-get_linklocal_addr(const char if_name[], struct sockaddr_storage* addr) {
-
-    struct ifaddrs* ifaddr, *ifa;
-
-    if (getifaddrs(&ifaddr) == -1) {
-        fprintf(stderr, "%s: Could not get interface addresses: %s\n",
-                progName, strerror(errno));
-        exit(2);
-    }
-
-    for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
-        if (ifa->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, if_name) == 0 &&
-                (ntohs(((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr.__in6_u.__u6_addr16[0]) & 0xffc0) == 0xfe80) {
-            break;
-        }
-    }
-    if (ifa != NULL) {
-        memcpy(addr, ifa->ifa_addr, sizeof(struct sockaddr_storage));
-    }
-    freeifaddrs(ifaddr);
-    return ifa != NULL;
-}
-
-void
-print_addrinfo(FILE* f, const struct addrinfo* addr) {
-    fprintf(f, "Addrinfo:\n");
-    fprintf(f, "flags: 0x%x;  family: %d;  socktype: %d;  proto: %d;\n",
-            addr->ai_flags, addr->ai_family, addr->ai_socktype, addr->ai_protocol);
-    fprintf(f, "addrlen: %u;  addr: %p;  canonname: %s;  next: %p\n",
-            addr->ai_addrlen, addr->ai_addr, addr->ai_canonname, addr->ai_next);
-    if (addr->ai_family == AF_INET6) {
-        print_sa6_info(f, (struct sockaddr_in6*)addr->ai_addr);
-    }
-}
-
-void
-print_sa6_info(FILE* f, const struct sockaddr_in6* sa) {
-    char addrbuf[ADDR_NAME_BUFSIZE];
-
-    fprintf(f, "IPv6 sockaddr info:\n");
-    fprintf(f, "family: %u;  flowinfo: 0x%x;  scope-id: %u  addr: %s\n",
-            sa->sin6_family, sa->sin6_flowinfo, sa->sin6_scope_id,
-            addrName((struct sockaddr_storage*)sa, addrbuf, sizeof(addrbuf)));
-}
-
-/*
- * Search for a specific option in the options stored in a DHCP packet.
- *
- * Input variables:
- * pkt is the packet to search.
- * search_opt is the option number to search for.
- *
- * Return value:
- * If the packet contains the option, a pointer to its start (the option
- * number) is returned.  If not, NULL is returned.
- */
-const unsigned char*
-find_option(const struct dhcp_packet* pkt, int search_opt) {
-    const unsigned char* p;
-
-    p = &pkt->options[4];
-    while ((p - pkt->options) < DHCP_MAX_OPTION_LEN && *p != DHO_END) {
-        if (*p == search_opt) {
-            return p;
-        } else if (*p == DHO_PAD) {
-            p++;
-        } else {
-            size_t len = p[1];
-            p += 2 + len;
-        }
-    }
-    return NULL;
-}

+ 21 - 24
tests/tools/perfdhcp/perfdhcp.h

@@ -1,33 +1,30 @@
+/*
+ * Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef PERFDHCP_H
+#define PERFDHCP_H
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define FLEXIBLE_ARRAY_MEMBER 500
-#define ADDR_NAME_BUFSIZE (NI_MAXHOST + 30)
-
-#define DK_SOCK 1
-#define DK_MSG 2
-#define DK_PACKET 4
-
-#include <stdlib.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include "dhcp.h"
-#include "dhcp6.h"
-
-struct v6_option {
-    uint16_t code;
-    uint16_t len;
-    unsigned char value;
-};
-
-typedef char aaddr_buf[ADDR_NAME_BUFSIZE];
-
-char* addrtoa(int addr_fam, const struct in_addr* addr, aaddr_buf buf);
-void print_dhcp_packet(int v6, const void* pkt, size_t len);
-
 const char progName[] = "dhcpperf";
 
 #ifdef __cplusplus
 }
 #endif
+
+#endif

+ 89 - 218
tests/tools/perfdhcp/procconf.cc

@@ -1,9 +1,17 @@
 /*
- * procopts: process command line options and config file variables.
- * This is still more or less a first cut (despite the rewrite!)
- * 2000-07-22 John H. DuBois III (john@armory.com)
- * 2007-04-28 2.0 Added command line processing.  Largely rewritten.
- * 2011-10-30 Cleaned up.  Added double types and out-of-range checking.
+ * Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 #include <string.h>
@@ -20,16 +28,20 @@
 static char errmsg[256];    /* for returning error descriptions */
 static const char* pc_name;
 static const char* pc_usage;
-static unsigned debugLevel = 0;     /* set by debug option */
-static int readConf = 1;        /* should config file be read? */
-#define VERBOSE_DEBUG 7
 
 #define INTERNAL_ERROR -1
 #define USAGE_ERROR -2
 
 /*
  * error: printf-style interface to print an error message or write it into
- * global errmsg.
+ * global errmsg.  If a usage message has been given (the indicator that errors
+ * should be handled internally), the message is printed to stderr and the
+ * program is exited.  If not, it is written into errmsg.
+ * Input variables:
+ * errtype is the error type.  If USAGE_ERROR, the program's usage is included
+ *     in error messages, and the exit status is 2; otherwise the exit status
+ *     is 1.
+ * format and the remaining arguments are as for printf().
  */
 static void
 error(const int errtype, const char* format, ...) {
@@ -50,29 +62,37 @@ error(const int errtype, const char* format, ...) {
     va_end(ap);
 }
 
+/*
+ * Allocate memory, with error checking.
+ * On allocation failure, error() is called; see its description.
+ */
 static void*
 pc_malloc(size_t size) {
     void* ret = malloc(size);
     if (ret == NULL) {
         error(INTERNAL_ERROR, "Out of memory");
     }
-    return ret;
+    return(ret);
 }
 
+/*
+ * Generate an error message describing an error in the value passed with an
+ * option.  This is a front end for error(); see its usage for details.
+ * Input variables:
+ * expected: A description of what was expected for the value.
+ * varDesc: The descriptor for the option.
+ * value: The value that was given with the option.
+ * detail: If non-null, additional detail to append regardign the problem.
+ */
 static void
 opterror(const char* expected, const char* value, const confvar_t* varDesc,
-         const char filename[], const char* detail) {
+         const char* detail) {
     if (detail == NULL) {
         detail = "";
     }
-    if (filename == NULL)
-        error(USAGE_ERROR,
-              "Invalid value given for option -%c: expected %s, got: %s%s",
-              varDesc->outind, expected, value, detail);
-    else
-        error(USAGE_ERROR, "Invalid value given in configuration file \"%s\""
-              " for option %s: expected %s, got: %s%s",
-              filename, varDesc->varname, expected, value, detail);
+    error(USAGE_ERROR,
+          "Invalid value given for option -%c: expected %s, got: %s%s",
+          varDesc->outind, expected, value, detail);
 }
 
 /*
@@ -81,12 +101,9 @@ opterror(const char* expected, const char* value, const confvar_t* varDesc,
  * of option structures.
  *
  * Input variables:
- * source is the source the option came from (command line, config file, etc.)
  * value is the string value assigned to the option, for options that take
  *     values.
  * varDesc is the description structure for this option.
- * filename is the configuration file name, if this option came from a config
- *     file, else null.
  *
  * Output variables:
  * The option value is stored in the option list pointed to by first.
@@ -100,21 +117,22 @@ opterror(const char* expected, const char* value, const confvar_t* varDesc,
  * -1 is returned.
  */
 static int
-addOptVal(const cf_source source, const char* value, const confvar_t* varDesc,
-          confval** first, confval** last, const char filename[]) {
-    const void* addr;
-    confval data, *ret_data;
-    int seen = *first != NULL;
-    char* ptr;
-    int err;
+addOptVal(const char* value, const confvar_t* varDesc,
+          confval** first, confval** last) {
+    const void* addr;           /* address, if any at which to store value */
+    confval data;               /* data for this option/value */
+    confval *ret_data;          /* allocated structure to add to list */
+    int seen = *first != NULL;  /* has this option been seen before? */
+    char* ptr;        /* character that terminated processing in strtox() */
+    int err;                    /* bad numeric value found? */
 
     /* if first instance of this option, store result to given addr */
     addr = seen ? NULL : varDesc->addr;
     switch (varDesc->type) {
     case CF_CHAR:
         if (strlen(value) > 1) {    /* length 0 is OK; gives null char */
-            opterror("a single character", value, varDesc, filename, NULL);
-            return -1;
+            opterror("a single character", value, varDesc, NULL);
+            return(-1);
         }
         data.value.charval = *value;
         if (addr != NULL) {
@@ -124,8 +142,8 @@ addOptVal(const cf_source source, const char* value, const confvar_t* varDesc,
     case CF_STRING:
     case CF_NE_STRING:
         if (varDesc->type == CF_NE_STRING && *value == '\0') {
-            opterror("a non-empty string", value, varDesc, filename, NULL);
-            return -1;
+            opterror("a non-empty string", value, varDesc, NULL);
+            return(-1);
         }
         data.value.string = value;
         if (addr != NULL) {
@@ -135,36 +153,34 @@ addOptVal(const cf_source source, const char* value, const confvar_t* varDesc,
     case CF_INT:
     case CF_NON_NEG_INT:
     case CF_POS_INT:
-    case CF_PDEBUG:
         /* todo: check for out-of-range result */
         errno = 0;
         data.value.intval = strtol(value, &ptr, 0);
         if (errno == ERANGE) {
-            opterror("an integer", value, varDesc, filename,
+            opterror("an integer", value, varDesc,
                      " (out of range)");
-            return -1;
+            return(-1);
         }
         err = *value == '\0' || *ptr != '\0';
         switch (varDesc->type) {
         case CF_INT:
             if (err) {
-                opterror("an integer", value, varDesc, filename, NULL);
-                return -1;
+                opterror("an integer", value, varDesc, NULL);
+                return(-1);
             }
             break;
         case CF_NON_NEG_INT:
             if (err || data.value.intval < 0) {
-                opterror("a non-negative integer", value, varDesc, filename,
+                opterror("a non-negative integer", value, varDesc,
                          NULL);
-                return -1;
+                return(-1);
             }
             data.value.nnint = data.value.intval;
             break;
         case CF_POS_INT:
-        case CF_PDEBUG:
             if (err || data.value.intval <= 0) {
-                opterror("a positive integer", value, varDesc, filename, NULL);
-                return -1;
+                opterror("a positive integer", value, varDesc, NULL);
+                return(-1);
             }
             data.value.nnint = data.value.intval;
             break;
@@ -175,9 +191,6 @@ addOptVal(const cf_source source, const char* value, const confvar_t* varDesc,
         if (addr != NULL) {
             *(int*) addr = data.value.intval;
         }
-        if (!seen && varDesc->type == CF_PDEBUG) {
-            debugLevel = data.value.intval;
-        }
         break;
     case CF_FLOAT:
     case CF_NON_NEG_FLOAT:
@@ -186,28 +199,28 @@ addOptVal(const cf_source source, const char* value, const confvar_t* varDesc,
         errno = 0;
         data.value.floatval = strtod(value, &ptr);
         if (errno == ERANGE) {
-            opterror("a number", value, varDesc, filename, " (out of range)");
-            return -1;
+            opterror("a number", value, varDesc, " (out of range)");
+            return(-1);
         }
         err = *value == '\0' || *ptr != '\0';
         switch (varDesc->type) {
         case CF_FLOAT:
             if (err) {
-                opterror("a number", value, varDesc, filename, NULL);
-                return -1;
+                opterror("a number", value, varDesc, NULL);
+                return(-1);
             }
             break;
         case CF_NON_NEG_FLOAT:
             if (err || data.value.floatval < 0) {
-                opterror("a non-negative number", value, varDesc, filename,
+                opterror("a non-negative number", value, varDesc,
                          NULL);
-                return -1;
+                return(-1);
             }
             break;
         case CF_POS_FLOAT:
             if (err || data.value.floatval <= 0) {
-                opterror("a positive number", value, varDesc, filename, NULL);
-                return -1;
+                opterror("a positive number", value, varDesc, NULL);
+                return(-1);
             }
             break;
         default:
@@ -219,39 +232,20 @@ addOptVal(const cf_source source, const char* value, const confvar_t* varDesc,
         }
         break;
     case CF_SWITCH:
-    case CF_NOCONF:
-    case CF_SDEBUG:
-        /* If option not turned on, ignore */
-        if (source == CF_FILE && *value != '1') {
-            return 0;
-        }
         data.value.switchval = varDesc->value;
         value = "1";    /* for debugging */
         if (addr != NULL) {
             *(int*) addr = varDesc->value;
         }
-        if (!seen)
-            switch (varDesc->type) {
-            case CF_NOCONF:
-                readConf = 0;
-                break;
-            case CF_SDEBUG:
-                debugLevel = 9;
-                break;
-            default:
-                /* To avoid complaints from -Wall */
-                ;
-            }
         break;
     case CF_ENDLIST:
         /* To avoid complaints from -Wall */
         ;
     }
     data.strval = value;
-    data.source = source;
     data.next = NULL;
     if ((ret_data = (confval*)pc_malloc(sizeof(confval))) == NULL) {
-        return -1;
+        return(-1);
     }
     *ret_data = data;
     if (seen) {
@@ -260,105 +254,10 @@ addOptVal(const cf_source source, const char* value, const confvar_t* varDesc,
         *first = ret_data;
     }
     *last = ret_data;
-    if (debugLevel >= VERBOSE_DEBUG)
-        fprintf(stderr, "Option %c (%s) gets value \"%s\" from %s%s\n",
-                0 < varDesc->outind && varDesc->outind < 256 ?
-                varDesc->outind : '-',
-                varDesc->varname == NULL ? "-" : varDesc->varname, value,
-                source == CF_ARGS ? "command line" : "config file", seen ?
-                " (already seen)" : "");
-    return 1;
+    return(1);
 }
 
 /*
- * This currently depends on defread().
- * A CDDL version of the def* library exists:
- *http://www.opensource.apple.com/source/autofs/autofs-207/automountlib/deflt.c
- * But, this should really be rewritten to not use defread().
- */
-#ifdef DEFREAD
-/*
- * Input variables:
- * filename: Name of configuration file.  If it begins with ~/, the ~ is
- *     replaced with the invoking user's home directory.
- * optConf[]: Option description structures.
- *
- * Output variables:
- * See addOptVal().
- *
- * Return value:
- * If the config file does not exist, 0.
- * Otherwise, the number of variable assignments read is returned (which may
- * also result in a 0 return value).
- * On error, a string describing the error is stored in the global errmsg and
- * -1 is returned.
- */
-static int
-procConfFile(const char filename[], const confvar_t optConf[],
-             confval* first[], confval* last[]) {
-    int count;
-    char* home;
-    int ind;
-
-    if (!strncmp(filename, "~/", 2)) {
-        char* path;
-
-        if (!(home = getenv("HOME"))) {
-            if (debugLevel > 2) {
-                fprintf(stderr, "HOME environment variable not set.\n");
-            }
-            return 0;
-        }
-        if ((path = pc_malloc(strlen(home) + strlen(filename))) == NULL) {
-            return -1;
-        }
-        strcpy(path, home);
-        strcat(path, filename+1);
-        if (defopen(path)) {
-            free(path);
-            return 0;
-        }
-        free(path);
-    } else if (defopen((char*)filename)) {
-        if (debugLevel > 2) {
-            fprintf(stderr, "Config file '%s' not found.\n", filename);
-        }
-        return 0;
-    }
-    count = 0;
-    for (ind = 0; optConf[ind].type != CF_ENDLIST; ind++) {
-        char buf[128];
-        char* s;
-
-        if (optConf[ind].varname == NULL) {
-            continue;
-        }
-        strncpy(buf, optConf[ind].varname, 126);
-        strcat(buf, "=");
-        if ((s = defread(buf)) != NULL) {
-            int ret;
-
-            if ((s = strdup(s)) == NULL) {
-                error(INTERNAL_ERROR, "Out of memory");
-                return -1;
-            }
-            switch ((ret = addOptVal(CF_FILE, s, &optConf[ind], &first[ind],
-                                     &last[ind], filename))) {
-            case 1:
-                count++;
-                break;
-            case 0:
-                break;
-            default:
-                return ret;
-            }
-        }
-    }
-    return count;
-}
-#endif
-
-/*
  * Input variables:
  * argc, argv: Command line data.
  * optConf[]: Option description structures.
@@ -380,11 +279,11 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
     extern char* optarg;    /* For getopt */
     extern int optind;      /* For getopt */
     extern int optopt;      /* For getopt */
-    char optstr[514];
-    unsigned optCharToConf[256];
-    int optchar;
-    unsigned confNum;
-    int count = 0;
+    char optstr[514];       /* List of option chars, for getopt */
+    unsigned optCharToConf[256];        /* Map option char/num to confvar */
+    int optchar;            /* value returned by getopt() */
+    unsigned confNum;       /* to iterate over confvars */
+    int count = 0;          /* number of options processed */
 
     p = optstr;
     *(p++) = ':';
@@ -394,8 +293,6 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
             *(p++) = (char) outind;
             switch (optConf[confNum].type) {
             case CF_SWITCH:
-            case CF_NOCONF:
-            case CF_SDEBUG:
                 break;
             default:
                 *(p++) = ':';
@@ -404,10 +301,6 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
             optCharToConf[outind] = confNum;
         }
     }
-    int x;
-    for (x = 0; x < *argc; x++) {
-        printf("%d:%s\n", x, (*argv)[x]);
-    }
 
     *p = '\0';
     optind = 1;
@@ -415,36 +308,34 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
         int ind;
         int ret;
 
-        printf("## %c\n", optchar);
         if (optchar == '?') {
             error(USAGE_ERROR, "Unknown option character '%c'", optopt);
-            return -1;
+            return(-1);
         } else if (optchar == ':') {
             error(USAGE_ERROR, "No value given for option -%c", optopt);
-            return -1;
+            return(-1);
         }
         ind = optCharToConf[optchar];
-        switch (ret = addOptVal(CF_ARGS, optarg, &optConf[ind], &first[ind],
-                                &last[ind], NULL)) {
+        switch (ret = addOptVal(optarg, &optConf[ind], &first[ind],
+                                &last[ind])) {
         case 1:
             count++;
             break;
         case 0:
             break;
         default:
-            return ret;
+            return(ret);
         }
     }
     *argc -= optind;
     *argv += optind;
-    return count;
+    return(count);
 }
 
 /*
  * Input variables:
  * argc, argv: Command line data.
  * optConf[]: Option description structures.
- * confFile[]: Configuration file, or NULL if none provided.
  * name: Name of program, for messages.
  * usage: Usage message.  If non-null, on error a message is printed to stderr
  *    and the program exits.
@@ -466,7 +357,7 @@ procCmdLineArgs(int* argc, const char** argv[], const confvar_t optConf[],
  */
 const char*
 procOpts(int* argc, const char** argv[], const confvar_t optConf[],
-         confdata_t* confdata, const char confFile[], const char name[],
+         confdata_t* confdata, const char name[],
          const char usage[]) {
     /* Number of configuration options given in optConf */
     unsigned numConf;
@@ -475,9 +366,9 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
     unsigned maxOptIndex = 0;   /* The highest option index number seen */
     /* number of option instances + assignments given */
     int numOptsFound;
-    unsigned optNum;
-    unsigned i;
-    confval** valuePointers;
+    unsigned optNum;    /* to iterate through the possible options */
+    unsigned i; /* index into the global list of option value structures */
+    confval** valuePointers;    /* global list of value structures */
 
     pc_name = name;
     pc_usage = usage;
@@ -491,28 +382,14 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
     if ((first = (confval**)pc_malloc(sizeof(confval*) * numConf)) == NULL ||
             (last =
                  (confval**)pc_malloc(sizeof(confval*) * numConf)) == NULL) {
-        return errmsg;
+        return(errmsg);
     }
     memset(first, '\0', sizeof(confval*) * numConf);
     memset(last, '\0', sizeof(confval*) * numConf);
 
     if ((numOptsFound =
                 procCmdLineArgs(argc, argv, optConf, first, last)) < 0) {
-        return errmsg;
-    }
-    if (readConf && confFile != NULL) {
-#ifdef DEFREAD
-        int ret;
-
-        if ((ret = procConfFile(confFile, optConf, first, last)) < 0) {
-            return errmsg;
-        } else {
-            nummOptsFound += ret;
-        }
-#else
-        error(INTERNAL_ERROR, "Built without defread!");
-        return errmsg;
-#endif
+        return(errmsg);
     }
 
     free(last);
@@ -525,14 +402,14 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
                 (confval**)pc_malloc(sizeof(confval*) * numOptsFound)) == NULL ||
             (confdata->optVals =
                  (cf_option*)pc_malloc(sizeof(cf_option) * numConf)) == NULL) {
-        return errmsg;
+        return(errmsg);
     }
     /* If option index numbers are used, allocate a map for them */
     if (maxOptIndex != 0) {
         if ((confdata->map =
                     (cf_option**)pc_malloc(sizeof(cf_option) * (maxOptIndex+1)))
                 == NULL) {
-            return errmsg;
+            return(errmsg);
         }
         memset(confdata->map, '\0', sizeof(confval*) * (maxOptIndex+1));
     }
@@ -556,13 +433,7 @@ procOpts(int* argc, const char** argv[], const confvar_t optConf[],
             confdata->optVals[optNum].num++;
             valuePointers[i++] = optval;
         }
-        if (debugLevel > 5)
-            fprintf(stderr, "Option %c (%s) got %d values\n",
-                    outind == 0 ? '-' : outind,
-                    optConf[optNum].varname == NULL ? "-" :
-                    optConf[optNum].varname,
-                    confdata->optVals[optNum].num);
     }
     free(first);
-    return NULL;
+    return(NULL);
 }

+ 60 - 22
tests/tools/perfdhcp/procconf.h

@@ -1,31 +1,46 @@
+/*
+ * Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This header gives the interface types and prototypes for the procconf
+ * module, which processes command line options.
+ */
+
 #ifndef PROCCONF_H
 #define PROCCONF_H
 
 #include <limits.h> /* for UINT_MAX */
 
+/*
+ * These are used to specify the option type expected
+ */
 typedef enum {
-    CF_CHAR,
-    CF_STRING,
-    CF_NE_STRING,
-    CF_INT,
-    CF_NON_NEG_INT,
-    CF_POS_INT,
-    CF_FLOAT,
-    CF_NON_NEG_FLOAT,
-    CF_POS_FLOAT,
-    CF_SWITCH,
-    CF_NOCONF,  /* option to specify that config file should not be read */
-    CF_PDEBUG,  /* option to turn on debugging, with positive integer value */
-    CF_SDEBUG,  /* option to turn on debugging, without a value */
-    CF_ENDLIST  /* End of option list */
+    CF_CHAR,          /* A single character */
+    CF_STRING,        /* A string */
+    CF_NE_STRING,     /* A non-empty string */
+    CF_INT,           /* An integer */
+    CF_NON_NEG_INT,   /* A non-negative integer */
+    CF_POS_INT,       /* A positive integer */
+    CF_FLOAT,         /* A floating-point value */
+    CF_NON_NEG_FLOAT, /* A non-negative floating point value */
+    CF_POS_FLOAT,     /* A positive floating point value */
+    CF_SWITCH,        /* An option that does not take a value */
+    CF_ENDLIST        /* End of option list */
 } cf_type;
 
-typedef enum {
-    CF_NONE,
-    CF_ARGS,
-    CF_FILE
-} cf_source;
-
 /*
  * This is to be OR'd into a confvar_t outind to indicate that an index
  * number that is given is not to be interpreted as a command line option
@@ -52,7 +67,6 @@ typedef struct {
  */
 typedef struct confval_struct {
     const char* strval; /* String form of value */
-    cf_source source;   /* Where value was taken from */
     unsigned index; /* Relative position of this instance */
     union {
         int intval;
@@ -77,9 +91,33 @@ typedef struct {
     cf_option** map;    /* Option values indexed by option-char/option-index */
 } confdata_t;
 
+/*
+ * Input variables:
+ * argc, argv: Command line data.
+ * optConf[]: Option description structures.  The array should end with an
+ *    element with a type of CF_ENDLIST.
+ * name: Name of program, for messages.
+ * usage: Usage message.  If non-null, on error a message is printed to stderr
+ *    and the program exits.
+ *
+ * Output variables:
+ * The processed option values are stored in confdata.
+ * A pointer to the start of the values for each option is stored in
+ * confdata->optVals[].values at the same offset as the option appears in
+ * confdata[].
+ * For any option for option characters/indexes have been used,
+ * confdata->map[index] is set to the same data.
+ * After processing, argc will have been adjusted to be the number of
+ * non-option arguments and argv will have been adjusted to start with the
+ * first non-option argument.
+ *
+ * Return value:
+ * On success, NULL.
+ * On error, a message describing the problem.
+ */
 const char*
 procOpts(int* argc, const char** argv[], const confvar_t optConf[],
-         confdata_t* confdata, const char confFile[], const char name[],
+         confdata_t* confdata, const char name[],
          const char usage[]);
 
 #endif

+ 68 - 18
tests/tools/perfdhcp/tests/cloptions_unittest.cc

@@ -15,44 +15,53 @@
 #include <stdint.h>
 #include <gtest/gtest.h>
 #include <exceptions/exceptions.h>
+#include <stdarg.h>
 
 #include "../cloptions.h"
 
-int checkOption(const char* optflag, const char* optval,
-                confdata_t* confdata, int retExpected) {
-    const char* argv[] = { "perfdhcp", NULL, NULL, NULL };
+// Up to 4 arguments may be specified
+// The final argument must be NULL.  This is not counted in the 4 arguments.
+int checkOption(confdata_t* confdata, int retExpected, ...) {
+    const char* argv[6] = { "perfdhcp" };
     int argc = 1;
     const char* server;
     int ret;
-
-    argv[argc++] = optflag;
-    if (optval != NULL) {
-        argv[argc++] = optval;
+    const char* p;
+    va_list ap;
+
+    va_start(ap, retExpected);
+    p = va_arg(ap, const char *);
+    while (p != NULL && argc < 5) {
+        argv[argc++] = p;
+        p = va_arg(ap, const char *);
     }
+    va_end(ap);
     argv[argc++] = "foo";   /* server */
     ret = procArgs(argc, argv, confdata, &server);
     EXPECT_EQ(ret, retExpected);
-    return ret == retExpected;
+    return(ret == retExpected);
 }
 
 void checkOptionInvalid(const char* optflag, const char* optval) {
     confdata_t confdata;
 
-    checkOption(optflag, optval, &confdata, 2);
+    checkOption(&confdata, 2, optflag, optval, NULL);
 }
 
 int checkOptionValid(const char* optflag, const char* optval,
                      confdata_t* confdata) {
 
-    return checkOption(optflag, optval, confdata, 1);
+    return(checkOption(confdata, 1, optflag, optval, NULL));
 }
 
 void checkPosFloatOpt(const char* optflag) {
     confdata_t confdata;
 
-    if (checkOptionValid(optflag, "100.0", &confdata))
+    if (checkOptionValid(optflag, "100.0", &confdata)) {
         EXPECT_EQ(100.0,
-                  confdata.map[(unsigned)optflag[1]]->values[0]->value.floatval);
+                  confdata.map[(unsigned)optflag[1]]->values[0]->
+                  value.floatval);
+    }
     checkOptionInvalid(optflag, "0");
     checkOptionInvalid(optflag, "-1");
     checkOptionInvalid(optflag, "0.0");
@@ -63,9 +72,10 @@ void checkPosFloatOpt(const char* optflag) {
 void checkPosIntOpt(const char* optflag) {
     confdata_t confdata;
 
-    if (checkOptionValid(optflag, "100", &confdata))
+    if (checkOptionValid(optflag, "100", &confdata)) {
         EXPECT_EQ(100,
                   confdata.map[(unsigned)optflag[1]]->values[0]->value.nnint);
+    }
     checkOptionInvalid(optflag, "0");
     checkOptionInvalid(optflag, "-1");
     checkOptionInvalid(optflag, "1.0");
@@ -75,32 +85,36 @@ void checkPosIntOpt(const char* optflag) {
 void checkFlag(const char* optflag) {
     confdata_t confdata;
 
-    if (checkOptionValid(optflag, NULL, &confdata))
+    if (checkOptionValid(optflag, NULL, &confdata)) {
         EXPECT_EQ(1,
-                  confdata.map[(unsigned)optflag[1]]->values[0]->value.switchval);
+                  confdata.map[(unsigned)optflag[1]]->values[0]->
+                  value.switchval);
+    }
 }
 
 void checkStrOpt(const char* optflag) {
     confdata_t confdata;
 
-    if (checkOptionValid(optflag, "bar", &confdata))
+    if (checkOptionValid(optflag, "bar", &confdata)) {
         EXPECT_EQ("bar",
                   confdata.map[(unsigned)optflag[1]]->values[0]->value.string);
+    }
 }
 
 void checkNEStrOpt(const char* optflag) {
     confdata_t confdata;
 
-    if (checkOptionValid(optflag, "bar", &confdata))
+    if (checkOptionValid(optflag, "bar", &confdata)) {
         EXPECT_EQ("bar",
                   confdata.map[(unsigned)optflag[1]]->values[0]->value.string);
+    }
     checkOptionInvalid(optflag, "");
 }
 
 void checkFlagHandled(const char* optflag) {
     confdata_t confdata;
 
-    checkOption(optflag, NULL, &confdata, 0);
+    checkOption(&confdata, 0, optflag, NULL);
 }
 
 TEST(CommandOptionsTest, numreq) {
@@ -160,3 +174,39 @@ TEST(CommandOptionsTest, maxdrop) {
 TEST(CommandOptionsTest, nosuchopt) {
     checkOptionInvalid("-W", "");
 }
+
+TEST(CommandOptionsTest, v4v6) {
+    checkOptionInvalid("-4", "-6");
+}
+
+TEST(CommandOptionsTest, ilr6) {
+    confdata_t confdata;
+
+    if (checkOption(&confdata, 1, "-6i", "-leth0", "-r", "50", NULL)) {
+        EXPECT_EQ("eth0",
+                  confdata.map[(unsigned)'l']->values[0]->value.string);
+        EXPECT_EQ(50, confdata.map[(unsigned)'r']->values[0]->value.nnint);
+        EXPECT_EQ(1, confdata.map[(unsigned)'6']->values[0]-> value.switchval);
+        EXPECT_EQ(1, confdata.map[(unsigned)'i']->values[0]-> value.switchval);
+    }
+}
+
+TEST(CommandOptionsTest, ind) {
+    confdata_t confdata;
+
+    if (checkOption(&confdata, 1, "-i", "-n10", "-d", "5", NULL)) {
+        EXPECT_EQ(1, confdata.map[(unsigned)'i']->values[0]-> value.switchval);
+        EXPECT_EQ(10, confdata.map[(unsigned)'n']->values[0]->value.nnint);
+        EXPECT_EQ(5, confdata.map[(unsigned)'d']->values[0]-> value.floatval);
+    }
+}
+
+TEST(CommandOptionsTest, px) {
+    confdata_t confdata;
+
+    if (checkOption(&confdata, 1, "-p", "5.5", "-x", "fo", NULL)) {
+        EXPECT_EQ("fo",
+                  confdata.map[(unsigned)'x']->values[0]->value.string);
+        EXPECT_EQ(5.5, confdata.map[(unsigned)'p']->values[0]->value.floatval);
+    }
+}