]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add support for Rapid Commit, RFC3315 and RFC4039.
authorRoy Marples <roy@marples.name>
Wed, 5 Jun 2013 23:57:03 +0000 (23:57 +0000)
committerRoy Marples <roy@marples.name>
Wed, 5 Jun 2013 23:57:03 +0000 (23:57 +0000)
dhcp-common.c
dhcp-common.h
dhcp.c
dhcp.h
dhcp6.c
dhcp6.h
dhcpcd.8.in
dhcpcd.conf

index 7b217f94d4cef7353ad02321d296e463a1ddba5c..3f28d24a9d9520d67a5ea9ed657c611ed50e4d22 100644 (file)
@@ -329,6 +329,14 @@ print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data,
                return print_string(s, len, dl, data);
        }
 
+       if (type & FLAG) {
+               if (s) {
+                       *s++ = '1';
+                       *s = '\0';
+               }
+               return 2;
+       }
+
        /* DHCPv6 status code */
        if (type & SCODE && dl >= (int)sizeof(u16)) {
                if (s) {
index 22f98bc13f0eff57d5b507693480f1b711a6f949..3a30b25267af29613cd3188dab3370c120267d17 100644 (file)
@@ -56,6 +56,8 @@
 #define ADDRIPV6       (1 << 14)
 #define BINHEX         (1 << 15)
 #define SCODE          (1 << 16)
+#define FLAG           (1 << 17)
+#define NOREQ          (1 << 18)
 
 struct dhcp_opt {
        uint16_t option;
diff --git a/dhcp.c b/dhcp.c
index 8180a40ee02b75f7dd3215ae8c33edd98b0a5d67..6c25da9ad4613e101c501030e3ad0333b1bc0797 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -183,6 +183,7 @@ const struct dhcp_opt dhcp_opts[] = {
        { 75,   IPV4A,          "streettalk_server" },
        { 76,   IPV4A,          "streettalk_directory_assistance_server" },
        { 77,   STRING,         "user_class" },
+       { 80,   FLAG | NOREQ,   "rapid_commit" },
        { 81,   STRING | RFC3397,       "fqdn_name" },
        { 85,   IPV4A,          "nds_servers" },
        { 86,   STRING,         "nds_tree_name" },
@@ -929,6 +930,15 @@ make_message(struct dhcp_message **message,
                p += len;
        }
 
+       if (type == DHCP_DISCOVER &&
+           !(options & DHCPCD_TEST) &&
+           has_option_mask(ifo->requestmask, DHO_RAPIDCOMMIT))
+       {
+               /* RFC 4039 Section 3 */
+               *p++ = DHO_RAPIDCOMMIT;
+               *p++ = 0;
+       }
+
        if (type == DHCP_DISCOVER && ifo->options & DHCPCD_REQUEST)
                PUTADDR(DHO_IPADDRESS, ifo->req_addr);
 
@@ -1037,6 +1047,8 @@ make_message(struct dhcp_message **message,
                        if (!(opt->type & REQUEST ||
                                has_option_mask(ifo->requestmask, opt->option)))
                                continue;
+                       if (opt->type & NOREQ)
+                               continue;
                        if (type == DHCP_INFORM &&
                            (opt->option == DHO_RENEWALTIME ||
                                opt->option == DHO_REBINDTIME))
@@ -2141,7 +2153,7 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
                    get_option_uint8(&tmp, dhcp, i) != 0)
                {
                        /* If we are bootp, then ignore the need for serverid.
-                        * To ignore bootp, require dhcp_message_type instead. */
+                        * To ignore bootp, require dhcp_message_type. */
                        if (type == 0 && i == DHO_SERVERID)
                                continue;
                        log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from);
diff --git a/dhcp.h b/dhcp.h
index c5124df135cb7d8ccfc1d979d5aea058c1b61fb3..ccf07a9de86765556d5fc35e3446bc1d95096e7a 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -103,6 +103,7 @@ enum DHO {
        DHO_VENDORCLASSID          = 60,
        DHO_CLIENTID               = 61,
        DHO_USERCLASS              = 77,  /* RFC 3004 */
+       DHO_RAPIDCOMMIT            = 80,  /* RFC 4039 */
        DHO_FQDN                   = 81,
        DHO_DNSSEARCH              = 119, /* RFC 3397 */
        DHO_CSR                    = 121, /* RFC 3442 */
diff --git a/dhcp6.c b/dhcp6.c
index 9d4d828559ad50fee05abf1a5af892afa04f9b94..d44e227fa5642f1548406089796c2e2511f70a7a 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -109,8 +109,8 @@ const struct dhcp_opt dhcp6_opts[] = {
        { D6_OPTION_SERVERID,           BINHEX,         "server_id" },
        { D6_OPTION_IA_ADDR,            IPV6A,          "ia_addr" },
        { D6_OPTION_PREFERENCE,         UINT8,          "preference" },
-       { D6_OPTION_RAPID_COMMIT,       0,              "rapid_commit" },
        { D6_OPTION_UNICAST,            ADDRIPV6,       "unicast" },
+       { D6_OPTION_RAPID_COMMIT,       FLAG | NOREQ,   "rapid_commit" },
        { D6_OPTION_STATUS_CODE,        SCODE,          "status_code" },
        { D6_OPTION_SIP_SERVERS_NAME,   RFC3397,        "sip_servers_names" },
        { D6_OPTION_SIP_SERVERS_ADDRESS,IPV6A,  "sip_servers_addresses" },
@@ -141,6 +141,7 @@ const struct dhcp_compat dhcp_compats[] = {
        { DHO_DNSDOMAIN,        D6_OPTION_FQDN },
        { DHO_NISSERVER,        D6_OPTION_NIS_SERVERS },
        { DHO_NTPSERVER,        D6_OPTION_SNTP_SERVERS },
+       { DHO_RAPIDCOMMIT,      D6_OPTION_RAPID_COMMIT },
        { DHO_FQDN,             D6_OPTION_FQDN },
        { DHO_DNSSEARCH,        D6_OPTION_DOMAIN_LIST },
        { 0, 0 }
@@ -393,8 +394,9 @@ dhcp6_makemessage(struct interface *ifp)
        si = NULL;
        if (state->state != DH6S_RELEASE) {
                for (opt = dhcp6_opts; opt->option; opt++) {
-                       if (opt->type & REQUEST ||
-                           has_option_mask(ifo->requestmask6, opt->option))
+                       if (!(opt->type & NOREQ) &&
+                           (opt->type & REQUEST ||
+                           has_option_mask(ifo->requestmask6, opt->option)))
                        {
                                n_options++;
                                len += sizeof(*u16);
@@ -463,6 +465,11 @@ dhcp6_makemessage(struct interface *ifp)
                IA = 0;
        }
 
+       if (state->state == DH6S_DISCOVER &&
+           !(options & DHCPCD_TEST) &&
+           has_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT))
+               len += sizeof(*o);
+
        if (m == NULL) {
                m = state->new;
                ml = state->new_len;
@@ -539,6 +546,15 @@ dhcp6_makemessage(struct interface *ifp)
        dhcp6_makevendor(o);
 #endif
 
+       if (state->state == DH6S_DISCOVER &&
+           !(options & DHCPCD_TEST) &&
+           has_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT))
+       {
+               o = D6_NEXT_OPTION(o);
+               o->code = htons(D6_OPTION_RAPID_COMMIT);
+               o->len = 0;
+       }
+
        for (l = 0; IA && l < ifo->iaid_len; l++) {
                o = D6_NEXT_OPTION(o);
                o->code = htons(ifo->ia_type);
@@ -624,9 +640,10 @@ dhcp6_makemessage(struct interface *ifp)
                        o->len = 0;
                        u16 = (uint16_t *)(void *)D6_OPTION_DATA(o);
                        for (opt = dhcp6_opts; opt->option; opt++) {
-                               if (opt->type & REQUEST ||
+                               if (!(opt->type & NOREQ) &&
+                                   (opt->type & REQUEST ||
                                    has_option_mask(ifo->requestmask6,
-                                       opt->option))
+                                       opt->option)))
                                {
                                        *u16++ = htons(opt->option);
                                        o->len += sizeof(*u16);
@@ -1962,6 +1979,13 @@ dhcp6_handledata(__unused void *arg)
                                return;
                        }
                        break;
+               case DH6S_DISCOVER:
+                       if (has_option_mask(ifo->requestmask6,
+                           D6_OPTION_RAPID_COMMIT)  &&
+                           dhcp6_getoption(D6_OPTION_RAPID_COMMIT, r, len))
+                               state->state = DH6S_REQUEST;
+                       else
+                               op = NULL;
                case DH6S_REQUEST: /* FALLTHROUGH */
                case DH6S_RENEW: /* FALLTHROUGH */
                case DH6S_REBIND:
@@ -2004,6 +2028,8 @@ dhcp6_handledata(__unused void *arg)
 
        switch(r->type) {
        case DHCP6_ADVERTISE:
+               if (state->state == DH6S_REQUEST) /* rapid commit */
+                       break;
                ap = TAILQ_FIRST(&state->addrs);
                syslog(LOG_INFO, "%s: ADV %s from %s",
                    ifp->name, ap->saddr, sfrom);
diff --git a/dhcp6.h b/dhcp6.h
index de6e649932bf11f496a17368dfd80c70f90d65f0..f1b8c7dc345fb0f47b0a688b35435f83105e219b 100644 (file)
--- a/dhcp6.h
+++ b/dhcp6.h
@@ -61,9 +61,9 @@
 #define D6_OPTION_IA_ADDR              5
 #define D6_OPTION_PREFERENCE           7
 #define D6_OPTION_ELAPSED              8
-#define D6_OPTION_RAPID_COMMIT         9
 #define D6_OPTION_UNICAST              12
 #define D6_OPTION_STATUS_CODE          13
+#define D6_OPTION_RAPID_COMMIT         14
 #define D6_OPTION_VENDOR               16
 #define D6_OPTION_SIP_SERVERS_NAME     21
 #define D6_OPTION_SIP_SERVERS_ADDRESS  22
index 1dc79399516a2c0d675eabe5bd3fd3b08e2f1d25..5e6ebf78272ec7833578f1950fdcdc5584cd3746 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 5, 2013
+.Dd June 6, 2013
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -603,9 +603,9 @@ running on the
 .Xr dhcpcd-run-hooks 8 ,
 .Xr resolvconf 8
 .Sh STANDARDS
-RFC 951, RFC 1534, RFC 2131, RFC 2132, RFC 2855, RFC 3004, RFC 3315,RFC 3361,
-RFC 3633, RFC 3396, RFC 3397, RFC 3442, RFC 3927, RFC 4075, RFC 4361, RFC 4390,
-RFC 4702, RFC 4704, RFC 4861, RFC 4833, RFC 5227, RFC 5969, RFC 6106.
+RFC 951, RFC 1534, RFC 2131, RFC 2132, RFC 2855, RFC 3004, RFC 3315, RFC 3361,
+RFC 3633, RFC 3396, RFC 3397, RFC 3442, RFC 3927, RFC 4039, RFC 4075, RFC 4361,
+RFC 4390, RFC 4702, RFC 4704, RFC 4861, RFC 4833, RFC 5227, RFC 5969, RFC 6106.
 .Sh AUTHORS
 .An Roy Marples Aq roy@marples.name
 .Sh BUGS
index 1f5b4adbc7ef95c4047c9c846264770c9f7b3fae..78628de13e058af74282a7a8c5c019e113c9a53c 100644 (file)
@@ -16,6 +16,11 @@ fqdn
 # Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
 duid
 
+# Rapid commit support.
+# Safe to enable by default because it requires the equivalent option set
+# on the server to actually work.
+option rapid_commit
+
 # A list of options to request from the DHCP server.
 option domain_name_servers, domain_name, domain_search, host_name
 option classless_static_routes