]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add support for vendor encapsulated options. Also, MINIAL define now disables all...
authorRoy Marples <roy@marples.name>
Mon, 30 Jun 2008 16:02:56 +0000 (16:02 +0000)
committerRoy Marples <roy@marples.name>
Mon, 30 Jun 2008 16:02:56 +0000 (16:02 +0000)
config.h
dhcp.c
dhcp.h
dhcpcd.8.in
dhcpcd.c
dhcpcd.conf.5.in
dhcpcd.h

index 3f2b16647426fd711cfd89b689104034f9f24955..eb4e90a24b4e46c3fefce3dbfcaf52a5a160de45 100644 (file)
--- a/config.h
+++ b/config.h
 /* 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
 # 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 */
 
 # define PIDFILE               RUNDIR "/" PACKAGE "-%s.pid"
 #endif
 
-
 #endif
diff --git a/dhcp.c b/dhcp.c
index 96f847d658d8033eaf1acb60de0ddc6c85ac8cef..f5489c75f90e53d91aa46329f1436c110687a8a9 100644 (file)
--- 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 89565d27643b799710ef2f9d64965480c1c56da2..8b88c5e7d0ce1dc7e4fdeb812ed5beadf447de62 100644 (file)
--- 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,
index 053b98064ac55d2ec6e75d46c20a45c122f0a104..ed83ac4fa79464c53153326caf4694b7444af2d0 100644 (file)
@@ -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 <version>.
@@ -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
index 585b3d334f5d2deb28d6782bb3ae2a3a9d2b3b7d..c3be5d09161d7f8ce9fe1b9fc51dffa60644ad4d 100644 (file)
--- 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;
 
index 6339d16020d1b62c6d64d63130d70120fd6e34b7..5ba825f2dc090fa3be991edf831b3c20a3de6d94 100644 (file)
@@ -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 ,
index 839e9b4eae4e168085054b8dc91d8b9784df81dc..8f2224af28bb11727aa60cebb0682ff8c2d9ef5a 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
 #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;