The require directive now requires that the required options are present in each DHCP message. A few variables and functions have also been renamed to make this part more readable.

This commit is contained in:
Roy Marples 2008-08-18 12:43:05 +00:00
parent bac03ede3d
commit cc45fbd76e
7 changed files with 72 additions and 38 deletions

View File

@ -1357,7 +1357,7 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp,
struct dhcp_message *dhcp = *dhcpp;
struct interface *iface = state->interface;
struct dhcp_lease *lease = &state->lease;
uint8_t type;
uint8_t type, tmp;
struct in_addr addr;
size_t i;
int r;
@ -1415,6 +1415,16 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp,
/* No NAK, so reset the backoff */
state->nakoff = 1;
/* Ensure that all required options are present */
for (i = 1; i < 255; i++) {
if (has_option_mask(options->requiremask, i) &&
get_option_uint8(&tmp, dhcp, i) != 0)
{
log_dhcp(LOG_WARNING, "reject", dhcp);
return 0;
}
}
if (type == DHCP_OFFER && state->state == STATE_DISCOVERING) {
lease->addr.s_addr = dhcp->yiaddr;
get_option_addr(&lease->server.s_addr, dhcp, DHO_SERVERID);

16
dhcp.c
View File

@ -166,7 +166,7 @@ print_options(void)
printf("%03d %s\n", opt->option, opt->var);
}
int make_reqmask(uint8_t *mask, char **opts, int add)
int make_option_mask(uint8_t *mask, char **opts, int add)
{
char *token, *p = *opts, *t;
const struct dhcp_opt *opt;
@ -190,11 +190,11 @@ int make_reqmask(uint8_t *mask, char **opts, int add)
}
if (match) {
if (add == 1)
add_reqmask(mask,
opt->option);
add_option_mask(mask,
opt->option);
else
del_reqmask(mask,
opt->option);
del_option_mask(mask,
opt->option);
break;
}
}
@ -908,7 +908,7 @@ make_message(struct dhcp_message **message,
*p++ = 0;
for (opt = dhcp_opts; opt->option; opt++) {
if (!(opt->type & REQUEST ||
has_reqmask(options->reqmask, opt->option)))
has_option_mask(options->requestmask, opt->option)))
continue;
switch (opt->option) {
case DHO_RENEWALTIME: /* FALLTHROUGH */
@ -1176,7 +1176,7 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
for (opt = dhcp_opts; opt->option; opt++) {
if (!opt->var)
continue;
if (has_reqmask(options->nomask, opt->option))
if (has_option_mask(options->nomask, opt->option))
continue;
if (get_option_raw(dhcp, opt->option))
e++;
@ -1219,7 +1219,7 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
for (opt = dhcp_opts; opt->option; opt++) {
if (!opt->var)
continue;
if (has_reqmask(options->nomask, opt->option))
if (has_option_mask(options->nomask, opt->option))
continue;
val = NULL;
p = get_option(dhcp, opt->option, &pl, NULL);

8
dhcp.h
View File

@ -154,10 +154,10 @@ struct dhcp_lease {
uint8_t frominfo;
};
#define add_reqmask(var, val) (var[val >> 3] |= 1 << (val & 7))
#define del_reqmask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
#define has_reqmask(var, val) (var[val >> 3] & (1 << (val & 7)))
int make_reqmask(uint8_t *, char **, int);
#define add_option_mask(var, val) (var[val >> 3] |= 1 << (val & 7))
#define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
#define has_option_mask(var, val) (var[val >> 3] & (1 << (val & 7)))
int make_option_mask(uint8_t *, char **, int);
void print_options(void);
char *get_option_string(const struct dhcp_message *, uint8_t);
int get_option_addr(uint32_t *, const struct dhcp_message *, uint8_t);

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd August 13, 2008
.Dd August 18, 2008
.Dt DHCPCD 8 SMM
.Sh NAME
.Nm dhcpcd
@ -46,6 +46,7 @@
.Op Fl F , -fqdn Ar FQDN
.Op Fl I , -clientid Ar clientid
.Op Fl O , -nooption Ar option
.Op Fl Q , -require Ar option
.Op Fl X , -blacklist Ar address
.Ar interface
.Nm
@ -351,6 +352,10 @@ Don't use IPv4LL (aka APIPA, aka Bonjour, aka ZeroConf).
Don't request the specified option.
If no option given, then don't request any options other than those to
configure the interface and routing.
.It Fl Q , -require Ar option
Requires the
.Ar option
to be present in all DHCP messages, otherwise the message is ignored.
.It Fl T, -test
On receipt of OFFER messages just call
.Pa @SCRIPT@

View File

@ -53,7 +53,7 @@ const char copyright[] = "Copyright (c) 2006-2008 Roy Marples";
/* Don't set any optional arguments here so we retain POSIX
* compatibility with getopt */
#define OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xABC:DEF:GI:KLO:TVX:"
#define OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xABC:DEF:GI:KLO:Q:TVX:"
static int doversion = 0;
static int dohelp = 0;
@ -88,6 +88,7 @@ static const struct option longopts[] = {
{"nolink", no_argument, NULL, 'K'},
{"noipv4ll", no_argument, NULL, 'L'},
{"nooption", optional_argument, NULL, 'O'},
{"require", required_argument, NULL, 'Q'},
{"test", no_argument, NULL, 'T'},
{"variables", no_argument, NULL, 'V'},
{"blacklist", required_argument, NULL, 'X'},
@ -154,7 +155,7 @@ usage(void)
printf("usage: "PACKAGE" [-dknpqxADEGHKLOTV] [-c script] [-f file ] [-h hostname]\n"
" [-i classID ] [-l leasetime] [-m metric] [-o option] [-r ipaddr]\n"
" [-s ipaddr] [-t timeout] [-u userclass] [-F none|ptr|both]\n"
" [-I clientID] [-C hookscript] [-X ipaddr] <interface>\n");
" [-I clientID] [-C hookscript] [-Q option] [-X ipaddr] <interface>\n");
}
static char *
@ -361,7 +362,7 @@ parse_option(int opt, char *oarg, struct options *options)
}
break;
case 'o':
if (make_reqmask(options->reqmask, &oarg, 1) != 0) {
if (make_option_mask(options->requestmask, &oarg, 1) != 0) {
logger(LOG_ERR, "unknown option `%s'", oarg);
return -1;
}
@ -531,13 +532,22 @@ parse_option(int opt, char *oarg, struct options *options)
options->options &= ~DHCPCD_IPV4LL;
break;
case 'O':
if (make_reqmask(options->reqmask, &optarg, -1) != 0 ||
make_reqmask(options->nomask, &optarg, 1) != 0)
if (make_option_mask(options->requestmask, &oarg, -1) != 0 ||
make_option_mask(options->requiremask, &oarg, -1) != 0 ||
make_option_mask(options->nomask, &oarg, 1) != 0)
{
logger(LOG_ERR, "unknown option `%s'", optarg);
return -1;
}
break;
case 'Q':
if (make_option_mask(options->requiremask, &oarg, 1) != 0 ||
make_option_mask(options->requestmask, &oarg, 1) != 0)
{
logger(LOG_ERR, "unknown option `%s'", oarg);
return -1;
}
break;
case 'X':
if (!inet_aton(oarg, &addr)) {
logger(LOG_ERR, "`%s' is not a valid IP address",
@ -617,12 +627,12 @@ main(int argc, char **argv)
"%s %s", PACKAGE, VERSION);
#ifdef CMDLINE_COMPAT
add_reqmask(options->reqmask, DHO_DNSSERVER);
add_reqmask(options->reqmask, DHO_DNSDOMAIN);
add_reqmask(options->reqmask, DHO_DNSSEARCH);
add_reqmask(options->reqmask, DHO_NISSERVER);
add_reqmask(options->reqmask, DHO_NISDOMAIN);
add_reqmask(options->reqmask, DHO_NTPSERVER);
add_requestmask(options->requestmask, DHO_DNSSERVER);
add_requestmask(options->reqmask, DHO_DNSDOMAIN);
add_requestmask(options->reqmask, DHO_DNSSEARCH);
add_requestmask(options->reqmask, DHO_NISSERVER);
add_requestmask(options->reqmask, DHO_NISDOMAIN);
add_requestmask(options->reqmask, DHO_NTPSERVER);
/* If the duid file exists, then enable duid by default
* This means we don't break existing clients that easily :) */
@ -771,22 +781,22 @@ main(int argc, char **argv)
#ifdef CMDLINE_COMPAT
case 'H': /* FALLTHROUGH */
case 'M':
del_reqmask(options->reqmask, DHO_MTU);
del_requestmask(options->reqmask, DHO_MTU);
break;
case 'N':
del_reqmask(options->reqmask, DHO_NTPSERVER);
del_requestmask(options->reqmask, DHO_NTPSERVER);
break;
case 'R':
del_reqmask(options->reqmask, DHO_DNSSERVER);
del_reqmask(options->reqmask, DHO_DNSDOMAIN);
del_reqmask(options->reqmask, DHO_DNSSEARCH);
del_requestmask(options->reqmask, DHO_DNSSERVER);
del_requestmask(options->reqmask, DHO_DNSDOMAIN);
del_requestmask(options->reqmask, DHO_DNSSEARCH);
break;
case 'S':
add_reqmask(options->reqmask, DHO_MSCSR);
add_requestmask(options->reqmask, DHO_MSCSR);
break;
case 'Y':
del_reqmask(options->reqmask, DHO_NISSERVER);
del_reqmask(options->reqmask, DHO_NISDOMAIN);
del_requestmask(options->reqmask, DHO_NISSERVER);
del_requestmask(options->reqmask, DHO_NISDOMAIN);
break;
#endif
default:

View File

@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd August 17, 2008
.Dd August 18, 2008
.Dt DHCPCD.CONF 5 SMM
.Sh NAME
.Nm dhcpcd.conf
@ -103,14 +103,22 @@ See
.It Ic nolink
Don't receive link messages about carrier status.
You should only set this for buggy interface drivers.
.It Ic option Ar dhcp-option
.It Ic option Ar option
Requests the
.Ar dhcp-option
.Ar option
from the server.
It can be a variable to be used in
.Xr dhcpcd-run-hooks 8
or the numerical value.
You can specify more seperated by commas, spaces or more option lines.
You can specify more options seperated by commas, spaces or more option lines.
.It Ic require Ar option
Requires the
.Ar option
to be present in all DHCP messages, otherwise the message is ignored.
It can be a variable to be used in
.Xr dhcpcd-run-hooks 8
or the numerical value.
You can specify more options seperated by commas, spaces or more require lines.
.It Ic script Ar script
Use
.Ar script

View File

@ -68,7 +68,8 @@
struct options {
char interface[IF_NAMESIZE];
int metric;
uint8_t reqmask[256 / 8];
uint8_t requestmask[256 / 8];
uint8_t requiremask[256 / 8];
uint8_t nomask[256 / 8];
uint32_t leasetime;
time_t timeout;