From: Roy Marples Date: Mon, 30 Jun 2008 16:02:56 +0000 (+0000) Subject: Add support for vendor encapsulated options. Also, MINIAL define now disables all... X-Git-Tag: v4.0.2~260 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=757520c586a98cdea4e1ef571cd9e448f9f9c72b;p=thirdparty%2Fdhcpcd.git Add support for vendor encapsulated options. Also, MINIAL define now disables all configurable options. --- diff --git a/config.h b/config.h index 3f2b1664..eb4e90a2 100644 --- a/config.h +++ b/config.h @@ -33,6 +33,24 @@ /* You can enable/disable various chunks of optional code here. * You would only do this to try and shrink the end binary if dhcpcd * was running on a low memory device */ + +/* Disable everything we possibly can. */ +#ifdef MINIMAL +# ifndef DISABLE_ARP +# define DISABLE_ARP +# endif +# ifndef DISABLE_IPV4LL +# define DISABLE_IPV4LL +# endif +# ifndef DISABLE_DUID +# define DISABLE_DUID +# endif +# ifndef DISABLE_VENDOR +# define DISABLE_VENDOR +# endif +#endif + +/* Enable ARP by default. */ #ifndef DISABLE_ARP # define ENABLE_ARP #endif @@ -64,6 +82,13 @@ # define ENABLE_DUID #endif +/* Allow dhcpcd to send encapsulated vendor options (code 43). + * Although this is enabled by default, only custom networks would really + * need it. */ +#ifndef DISABLE_VENDOR +# define ENABLE_VENDOR +#endif + /* Some systems do not have a working fork. */ /* #define THERE_IS_NO_FORK */ @@ -97,5 +122,4 @@ # define PIDFILE RUNDIR "/" PACKAGE "-%s.pid" #endif - #endif diff --git a/dhcp.c b/dhcp.c index 96f847d6..f5489c75 100644 --- a/dhcp.c +++ b/dhcp.c @@ -863,6 +863,15 @@ make_message(struct dhcp_message **message, } } +#ifdef ENABLE_VENDOR + /* vendor is already encoded correctly, so just add it */ + if (options->vendor[0]) { + *p++ = DHCP_VENDOR; + memcpy(p, options->vendor, options->vendor[0] + 1); + p += options->vendor[0] + 1; + } +#endif + *p++ = DHCP_PARAMETERREQUESTLIST; n_params = p; *p++ = 0; diff --git a/dhcp.h b/dhcp.h index 89565d27..8b88c5e7 100644 --- a/dhcp.h +++ b/dhcp.h @@ -76,6 +76,7 @@ enum DHCP_OPTIONS DHCP_NISDOMAIN = 40, DHCP_NISSERVER = 41, DHCP_NTPSERVER = 42, + DHCP_VENDOR = 43, DHCP_IPADDRESS = 50, DHCP_LEASETIME = 51, DHCP_OPTIONSOVERLOADED = 52, diff --git a/dhcpcd.8.in b/dhcpcd.8.in index 053b9806..ed83ac4f 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -41,6 +41,7 @@ .Op Fl s , -inform Ar address Ns Op Ar /cidr .Op Fl t , -timeout Ar seconds .Op Fl u , -userclass Ar class +.Op Fl v , -vendor Ar code , Ar value .Op Fl C , -nohook Ar hook .Op Fl F , -fqdn Ar FQDN .Op Fl I , -clientid Ar clientid @@ -149,7 +150,7 @@ stop any .Ar hostname from being sent. .It Fl i , -classid Ar classid -Override the DHCP vendor +Override the .Ar classid field sent. The default is dhcpcd . @@ -244,6 +245,18 @@ Tags the DHCP message with the userclass .Ar class . DHCP servers use this give memebers of the class DHCP options other than the default, without having to know things like hardware address or hostname. +.It Fl v , -vendor Ar code , Ns Ar value +Add an enscapulated vendor option. +.Ar code +should be between 1 and 254 inclusive. +Examples. +.Pp +Set the vendor option 01 with an IP address. +.D1 dhcpcd -v 01,192.168.0.2 eth0 +Set the vendor option 02 with a hex code. +.D1 dhcpcd -v 02,01:02:03:04:05 eth0 +Do the above and set a third option with a string and not an IP address. +.D1 dhcpcd -v 01,192.168.0.2 -v 02,01:02:03:04:05 -v 03,\e"192.168.0.2\e" eth0 .It Fl x , -exit This causes an existing .Nm diff --git a/dhcpcd.c b/dhcpcd.c index 585b3d33..c3be5d09 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -51,7 +51,7 @@ const char copyright[] = "Copyright (c) 2006-2008 Roy Marples"; /* Don't set any optional arguments here so we retain POSIX * compatibility with getopt */ -#define OPTS "c:df:h:i:kl:m:no:pr:s:t:u:xAC:DEF:GI:KLO:TV" +#define OPTS "c:df:h:i:kl:m:no:pr:s:t:u:v:xAC:DEF:GI:KLO:TV" static int doversion = 0; static int dohelp = 0; @@ -71,6 +71,7 @@ static const struct option longopts[] = { {"request", optional_argument, NULL, 'r'}, {"timeout", required_argument, NULL, 't'}, {"userclass", required_argument, NULL, 'u'}, + {"vendor", required_argument, NULL, 'v'}, {"exit", no_argument, NULL, 'x'}, {"noarp", no_argument, NULL, 'A'}, {"nohook", required_argument, NULL, 'C'}, @@ -208,8 +209,12 @@ parse_option(int opt, char *oarg, struct options *options) { int i; char *p; - size_t s; - size_t olen; + size_t olen, s; + uint8_t *u; +#ifdef ENABLE_VENDOR + int j; + struct in_addr addr; +#endif if (oarg) olen = strlen(oarg); @@ -242,7 +247,7 @@ parse_option(int opt, char *oarg, struct options *options) return -1; } else { options->classid[0] = strlen(oarg); - strlcpy(options->classid + 1, oarg, + strlcpy((char *)options->classid + 1, oarg, sizeof(options->classid)); } break; @@ -321,11 +326,71 @@ parse_option(int opt, char *oarg, struct options *options) USERCLASS_MAX_LEN); return -1; } - p = options->userclass + options->userclass[0] + 1; - *p++ = olen; - memcpy(p, oarg, olen); + u = options->userclass + options->userclass[0] + 1; + *u++ = olen; + memcpy(u, oarg, olen); options->userclass[0] += olen + 1; break; + case 'v': +#ifdef ENABLE_VENDOR + p = strchr(oarg, ','); + if (!p || !p[1]) { + logger(LOG_ERR, "invalid vendor format"); + return -1; + } + *p = '\0'; + i = atoint(oarg); + oarg = p + 1; + if (i < 1 || i > 254) { + logger(LOG_ERR, "vendor option should be between" + " 1 and 254 inclusive"); + return -1; + } + /* string */ + j = 0; + if (*oarg == '"') { + p = oarg + strlen(oarg) - 1; + if (*p == '"') { + oarg++; + *p = '\0'; + } + } else { + /* hex encoding */ + errno = 0; + s = hwaddr_aton(NULL, oarg); + if (s > 0) + j = 1; + else { + if (inet_aton(oarg, &addr) == 1) { + s = sizeof(addr.s_addr); + j = 2; + } + } + } + if (j == 0) + s = strlen(oarg); + /* Need to include then len char */ + if (options->vendor[0] + s + 1 > VENDOR_MAX_LEN) { + logger(LOG_ERR, "vendor option is too long"); + return -1; + } + u = options->vendor + options->vendor[0] + 1; + options->vendor[0] += s + 2; + *u++ = (uint8_t)i; + *u++ = (uint8_t)s; + switch(j) { + case 0: + memcpy(u, oarg, s); + break; + case 1: + hwaddr_aton(u, oarg); + break; + case 2: + memcpy(u, &addr.s_addr, s); + break; + } +#endif + break; case 'A': options->options &= ~DHCPCD_ARP; /* IPv4LL requires ARP */ @@ -451,7 +516,7 @@ main(int argc, char **argv) options = xzalloc(sizeof(*options)); strlcpy(options->script, SCRIPT, sizeof(options->script)); - options->classid[0] = snprintf(options->classid + 1, CLASSID_MAX_LEN, + options->classid[0] = snprintf((char *)options->classid + 1, CLASSID_MAX_LEN, "%s %s", PACKAGE, VERSION); options->options |= DHCPCD_GATEWAY | DHCPCD_DAEMONISE | DHCPCD_CLIENTID; @@ -531,6 +596,9 @@ main(int argc, char **argv) #ifdef ENABLE_IPV4LL " IPV4LL" #endif +#ifdef ENABLE_VENDOR + " VENDOR" +#endif #ifdef THERE_IS_NO_FORK " THERE_IS_NO_FORK" #endif @@ -843,6 +911,14 @@ main(int argc, char **argv) logger(LOG_INFO, PACKAGE " " VERSION " starting"); } +#ifdef ENABLE_VENDOR + /* Terminate the encapsulated options */ + if (options->vendor[0]) { + options->vendor[0]++; + options->vendor[options->vendor[0]] = DHCP_END; + } +#endif + if (dhcp_run(options, &pid_fd) == 0) retval = EXIT_SUCCESS; diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index 6339d160..5ba825f2 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd Jun 07, 2008 +.Dd Jun 30, 2008 .Dt DHCPCD.CONF 5 SMM .Sh NAME .Nm dhcpcd.conf @@ -115,6 +115,18 @@ be too long or too short and can be changed here. .It Ic userclass Ar string Tag the DHCP messages with the userclass. You can specify more than one. +.It vendor Ar code , Ns Ar value +Add an enscapulated vendor option. +.Ar code +should be between 1 and 254 inclusive. +Examples. +.Pp +Set the vendor option 01 with an IP address. +.D1 vendor 01,192.168.0.2 +Set the vendor option 02 with a hex code. +.D1 vendor 02,01:02:03:04:05 +Set the vendor option 03 with an IP address as a string. +.D1 vendor 03,\e"192.168.0.2\e" .El .Sh SEE ALSO .Xr dhcpcd-run-hooks 8 , diff --git a/dhcpcd.h b/dhcpcd.h index 839e9b4e..8f2224af 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -39,11 +39,12 @@ #include "common.h" #define DEFAULT_TIMEOUT 30 -#define DEFAULT_LEASETIME 3600 /* 1 hour */ +#define DEFAULT_LEASETIME 3600 /* 1 hour */ #define CLASSID_MAX_LEN 48 #define CLIENTID_MAX_LEN 48 #define USERCLASS_MAX_LEN 255 +#define VENDOR_MAX_LEN 255 #ifdef THERE_IS_NO_FORK extern char dhcpcd[PATH_MAX]; @@ -72,9 +73,12 @@ struct options { char interface[IF_NAMESIZE]; char hostname[MAXHOSTNAMELEN]; int fqdn; - char classid[CLASSID_MAX_LEN + 1]; + uint8_t classid[CLASSID_MAX_LEN + 1]; char clientid[CLIENTID_MAX_LEN + 1]; - char userclass[USERCLASS_MAX_LEN + 1]; + uint8_t userclass[USERCLASS_MAX_LEN + 1]; +#ifdef ENABLE_VENDOR + uint8_t vendor[VENDOR_MAX_LEN + 1]; +#endif uint8_t reqmask[256 / 8]; uint8_t nomask[256 / 8]; uint32_t leasetime;