]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
reject <option> will now reject any DHCP message that contains that option.
authorRoy Marples <roy@marples.name>
Tue, 20 Jan 2015 10:42:47 +0000 (10:42 +0000)
committerRoy Marples <roy@marples.name>
Tue, 20 Jan 2015 10:42:47 +0000 (10:42 +0000)
dhcp.c
dhcp6.c
dhcpcd.conf.5.in
if-options.c
if-options.h

diff --git a/dhcp.c b/dhcp.c
index 23bdaf19cda1613a45af2d30a65ea6cd08307b58..2d73de0cefbd891141907d18eebc0518c41f7ed8 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -2486,6 +2486,16 @@ dhcp_handledhcp(struct interface *iface, struct dhcp_message **dhcpp,
        /* reset the message counter */
        state->interval = 0;
 
+       /* Ensure that no reject options are present */
+       for (i = 1; i < 255; i++) {
+               if (has_option_mask(ifo->rejectmask, i) &&
+                   get_option_uint8(iface->ctx, &tmp, dhcp, (uint8_t)i) == 0)
+               {
+                       log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from);
+                       return;
+               }
+       }
+
        if (type == DHCP_NAK) {
                /* For NAK, only check if we require the ServerID */
                if (has_option_mask(ifo->requiremask, DHO_SERVERID) &&
@@ -2522,6 +2532,23 @@ dhcp_handledhcp(struct interface *iface, struct dhcp_message **dhcpp,
                return;
        }
 
+       /* Ensure that all required options are present */
+       for (i = 1; i < 255; i++) {
+               if (has_option_mask(ifo->requiremask, i) &&
+                   get_option_uint8(iface->ctx, &tmp, dhcp, (uint8_t)i) != 0)
+               {
+                       /* If we are bootp, then ignore the need for serverid.
+                        * To ignore bootp, require dhcp_message_type.
+                        * However, nothing really stops bootp from providing
+                        * DHCP style options as well so the above isn't
+                        * always true. */
+                       if (type == 0 && i == DHO_SERVERID)
+                               continue;
+                       log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from);
+                       return;
+               }
+       }
+
        /* DHCP Auto-Configure, RFC 2563 */
        if (type == DHCP_OFFER && dhcp->yiaddr == 0) {
                log_dhcp(LOG_WARNING, "no address given", iface, dhcp, from);
@@ -2568,23 +2595,6 @@ dhcp_handledhcp(struct interface *iface, struct dhcp_message **dhcpp,
                return;
        }
 
-       /* Ensure that all required options are present */
-       for (i = 1; i < 255; i++) {
-               if (has_option_mask(ifo->requiremask, i) &&
-                   get_option_uint8(iface->ctx, &tmp, dhcp, (uint8_t)i) != 0)
-               {
-                       /* If we are bootp, then ignore the need for serverid.
-                        * To ignore bootp, require dhcp_message_type.
-                        * However, nothing really stops bootp from providing
-                        * DHCP style options as well so the above isn't
-                        * always true. */
-                       if (type == 0 && i == DHO_SERVERID)
-                               continue;
-                       log_dhcp(LOG_WARNING, "reject DHCP", iface, dhcp, from);
-                       return;
-               }
-       }
-
        /* Ensure that the address offered is valid */
        if ((type == 0 || type == DHCP_OFFER || type == DHCP_ACK) &&
            (dhcp->ciaddr == INADDR_ANY || dhcp->ciaddr == INADDR_BROADCAST) &&
diff --git a/dhcp6.c b/dhcp6.c
index 20c3d7120e76e056dac5665167416ff6a96ecd76..30696cc2080a126a7c3722cc5b0db8c36e8ac792 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -2686,6 +2686,14 @@ dhcp6_handledata(void *arg)
                            ifp->name, opt->var, ctx->sfrom);
                        return;
                }
+               if (has_option_mask(ifo->rejectmask6, opt->option) &&
+                   dhcp6_getmoption(opt->option, r, len))
+               {
+                       syslog(LOG_WARNING,
+                           "%s: reject DHCPv6 (option %s) from %s",
+                           ifp->name, opt->var, ctx->sfrom);
+                       return;
+               }
        }
 
        /* Authenticate the message */
index 778ee93262828f9b9acf6fdf7fed90eaa785335a..9b60de72bc4f9e2faeedc0f35ce0ca2cb11de527 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd January 8, 2015
+.Dd January 20, 2015
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -489,6 +489,14 @@ To enforce that
 only responds to DHCP servers and not BOOTP servers, you can
 .Ic require
 .Ar dhcp_message_type .
+This isn't an exact science though because a BOOTP server can send DHCP like
+options.
+.It Ic reject Ar option
+Reject a DHCP message that contains the
+.Ar option .
+This is useful when you cannot use
+.Ic require
+to select / de-select BOOTP messages.
 .It Ic script Ar script
 Use
 .Ar script
index 904be4f648a7ed56f6f6a3b4c665b50ba19c4175..86b0a12b6d7d449c401728588ce68a83bc2a09bb 100644 (file)
@@ -95,6 +95,7 @@
 #define O_PFXDLGMIX            O_BASE + 37
 #define O_IPV6RA_AUTOCONF      O_BASE + 38
 #define O_IPV6RA_NOAUTOCONF    O_BASE + 39
+#define O_REJECT               O_BASE + 40
 
 const struct option cf_options[] = {
        {"background",      no_argument,       NULL, 'b'},
@@ -184,6 +185,7 @@ const struct option cf_options[] = {
        {"slaac",           required_argument, NULL, O_SLAAC},
        {"gateway",         no_argument,       NULL, O_GATEWAY},
        {"ia_pd_mix",       no_argument,       NULL, O_PFXDLGMIX},
+       {"reject",          required_argument, NULL, O_REJECT},
        {NULL,              0,                 NULL, '\0'}
 };
 
@@ -527,7 +529,7 @@ set_option_space(struct dhcpcd_ctx *ctx,
     const struct dhcp_opt **d, size_t *dl,
     const struct dhcp_opt **od, size_t *odl,
     struct if_options *ifo,
-    uint8_t *request[], uint8_t *require[], uint8_t *no[])
+    uint8_t *request[], uint8_t *require[], uint8_t *no[], uint8_t *reject[])
 {
 
 #if !defined(INET) && !defined(INET6)
@@ -544,6 +546,7 @@ set_option_space(struct dhcpcd_ctx *ctx,
                *request = ifo->requestmask6;
                *require = ifo->requiremask6;
                *no = ifo->nomask6;
+               *reject = ifo->rejectmask6;
                return arg + strlen("dhcp6_");
        }
 #endif
@@ -562,6 +565,7 @@ set_option_space(struct dhcpcd_ctx *ctx,
        *request = ifo->requestmask;
        *require = ifo->requiremask;
        *no = ifo->nomask;
+       *reject = ifo->rejectmask;
        return arg;
 }
 
@@ -649,7 +653,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
        in_addr_t *naddr;
        struct rt *rt;
        const struct dhcp_opt *d, *od;
-       uint8_t *request, *require, *no;
+       uint8_t *request, *require, *no, *reject;
        struct dhcp_opt **dop, *ndop;
        size_t *dop_len, dl, odl;
        struct vivco *vivco;
@@ -751,9 +755,21 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                break;
        case 'o':
                arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-                   &request, &require, &no);
+                   &request, &require, &no, &reject);
                if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
-                   make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
+                   make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
+                   make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
+               {
+                       syslog(LOG_ERR, "unknown option `%s'", arg);
+                       return -1;
+               }
+               break;
+       case O_REJECT:
+               arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
+                   &request, &require, &no, &reject);
+               if (make_option_mask(d, dl, od, odl, reject, arg, 1) != 0 ||
+                   make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
+                   make_option_mask(d, dl, od, odl, require, arg, -1) != 0)
                {
                        syslog(LOG_ERR, "unknown option `%s'", arg);
                        return -1;
@@ -970,7 +986,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                break;
        case 'O':
                arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-                   &request, &require, &no);
+                   &request, &require, &no, &reject);
                if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
                    make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
                    make_option_mask(d, dl, od, odl, no, arg, 1) != 0)
@@ -981,10 +997,11 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                break;
        case 'Q':
                arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-                   &request, &require, &no);
+                   &request, &require, &no, &reject);
                if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 ||
                    make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
-                   make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
+                   make_option_mask(d, dl, od, odl, no, arg, -1) != 0 ||
+                   make_option_mask(d, dl, od, odl, reject, arg, -1) != 0)
                {
                        syslog(LOG_ERR, "unknown option `%s'", arg);
                        return -1;
@@ -1174,7 +1191,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
                break;
        case O_DESTINATION:
                arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
-                   &request, &require, &no);
+                   &request, &require, &no, &reject);
                if (make_option_mask(d, dl, od, odl,
                    ifo->dstmask, arg, 2) != 0)
                {
index ec7d3191f21e83dd8e5c0fc1aad024a3761703b8..41d2dca147372494618b680c17e1e2d635b28a10 100644 (file)
@@ -141,9 +141,11 @@ struct if_options {
        uint8_t requestmask[256 / NBBY];
        uint8_t requiremask[256 / NBBY];
        uint8_t nomask[256 / NBBY];
+       uint8_t rejectmask[256 / NBBY];
        uint8_t requestmask6[(UINT16_MAX + 1) / NBBY];
        uint8_t requiremask6[(UINT16_MAX + 1) / NBBY];
        uint8_t nomask6[(UINT16_MAX + 1) / NBBY];
+       uint8_t rejectmask6[(UINT16_MAX + 1) / NBBY];
        uint8_t dstmask[256 / NBBY];
        uint32_t leasetime;
        time_t timeout;