struct in_addr server;
int r;
+ r = get_option_addr(&server.s_addr, dhcp, DHCP_SERVERID);
if (strcmp(msg, "NAK:") == 0)
addr = get_option_string(dhcp, DHCP_MESSAGE);
else {
server.s_addr = dhcp->yiaddr;
addr = xstrdup(inet_ntoa(server));
}
- r = get_option_addr(&server.s_addr, dhcp, DHCP_SERVERID);
if (dhcp->servername[0] && r == 0)
logger(lvl, "%s %s from %s `%s'", msg,
addr, inet_ntoa(server),
struct interface *iface = state->interface;
struct dhcp_lease *lease = &state->lease;
uint8_t type;
+ struct in_addr server;
+ size_t i;
+
+ /* reset the message counter */
+ state->messages = 0;
+ /* We have to have DHCP type to work */
if (get_option_uint8(&type, dhcp, DHCP_MESSAGETYPE) == -1) {
log_dhcp(LOG_ERR, "no DHCP type in", dhcp);
- return -1;
+ return 0;
}
- /* reset the message counter */
- state->messages = 0;
+ /* Ensure that it's not from a blacklisted server.
+ * We should expand this to check IP and/or hardware address
+ * at the packet level. */
+ if (options->blacklist_len != 0 &&
+ get_option_addr(&server.s_addr, dhcp, DHCP_SERVERID) == 0)
+ {
+ for (i = 0; i < options->blacklist_len; i++) {
+ if (options->blacklist[i] != server.s_addr)
+ continue;
+ if (dhcp->servername[0])
+ logger(LOG_WARNING,
+ "ignoring blacklisted server %s `%s'",
+ inet_ntoa(server), dhcp->servername);
+ else
+ logger(LOG_WARNING,
+ "ignoring blacklisted server %s",
+ inet_ntoa(server));
+ return 0;
+ }
+ }
/* We should restart on a NAK */
if (type == DHCP_NAK) {
.Op Fl F , -fqdn Ar FQDN
.Op Fl I , -clientid Ar clientid
.Op Fl O , -nooption Ar option
+.Op Fl X , -blacklist Ar address
.Ar interface
.Nm
.Fl k , -release
.It Fl V, -variables
Display a list of option codes and the associated variable for use in
.Xr dhcpcd-run-hooks 8 .
+.It Fl X, -blacklist Ar address
+Ignores all DHCP messages which have this
+.Ar address
+as the server ID.
+This may be expanded in future releases to ignore all packets
+matching either the IP or hardware
+.Ar address .
.El
.Sh NOTES
.Nm
/* 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:TV"
+#define OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xABC:DEF:GI:KLO:TVX:"
static int doversion = 0;
static int dohelp = 0;
{"nooption", optional_argument, NULL, 'O'},
{"test", no_argument, NULL, 'T'},
{"variables", no_argument, NULL, 'V'},
+ {"blacklist", required_argument, NULL, 'X'},
{"help", no_argument, &dohelp, 1},
{"version", no_argument, &doversion, 1},
#ifdef THERE_IS_NO_FORK
static void
usage(void)
{
-#ifndef MINIMAL
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] <interface>\n");
-#endif
+ " [-I clientID] [-C hookscript] [-X ipaddr] <interface>\n");
}
static char *
return -1;
}
break;
+ case 'X':
+ if (!inet_aton(oarg, &addr)) {
+ logger(LOG_ERR, "`%s' is not a valid IP address",
+ oarg);
+ return -1;
+ }
+ options->blacklist = xrealloc(options->blacklist,
+ sizeof(in_addr_t) * (options->blacklist_len + 1));
+ options->blacklist[options->blacklist_len] = addr.s_addr;
+ options->blacklist_len++;
+ break;
default:
return 0;
}
free(options->environ[len++]);
free(options->environ);
}
+ free(options->blacklist);
free(options);
#ifdef THERE_IS_NO_FORK
char clientid[CLIENTID_MAX_LEN + 1];
uint8_t userclass[USERCLASS_MAX_LEN + 1];
uint8_t vendor[VENDOR_MAX_LEN + 1];
+
+ size_t blacklist_len;
+ in_addr_t *blacklist;
};
#endif