Various fixes
authorSteven Barth <steven@midlink.org>
Mon, 14 Oct 2013 11:12:28 +0000 (13:12 +0200)
committerSteven Barth <steven@midlink.org>
Mon, 14 Oct 2013 11:12:28 +0000 (13:12 +0200)
README
src/config.c
src/dhcpv4.c
src/odhcpd.h
src/ubus.c

diff --git a/README b/README
index c1c0d1eb5dc956e53331ae8924386b94ba09f2b8..f81d260f33ce11ecd9a320d0c04d78907aa4f8ec 100644 (file)
--- a/README
+++ b/README
@@ -21,8 +21,8 @@ prefix delegation and can be used to relay RA, DHCPv6 and NDP between routed
    relay:      RD relay between master and slave interfaces
    a) support for rewriting announced DNS-server addresses in relay mode
    
-3. DHCPv6-support with 2 modes of operation
-   server:     minimalistic server mode
+2. DHCPv6-support with 2 modes of operation
+   server: stateless, stateful and PD-server mode
    a) stateless and stateful address assignment
    b) prefix delegation support
    c) dynamic reconfiguration in case prefixes change
@@ -31,6 +31,9 @@ prefix delegation and can be used to relay RA, DHCPv6 and NDP between routed
    relay:      mostly standards-compliant DHCPv6-relay
    a) support for rewriting announced DNS-server addresses
    
+3. DHCPv4-support
+   server: stateless and stateful mode
+
 4. Proxy for Neighbor Discovery messages (solicitations and advertisments)
    a) support for auto-learning routes to the local routing table
    b) support for marking interfaces "external" not proxying NDP for them
@@ -46,40 +49,68 @@ odhcpd uses cmake:
 * To build DEB or RPM packages use: "make package" afterwards.
 
 
-** Server Mode **
+** Configuration **
 
-0. Server mode is used as a minimalistic alternative for full-blown servers
-   like radvd or ISC DHCP if simplicity or a small footprint matter.
-   Note: The master interface is unused in this mode. It should be set to '.'.
+odhcpd uses a UCI configuration file in /etc/config/dhcp for configuration
+and may also receive information from ubus
 
-1. If there are non-local addresses assigned to the slave interface when a
-   router solicitation is received, said prefixes are announced automatically
-   for stateless autoconfiguration and also offered via stateful DHCPv6.
-   If all prefixes are bigger than /64 all but the first /64 of these prefixes
-   is offered via DHCPv6-PD to downstream routers.
 
-2. If DNS servers should be announced (DHCPv6 server-mode) then a local DNS-
-   proxy (e.g. dnsmasq) needs to be run on the router itself because 6relayd
-   will always announce a local address as DNS-server (if not otherwise
-   configured).
+Section of type odhcpd
 
-3. odhcpd is run with the appropriate configuration.
+Option                 Type            Default                                 Description
+legacy                 bool            0                                               Enable DHCPv4 if start but
+                                                                                                       no dhcpv4 option set
+leasefile              string                                                          DHCP/v6 lease/hostfile
+leasetrigger   string                                                          Lease trigger script
 
 
-** Relay Mode **
+Sections of type dhcp (configure DHCP / DHCPv6 / RA / NDP service)
 
-0. Relay mode is used when a /64-bit IPv6-Prefix should be distributed over
-   several links / isolated layer 2 domains (e.g. if no prefix delegation
-   is available). In this mode NDP (namely Router Discovery and Neighbor
-   Discovery) messages and DHCPv6-messages are proxied. For DHCPv6 also
-   server mode can be used instead of relaying if desired.
+Option                 Type            Default                                 Description
+interface              string          <name of UCI section>   logical OpenWrt interface
+ifname                 string          <resolved from logical> physical network interface
+networkid              string          same as ifname                  compat. alias for ifname
+ignore                 bool            0                                               ignore this interface
+master                 bool            0                                               is a master interface
+                                                                                                       for relaying
+
+ra                             string          disabled                                Router Advert service
+                               [disabled|server|relay|hybrid]
+dhcpv6                 string          disabled                                DHCPv6 service
+                               [disabled|server|relay|hybrid]
+dhcpv4                 string          disabled                                DHCPv4 service
+                               [disabled|server]
+ndp                            string          disabled                                Neighbor Discovery Proxy
+                               [disabled|relay|hybrid]
+
+dynamicdhcp            bool            1                                               dynamically create leases
+                                                                                                       for DHCPv4 and DHCPv6
+dns                            list            <local address>                 DNS servers to announce
+                                                                                                       accepts IPv4 and IPv6
+domain                 list            <local search domain>   Search domains to announce
+
+leasetime              string          12h                                             DHCPv4 address leasetime
+start                  integer         100                                             DHCPv4 pool start
+limit                  integer         150                                             DHCPv4 pool size
+
+ula_compat             bool            0                                               Announce ULA in compat mode
+ra_default             integer         0                                               Override default route
+                               0: default, 1: ignore no public address, 2: ignore all
+ra_management  integer         1                                               RA management mode
+                               0: no M-Flag but A-Flag, 1: both M and A, 2: M but not A
+ra_offlink             bool            0                                               Announce prefixes off-link
+ra_preference  string          medium                                  Route(r) preference
+                               [medium|high|low]
+ndproxy_routing        bool            0                                               Learn routes from NDP
+ndproxy_slave  bool            0                                               NDProxy external slave
+ndproxy_static list                                                            Static NDProxy prefixes
+
+
+Sections of type lease (static leases)
+Option                 Type            Default                                 Description
+ip                             string                                                          IP-Address to lease
+mac                            string                                                          MAC-address
+duid                   string                                                          DUID in base16
+hostid                 string                                                          IPv6 host identifier
+hostname               string                                                          Hostname
 
-1. When starting 6relayd it is required that the master interface - where
-   IPv6-service is already provided - is configured and usable.
-   
-2. If the upstream router doesn't provide or announce a DNS-service that is
-   reachable in an at least site-local scope, a local DNS proxy (e.g. dnsmasq)
-   needs to be run and configued on the same router where 6relayd is running.
-   (This step can most likely be skipped in most environments.)
-   
-3. odhcpd is run with the appropriate configuration.
index 6ae219a813c901c09fb65122e3b1f3716b3a486a..ebc664262d8331788ec31449446c6ab946d55d9f 100644 (file)
@@ -15,6 +15,7 @@ struct config config = {false, NULL, NULL};
 enum {
        IFACE_ATTR_INTERFACE,
        IFACE_ATTR_IFNAME,
+       IFACE_ATTR_NETWORKID,
        IFACE_ATTR_DYNAMICDHCP,
        IFACE_ATTR_IGNORE,
        IFACE_ATTR_LEASETIME,
@@ -25,7 +26,7 @@ enum {
        IFACE_ATTR_RA,
        IFACE_ATTR_DHCPV4,
        IFACE_ATTR_DHCPV6,
-       IFACE_ATTR_NDPROXY,
+       IFACE_ATTR_NDP,
        IFACE_ATTR_DNS,
        IFACE_ATTR_DOMAIN,
        IFACE_ATTR_ULA_COMPAT,
@@ -42,6 +43,7 @@ enum {
 static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
        [IFACE_ATTR_INTERFACE] = { .name = "interface", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
+       [IFACE_ATTR_NETWORKID] = { .name = "networkid", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_DYNAMICDHCP] = { .name = "dynamicdhcp", .type = BLOBMSG_TYPE_BOOL },
        [IFACE_ATTR_IGNORE] = { .name = "ignore", .type = BLOBMSG_TYPE_BOOL },
        [IFACE_ATTR_LEASETIME] = { .name = "leasetime", .type = BLOBMSG_TYPE_STRING },
@@ -52,7 +54,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
        [IFACE_ATTR_RA] = { .name = "ra", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_DHCPV4] = { .name = "dhcpv4", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_DHCPV6] = { .name = "dhcpv6", .type = BLOBMSG_TYPE_STRING },
-       [IFACE_ATTR_NDPROXY] = { .name = "ndproxy", .type = BLOBMSG_TYPE_BOOL },
+       [IFACE_ATTR_NDP] = { .name = "ndp", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },
        [IFACE_ATTR_DOMAIN] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY },
        [IFACE_ATTR_ULA_COMPAT] = { .name = "ula_compat", .type = BLOBMSG_TYPE_BOOL },
@@ -276,6 +278,8 @@ int config_parse_interface(struct blob_attr *b, const char *name, bool overwrite
 #endif
        if ((c = tb[IFACE_ATTR_IFNAME]))
                ifname = blobmsg_get_string(c);
+       else if ((c = tb[IFACE_ATTR_NETWORKID]))
+               ifname = blobmsg_get_string(c);
 
        strncpy(iface->ifname, ifname, sizeof(iface->ifname) - 1);
        iface->inuse = true;
@@ -352,13 +356,15 @@ int config_parse_interface(struct blob_attr *b, const char *name, bool overwrite
                if ((iface->dhcpv6 = parse_mode(blobmsg_get_string(c))) < 0)
                        goto err;
 
-       if ((c = tb[IFACE_ATTR_NDPROXY]))
-               iface->ndp = blobmsg_get_bool(c) ? RELAYD_RELAY : RELAYD_DISABLED;
+       if ((c = tb[IFACE_ATTR_NDP]))
+               if ((iface->ndp = parse_mode(blobmsg_get_string(c))) < 0)
+                       goto err;
 
        if ((c = tb[IFACE_ATTR_DNS])) {
                struct blob_attr *cur;
                int rem;
 
+               iface->always_rewrite_dns = true;
                blobmsg_for_each_attr(cur, c, rem) {
                        if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, NULL))
                                continue;
@@ -513,6 +519,11 @@ void odhcpd_run(void)
                                continue;
 
                        enum odhcpd_mode hybrid_mode = RELAYD_DISABLED;
+#ifdef WITH_UBUS
+                       if (ubus_has_prefix(i->name, i->ifname))
+                               hybrid_mode = RELAYD_RELAY;
+#endif
+
                        if (i->dhcpv6 == RELAYD_HYBRID)
                                i->dhcpv6 = hybrid_mode;
 
index 38b4f9ba5bb9869a19da709897117dc5665e2c37..7a68f66e62a0bed2b4aade7d009d6d86117173b0 100644 (file)
@@ -119,8 +119,8 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable)
                                end = addr.s_addr & mask.s_addr;
 
                                if (ntohl(mask.s_addr) <= 0xffffff00) {
-                                       iface->dhcpv4_start.s_addr = start | htonl(20);
-                                       iface->dhcpv4_end.s_addr = end | htonl(199);
+                                       iface->dhcpv4_start.s_addr = start | htonl(100);
+                                       iface->dhcpv4_end.s_addr = end | htonl(250);
                                } else {
                                        iface->dhcpv4_start.s_addr = start | htonl(10);
                                        iface->dhcpv4_end.s_addr = end | htonl(59);
@@ -168,7 +168,7 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable)
 
 
                if (iface->dhcpv4_leasetime < 60)
-                       iface->dhcpv4_leasetime = 1800;
+                       iface->dhcpv4_leasetime = 43200;
 
                iface->dhcpv4_event.uloop.fd = sock;
                iface->dhcpv4_event.handle_dgram = handle_dhcpv4;
index be8baeb98bee54e567ec584170204a0ab69e69df..fb3db37f80650a4c575a0cb5a2d8742f56033263 100644 (file)
@@ -190,6 +190,7 @@ int config_parse_interface(struct blob_attr *b, const char *iname, bool overwrit
 
 const char* ubus_get_ifname(const char *name);
 void ubus_apply_network(void);
+bool ubus_has_prefix(const char *name, const char *ifname);
 
 
 // Exported module initializers
index 7f69d3db62b6fd63d4a35e294549496716877e86..41d538a9c8c2fed07781ccb6d5e254d56b466a5d 100644 (file)
@@ -160,6 +160,7 @@ enum {
        IFACE_ATTR_IFNAME,
        IFACE_ATTR_UP,
        IFACE_ATTR_DATA,
+       IFACE_ATTR_PREFIX,
        IFACE_ATTR_MAX,
 };
 
@@ -168,6 +169,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
        [IFACE_ATTR_IFNAME] = { .name = "ifname", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_UP] = { .name = "up", .type = BLOBMSG_TYPE_BOOL },
        [IFACE_ATTR_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE },
+       [IFACE_ATTR_PREFIX] = { .name = "ipv6-prefix", .type = BLOBMSG_TYPE_ARRAY },
 };
 
 static void handle_dump(_unused struct ubus_request *req, _unused int type, struct blob_attr *msg)
@@ -308,6 +310,41 @@ const char* ubus_get_ifname(const char *name)
 }
 
 
+bool ubus_has_prefix(const char *name, const char *ifname)
+{
+       struct blob_attr *c, *cur;
+       int rem;
+
+       if (!dump)
+               return NULL;
+
+       blobmsg_for_each_attr(c, dump, rem) {
+               struct blob_attr *tb[IFACE_ATTR_MAX];
+               blobmsg_parse(iface_attrs, IFACE_ATTR_MAX, tb, blob_data(c), blob_len(c));
+
+               if (!tb[IFACE_ATTR_INTERFACE] || !tb[IFACE_ATTR_IFNAME])
+                       continue;
+
+               if (!strcmp(name, blobmsg_get_string(tb[IFACE_ATTR_INTERFACE])) ||
+                               !strcmp(ifname, blobmsg_get_string(tb[IFACE_ATTR_IFNAME])))
+                       continue;
+
+               if ((cur = tb[IFACE_ATTR_PREFIX])) {
+                       if (blobmsg_type(cur) != BLOBMSG_TYPE_ARRAY || !blobmsg_check_attr(cur, NULL))
+                               continue;
+
+                       struct blob_attr *d;
+                       int drem;
+                       blobmsg_for_each_attr(d, cur, drem) {
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+
 int init_ubus(void)
 {
        if (!(ubus = ubus_connect(NULL))) {