dhcpv4: implement router configuration option
authorChristian Mehlis <christian@m3hlis.de>
Tue, 12 Aug 2014 12:58:06 +0000 (14:58 +0200)
committerChristian Mehlis <christian@m3hlis.de>
Tue, 12 Aug 2014 12:58:06 +0000 (14:58 +0200)
RFC 2132 defines:

3.5. Router Option

   The router option specifies a list of IP addresses for routers on the
   client's subnet.  Routers SHOULD be listed in order of preference.

   The code for the router option is 3.  The minimum length for the
   router option is 4 octets, and the length MUST always be a multiple
   of 4.

    Code   Len         Address 1               Address 2
   +-----+-----+-----+-----+-----+-----+-----+-----+--
   |  3  |  n  |  a1 |  a2 |  a3 |  a4 |  a1 |  a2 |  ...
   +-----+-----+-----+-----+-----+-----+-----+-----+--

README
src/config.c
src/dhcpv4.c
src/odhcpd.h

diff --git a/README b/README
index 6011b0f175730bf772373f89be15eacaa9e6b8e5..b86df25fd32f88be8360fca006a9d36ddd9476ad 100644 (file)
--- a/README
+++ b/README
@@ -85,6 +85,8 @@ ndp           string  disabled                Neighbor Discovery Proxy
 
 dynamicdhcp    bool    1                       dynamically create leases
                                                for DHCPv4 and DHCPv6
+router          list    <local address>         Routers to announce
+                                                accepts IPv4 only
 dns            list    <local address>         DNS servers to announce
                                                accepts IPv4 and IPv6
 domain         list    <local search domain>   Search domains to announce
index 068d1a7483a14cba591ec0dd3c1fdbd852e484c1..835db13a7e5e09763bfe87660d8ef2936135b7d0 100644 (file)
@@ -30,6 +30,7 @@ enum {
        IFACE_ATTR_DHCPV4,
        IFACE_ATTR_DHCPV6,
        IFACE_ATTR_NDP,
+       IFACE_ATTR_ROUTER,
        IFACE_ATTR_DNS,
        IFACE_ATTR_DOMAIN,
        IFACE_ATTR_FILTER_CLASS,
@@ -61,6 +62,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
        [IFACE_ATTR_DHCPV4] = { .name = "dhcpv4", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_DHCPV6] = { .name = "dhcpv6", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_NDP] = { .name = "ndp", .type = BLOBMSG_TYPE_STRING },
+       [IFACE_ATTR_ROUTER] = { .name = "router", .type = BLOBMSG_TYPE_ARRAY },
        [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },
        [IFACE_ATTR_DOMAIN] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY },
        [IFACE_ATTR_FILTER_CLASS] = { .name = "filter_class", .type = BLOBMSG_TYPE_STRING },
@@ -152,6 +154,7 @@ static void clean_interface(struct interface *iface)
        free(iface->search);
        free(iface->upstream);
        free(iface->static_ndp);
+       free(iface->dhcpv4_router);
        free(iface->dhcpv4_dns);
        free(iface->dhcpv6_raw);
        free(iface->filter_class);
@@ -409,6 +412,28 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
                        goto err;
        }
 
+       if ((c = tb[IFACE_ATTR_ROUTER])) {
+               struct blob_attr *cur;
+               unsigned rem;
+
+               blobmsg_for_each_attr(cur, c, rem) {
+                       if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, NULL))
+                               continue;
+
+                       struct in_addr addr4;
+                       if (inet_pton(AF_INET, blobmsg_get_string(cur), &addr4) == 1) {
+                               iface->dhcpv4_router = realloc(iface->dhcpv4_router,
+                                               (++iface->dhcpv4_router_cnt) * sizeof(*iface->dhcpv4_router));
+                               if (!iface->dhcpv4_router)
+                                       goto err;
+
+                               iface->dhcpv4_router[iface->dhcpv4_router_cnt - 1] = addr4;
+                       } else {
+                               goto err;
+                       }
+               }
+       }
+
        if ((c = tb[IFACE_ATTR_DNS])) {
                struct blob_attr *cur;
                unsigned rem;
index 2093ecd037b173df7b286f9e08983dae945a8266..7b200cded2b5e70725a8427c0c51b71abd98fa5a 100644 (file)
@@ -384,8 +384,11 @@ static void handle_dhcpv4(void *addr, void *data, size_t len,
                                        len, search_buf);
        }
 
-       dhcpv4_put(&reply, &cookie, DHCPV4_OPT_ROUTER, 4, &ifaddr.sin_addr);
-
+       if (iface->dhcpv4_router_cnt == 0)
+               dhcpv4_put(&reply, &cookie, DHCPV4_OPT_ROUTER, 4, &ifaddr.sin_addr);
+       else
+               dhcpv4_put(&reply, &cookie, DHCPV4_OPT_ROUTER,
+                               4 * iface->dhcpv4_router_cnt, iface->dhcpv4_router);
 
 
        if (iface->dhcpv4_dns_cnt == 0)
index b2b38dc8d47387dbd693bc22f4f87e6671db9796..4c0c28ca166b8ae971b251f81fc8d477a1624c15 100644 (file)
@@ -147,6 +147,8 @@ struct interface {
        // DHCPv4
        struct in_addr dhcpv4_start;
        struct in_addr dhcpv4_end;
+       struct in_addr *dhcpv4_router;
+       size_t dhcpv4_router_cnt;
        struct in_addr *dhcpv4_dns;
        size_t dhcpv4_dns_cnt;
        uint32_t dhcpv4_leasetime;