]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add a static directive that allows the configuration of variables, which
authorRoy Marples <roy@marples.name>
Thu, 1 Jan 2009 14:23:36 +0000 (14:23 +0000)
committerRoy Marples <roy@marples.name>
Thu, 1 Jan 2009 14:23:36 +0000 (14:23 +0000)
supercedes any DHCP configured variables.
If ip_address is configured then we don't bother with a DHCP
transaction.

13 files changed:
bind.c
configure.c
dhcpcd-hooks/20-resolv.conf
dhcpcd-hooks/29-lookup-hostname
dhcpcd-hooks/30-hostname
dhcpcd-hooks/50-ntp.conf
dhcpcd-hooks/50-yp.conf
dhcpcd-run-hooks.8.in
dhcpcd.8.in
dhcpcd.c
dhcpcd.conf.5.in
if-options.c
if-options.h

diff --git a/bind.c b/bind.c
index 38cc74fbd4757e5bb0d6f0db2dffd0ced308f69e..b692ab92ef2b96bcbe6609c29b09cbe819888959 100644 (file)
--- a/bind.c
+++ b/bind.c
@@ -1,6 +1,6 @@
 /* 
  * dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -129,7 +129,13 @@ bind_interface(void *arg)
        state->new = state->offer;
        state->offer = NULL;
        get_lease(lease, state->new);
-       if (IN_LINKLOCAL(htonl(state->new->yiaddr))) {
+       if (ifo->options & DHCPCD_STATIC) {
+               syslog(LOG_INFO, "%s: using static address %s",
+                      iface->name, inet_ntoa(lease->addr));
+               lease->leasetime = ~0U;
+               lease->net.s_addr = ifo->request_netmask.s_addr;
+               reason = "STATIC";
+       } else if (IN_LINKLOCAL(htonl(state->new->yiaddr))) {
                syslog(LOG_INFO, "%s: using IPv4LL address %s",
                       iface->name, inet_ntoa(lease->addr));
                lease->leasetime = ~0U;
@@ -146,7 +152,7 @@ bind_interface(void *arg)
        } else {
                if (gettimeofday(&tv, NULL) == 0)
                        lease->leasedfrom = tv.tv_sec;
-               if (lease->frominfo)
+               else if (lease->frominfo)
                        reason = "TIMEOUT";
                if (lease->leasetime == ~0U) {
                        lease->renewaltime = lease->rebindtime = lease->leasetime;
@@ -176,7 +182,7 @@ bind_interface(void *arg)
                               inet_ntoa(lease->addr), lease->leasetime);
                }
        }
-       if (!reason) {
+       if (reason == NULL) {
                if (state->old) {
                        if (state->old->yiaddr == state->new->yiaddr &&
                            lease->server.s_addr)
index 769b411a6b14d44f9b91196c295bf565137af0fe..917bd181cba0c564ef34a2da146c2cf5dcc4e396 100644 (file)
@@ -1,6 +1,6 @@
 /* 
  * dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -91,6 +91,50 @@ exec_script(char *const *argv, char *const *env)
        return pid;
 }
 
+static char *
+make_var(const char *prefix, const char *var)
+{
+       size_t len;
+       char *v;
+
+       len = strlen(prefix) + strlen(var) + 2;
+       v = xmalloc(len);
+       snprintf(v, len, "%s_%s", prefix, var);
+       return v;
+}
+
+
+static void
+append_config(char ***env, ssize_t *len,
+             const char *prefix, const char *const *config)
+{
+       ssize_t i, j, e1;
+       char **ne, *eq;
+
+       if (config == NULL)
+               return;
+
+       ne = *env;
+       for (i = 0; config[i] != NULL; i++) {
+               eq = strchr(config[i], '=');
+               e1 = eq - config[i] + 1;
+               for (j = 0; j < *len; j++) {
+                       if (strncmp(ne[j] + strlen(prefix) + 1, config[i], e1) == 0) {
+                               free(ne[j]);
+                               ne[j] = make_var(prefix, config[i]);
+                               break;
+                       }
+               }
+               if (j == *len) {
+                       j++;
+                       ne = xrealloc(ne, sizeof(char *) * (j + 1));
+                       ne[j - 1] = make_var(prefix, config[i]);
+                       *len = j;
+               }
+       }
+       *env = ne;
+}
+
 int
 run_script(const struct interface *iface, const char *reason)
 {
@@ -149,6 +193,8 @@ run_script(const struct interface *iface, const char *reason)
                        elen += configure_env(env + elen, "old",
                                        iface->state->old, ifo);
                }
+               append_config(&env, &elen, "old",
+                             (const char *const *)ifo->config);
        }
        if (iface->state->new) {
                e = configure_env(NULL, NULL, iface->state->new, ifo);
@@ -157,7 +203,10 @@ run_script(const struct interface *iface, const char *reason)
                        elen += configure_env(env + elen, "new",
                                        iface->state->new, ifo);
                }
+               append_config(&env, &elen, "new",
+                             (const char *const *)ifo->config);
        }
+
        /* Add our base environment */
        if (ifo->environ) {
                e = 0;
@@ -332,6 +381,30 @@ add_subnet_route(struct rt *rt, const struct interface *iface)
        return r;
 }
 
+static struct rt *
+get_routes(const struct interface *iface) {
+       struct rt *rt, *nrt, *r = NULL;
+
+       if (iface->state->options->routes != NULL) {
+               for (rt = iface->state->options->routes;
+                    rt != NULL;
+                    rt = rt->next)
+               {
+                       if (r == NULL)
+                               r = nrt = xmalloc(sizeof(*r));
+                       else {
+                               r->next = xmalloc(sizeof(*r));
+                               r = r->next;
+                       }
+                       memcpy(r, rt, sizeof(*r));
+                       r->next = NULL;
+               }
+               return nrt;
+       }
+
+       return get_option_routes(iface->state->new);
+}
+
 static void
 build_routes()
 {
@@ -341,7 +414,7 @@ build_routes()
        for (ifp = ifaces; ifp; ifp = ifp->next) {
                if (ifp->state->new == NULL)
                        continue;
-               dnr = get_option_routes(ifp->state->new);
+               dnr = get_routes(ifp);
                dnr = add_subnet_route(dnr, ifp);
                for (rt = dnr; rt && (rtn = rt->next, 1); lrt = rt, rt = rtn) {
                        rt->iface = ifp;
index 0d812ca18e92a3fe44883e3a81923849cb62da73..601ef0ad69f35fb0d7b52286a2c62e538f730b32 100644 (file)
@@ -119,6 +119,6 @@ remove_resolv_conf()
 }
 
 case "${reason}" in
-BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT)      add_resolv_conf;;
-PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP)       remove_resolv_conf;;
+BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC)       add_resolv_conf;;
+PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP)               remove_resolv_conf;;
 esac
index 3dfade3f2203e7de36c97be406944bb6a8e05c43..3214c50de8f925358ccf411e965b3e574b53496f 100644 (file)
@@ -30,5 +30,5 @@ set_hostname()
 }
 
 case "${reason}" in
-BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT)      set_hostname;;
+BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC)       set_hostname;;
 esac
index b2e5fc89e2edbb7fe373756effb50a926d61612d..1f73d1fd89c85a9eb7fb4c1b409486c4704cc501 100644 (file)
@@ -24,5 +24,5 @@ set_hostname()
 }
 
 case "${reason}" in
-BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT)      set_hostname;;
+BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC)       set_hostname;;
 esac
index 8c92f2799b30a71f1c6bd2d71f32f9721d5aea91..3193cb2d9deca7434b3ea53b6abebd1e581b4c3d 100644 (file)
@@ -84,6 +84,6 @@ remove_ntp_conf()
 }
 
 case "${reason}" in
-BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT)      add_ntp_conf add;;
-PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP)       remove_ntp_conf del;;
+BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC)       add_ntp_conf add;;
+PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP)               remove_ntp_conf del;;
 esac
index a2296ebfe4d957ae91bd56f84991052e3361f93c..6060696e9000ee039b43163395b4b8d04d3f7966 100644 (file)
@@ -44,6 +44,6 @@ restore_yp_conf()
 }
 
 case "${reason}" in
-BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT)      make_yp_conf;;
-EXPIRE|FAIL|IPV4LL|RELEASE|STOP)               restore_yp_conf;;
+BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC)       make_yp_conf;;
+EXPIRE|FAIL|IPV4LL|RELEASE|STOP)                       restore_yp_conf;;
 esac
index a8b25ed9cc00ba6dcb43b3eafcb30a89d9fdf321..a2e4951d56911bece23d97318dd021e1a1ac3105 100644 (file)
@@ -1,4 +1,4 @@
-.\" Copyright 2006-2008 Roy Marples
+.\" Copyright 2006-2009 Roy Marples
 .\" All rights reserved
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd October 07, 2008
+.Dd January 1, 2008
 .Dt DHCPCD.SH 8 SMM
 .Sh NAME
 .Nm dhcpcd-run-hooks
@@ -83,7 +83,7 @@ dhcpcd has rebound to a new DHCP server.
 .It Dv REBOOT
 dhcpcd successfully requested a lease from a DHCP server.
 .It Dv EXPIRE
-dhcpcd's lease expired and it failed to obtain a new one.
+dhcpcd's lease or state expired and it failed to obtain a new one.
 .It Dv IPV4LL
 dhcpcd failed to contact any DHCP servers but did obtain an IPV4LL address.
 .It Dv FAIL
@@ -95,6 +95,9 @@ dhcpcd received an OFFER from a DHCP server but will not configure the
 interface.
 This is primarily used to test the variables are filled correctly for the
 script to process them.
+.It Dv STATIC
+dhcpcd has been configured with a static configuration which has not been
+obtained from a DHCP server.
 .El
 .Sh FILES 
 When
index f385072c9bce4a3ae52f5f98b246ca5a9acd1399..ac0be091f829a83a445f5eaf371dcc514346b958 100644 (file)
@@ -1,4 +1,4 @@
-.\" Copyright 2006-2008 Roy Marples
+.\" Copyright 2006-2009 Roy Marples
 .\" All rights reserved
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd December 16, 2008
+.Dd January 1, 2009
 .Dt DHCPCD 8 SMM
 .Sh NAME
 .Nm dhcpcd
@@ -49,6 +49,7 @@
 .Op Fl I , -clientid Ar clientid
 .Op Fl O , -nooption Ar option
 .Op Fl Q , -require Ar option
+.Op Fl S , -static Ar value
 .Op Fl X , -blacklist Ar address
 .Op Fl Z , -denyinterfaces Ar pattern
 .Op interface
@@ -424,6 +425,21 @@ To enforce that
 only responds to DHCP servers and not BOOTP servers, you can
 .Fl Q
 .Ar dhcp_message_type .
+.It Fl S, -static Ar value
+Configures a static
+.Ar value .
+If you set
+.Ic ip_address
+then
+.Nm
+will not attempt to obtain a lease and just use the value for the address with
+an infinite lease time.
+.Pp
+Here is an example which configures a static address, routes and dns.
+.D1 dhcpcd -S ip_address=192.168.0.10/24 \e
+.D1 -S routers=192.168.0.1 \e
+.D1 -S domain_name_servers=192.168.0.1 \e
+.D1 eth0
 .It Fl T, -test
 On receipt of OFFER messages just call
 .Pa @SCRIPT@
index 49d48a8eb7916c1025d81772a4540fbd0ad3d2c7..033f1368bec60cfcf970d0381349da64b5e88add 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -1,6 +1,6 @@
 /* 
  * dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
  * SUCH DAMAGE.
  */
 
-const char copyright[] = "Copyright (c) 2006-2008 Roy Marples";
+const char copyright[] = "Copyright (c) 2006-2009 Roy Marples";
 
 #include <sys/file.h>
 #include <sys/stat.h>
@@ -778,6 +778,28 @@ start_reboot(struct interface *iface)
                send_request(iface);
 }
 
+static void
+start_static(struct interface *iface)
+{
+       struct dhcp_message *dhcp;
+       struct if_options *ifo = iface->state->options;
+       uint8_t *p;
+       uint32_t u32;
+
+       dhcp = xzalloc(sizeof(*dhcp));
+       dhcp->yiaddr = ifo->request_address.s_addr;
+       p = dhcp->options;
+       *p++ = DHO_SUBNETMASK;
+       *p++ = sizeof(u32);
+       u32 = ifo->request_netmask.s_addr;
+       memcpy(p, &u32, sizeof(u32));
+       *p++ = DHO_END;
+
+       iface->state->offer = dhcp;
+       delete_timeout(NULL, iface);
+       bind_interface(iface);
+}
+
 void
 start_interface(void *arg)
 {
@@ -800,6 +822,10 @@ start_interface(void *arg)
                start_discover(iface);
                return;
        }
+       if (ifo->options & DHCPCD_STATIC) {
+               start_static(iface);
+               return;
+       }
        if (ifo->request_address.s_addr) {
                /* This also changes netmask */
                if (iface->state->options->options & DHCPCD_INFORM &&
index c7aa7219a84d358e271569bcee29568a51120fbf..f136a944d3f596d03d00bdedc9d8d73c55c61178 100644 (file)
@@ -1,4 +1,4 @@
-.\" Copyright 2006-2008 Roy Marples
+.\" Copyright 2006-2009 Roy Marples
 .\" All rights reserved
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd December 16, 2008
+.Dd January 1, 2009
 .Dt DHCPCD.CONF 5 SMM
 .Sh NAME
 .Nm dhcpcd.conf
@@ -175,6 +175,21 @@ Use
 .Ar script
 instead of the default
 .Pa @SCRIPT@ .
+.It Ic static Ar value
+Configures a static
+.Ar value .
+If you set
+.Ic ip_address
+then
+.Nm dhcpcd
+will not attempt to obtain a lease and just use the value for the address with
+an infinite lease time.
+.Pp
+Here is an example which configures a static address, routes and dns.
+.D1 interface eth0
+.D1 static ip_address=192.168.0.10/24
+.D1 static routers=192.168.0.1
+.D1 static domain_name_servers=192.168.0.1
 .It Ic timeout Ar seconds
 The default timeout for waiting for a DHCP response is 30 seconds which may
 be too long or too short and can be changed here.
index 6d031295cc1460c9b1e91f4d258a4a8dc293fefe..abbb92ccfb3f153ba48c558c6d59b2e2057621e3 100644 (file)
@@ -1,6 +1,6 @@
 /* 
  * dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,7 @@ const struct option cf_options[] = {
        {"noipv4ll",        no_argument,       NULL, 'L'},
        {"nooption",        optional_argument, NULL, 'O'},
        {"require",         required_argument, NULL, 'Q'},
+       {"static",          required_argument, NULL, 'S'},
        {"test",            no_argument,       NULL, 'T'},
        {"variables",       no_argument,       NULL, 'V'},
        {"blacklist",       required_argument, NULL, 'X'},
@@ -263,13 +264,40 @@ splitv(int *argc, char **argv, const char *arg)
        return v;       
 }
 
+
+static int
+parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg)
+{
+       char *p;
+       int i;
+
+       if (arg == NULL || *arg == '\0')
+               return 0;
+       if ((p = strchr(arg, '/')) != NULL) {
+               *p++ = '\0';
+               if (net != NULL &&
+                   (sscanf(p, "%d", &i) != 1 ||
+                    inet_cidrtoaddr(i, net) != 0))
+               {
+                       syslog(LOG_ERR, "`%s' is not a valid CIDR", p);
+                       return -1;
+               }
+       }
+       if (addr != NULL && inet_aton(arg, addr) == 0) {
+               syslog(LOG_ERR, "`%s' is not a valid IP address", arg);
+               return -1;
+       }
+       return 0;
+}
+
 static int
 parse_option(struct if_options *ifo, int opt, const char *arg)
 {
        int i;
-       char *p = NULL;
+       char *p = NULL, *np;
        ssize_t s;
        struct in_addr addr;
+       struct rt *rt;
 
        switch(opt) {
        case 'd': /* FALLTHROUGH */
@@ -351,34 +379,17 @@ parse_option(struct if_options *ifo, int opt, const char *arg)
                ifo->options &= ~DHCPCD_ARP;
                if (!arg || *arg == '\0') {
                        ifo->request_address.s_addr = 0;
-                       break;
                } else {
-                       if ((p = strchr(arg, '/'))) {
-                               /* nullify the slash, so the -r option
-                                * can read the address */
-                               *p++ = '\0';
-                               if (sscanf(p, "%d", &i) != 1 ||
-                                   inet_cidrtoaddr(i, &ifo->request_netmask) != 0)
-                               {
-                                       syslog(LOG_ERR,
-                                              "`%s' is not a valid CIDR",
-                                              p);
-                                       return -1;
-                               }
-                       }
+                       if (parse_addr(&ifo->request_address,
+                                      &ifo->request_netmask,
+                                      arg) != 0)
+                               return -1;
                }
-               /* FALLTHROUGH */
+               break;
        case 'r':
-               if (!(ifo->options & DHCPCD_INFORM))
-                       ifo->options |= DHCPCD_REQUEST;
-               if (arg && !inet_aton(arg, &ifo->request_address)) {
-                       syslog(LOG_ERR, "`%s' is not a valid IP address",
-                              arg);
+               ifo->options |= DHCPCD_REQUEST;
+               if (parse_addr(&ifo->request_address, NULL, arg) != 0)
                        return -1;
-               }
-               /* Restore the slash */
-               if (ifo->options & DHCPCD_INFORM && p)
-                       *--p = '/';
                break;
        case 't':
                ifo->timeout = atoint(arg);
@@ -531,6 +542,78 @@ parse_option(struct if_options *ifo, int opt, const char *arg)
                        return -1;
                }
                break;
+       case 'S':
+               p = strchr(arg, '=');
+               if (p == NULL) {
+                       syslog(LOG_ERR, "static assignment required");
+                       return -1;
+               }
+               p++;
+               if (strncmp(arg, "ip_address=", strlen("ip_address=")) == 0) {
+                       if (parse_addr(&ifo->request_address,
+                                      &ifo->request_netmask, p) != 0)
+                               return -1;
+
+                       ifo->options |= DHCPCD_STATIC;
+               } else if (strncmp(arg, "routes=", strlen("routes=")) == 0 ||
+                          strncmp(arg, "static_routes=", strlen("static_routes=")) == 0 ||
+                          strncmp(arg, "classless_static_routes=", strlen("classless_static_routes=")) == 0 ||
+                          strncmp(arg, "ms_classless_static_routes=", strlen("ms_classless_static_routes=")) == 0)
+               {
+                       np = strchr(p, ' ');
+                       if (np == NULL) {
+                               syslog(LOG_ERR, "all routes need a gateway");
+                               return -1;
+                       }
+                       *np++ = '\0';
+                       while (*np == ' ')
+                               np++;
+                       if (ifo->routes == NULL) {
+                               rt = ifo->routes = xmalloc(sizeof(*rt));
+                       } else {
+                               rt = ifo->routes;
+                               while (rt->next)
+                                       rt = rt->next;
+                               rt->next = xmalloc(sizeof(*rt));
+                               rt = rt->next;
+                       }
+                       rt->next = NULL;
+                       if (parse_addr(&rt->dest, &rt->net, p) == -1 ||
+                           parse_addr(&rt->gate, NULL, np) == -1)
+                               return -1;
+               } else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
+                       if (ifo->routes == NULL) {
+                               rt = ifo->routes = xzalloc(sizeof(*rt));
+                       } else {
+                               rt = ifo->routes;
+                               while (rt->next)
+                                       rt = rt->next;
+                               rt->next = xmalloc(sizeof(*rt));
+                               rt = rt->next;
+                       }
+                       rt->dest.s_addr = 0;
+                       rt->net.s_addr = 0;
+                       rt->next = NULL;
+                       if (parse_addr(&rt->gate, NULL, p) == -1)
+                               return -1;
+               } else {
+                       s = 0;
+                       if (ifo->config != NULL) {
+                               while (ifo->config[s] != NULL) {
+                                       if (strncmp(ifo->config[s], arg, p - arg) == 0) {
+                                               printf("match\n");
+                                               free(ifo->config[s]);
+                                               ifo->config[s] = xstrdup(arg);
+                                               return 1;
+                                       }
+                                       s++;
+                               }
+                       }
+                       ifo->config = xrealloc(ifo->config, sizeof(char *) * (s + 2));
+                       ifo->config[s] = xstrdup(arg);
+                       ifo->config[s + 1] = NULL;
+               }
+               break;
        case 'X':
                if (!inet_aton(arg, &addr)) {
                        syslog(LOG_ERR, "`%s' is not a valid IP address",
@@ -674,6 +757,13 @@ free_options(struct if_options *ifo)
                                free(ifo->environ[i++]);
                        free(ifo->environ);
                }
+               if (ifo->config) {
+                       i = 0;
+                       while (ifo->config[i])
+                               free(ifo->config[i++]);
+                       free(ifo->config);
+               }
+               free_routes(ifo->routes);
                free(ifo->blacklist);
                free(ifo);
        }
index 1d90709144fe4760d347a54a7e1d3de79b19c40c..545e74791b623599582b69640d96f86bd610cd61 100644 (file)
@@ -1,6 +1,6 @@
 /* 
  * dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
  * All rights reserved
 
  * Redistribution and use in source and binary forms, with or without
@@ -52,6 +52,7 @@
 #define DHCPCD_RELEASE         (1 << 1)
 #define DHCPCD_DOMAIN          (1 << 2)
 #define DHCPCD_GATEWAY         (1 << 3)
+#define DHCPCD_STATIC          (1 << 4)
 #define DHCPCD_LASTLEASE       (1 << 7)
 #define DHCPCD_INFORM          (1 << 8)
 #define DHCPCD_REQUEST         (1 << 9)
@@ -82,6 +83,8 @@ struct if_options {
 
        struct in_addr request_address;
        struct in_addr request_netmask;
+       struct rt *routes;
+       char **config;
 
        char **environ;
        char script[PATH_MAX];