From: Roy Marples Date: Mon, 28 Jul 2008 13:21:47 +0000 (+0000) Subject: Add -X, --blacklist option to reject DHCP messages with a matching serverid. X-Git-Tag: v4.0.2~119 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eceefd55549c60544e0303f1fb5101bbb4f6d17e;p=thirdparty%2Fdhcpcd.git Add -X, --blacklist option to reject DHCP messages with a matching serverid. --- diff --git a/client.c b/client.c index f8dbd31c..79a494e5 100644 --- a/client.c +++ b/client.c @@ -1330,13 +1330,13 @@ log_dhcp(int lvl, const char *msg, const struct dhcp_message *dhcp) 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), @@ -1356,14 +1356,38 @@ handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp, 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) { diff --git a/dhcpcd.8.in b/dhcpcd.8.in index 33287040..dcf84483 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -46,6 +46,7 @@ .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 @@ -354,6 +355,13 @@ files. .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 diff --git a/dhcpcd.c b/dhcpcd.c index 46e39a37..3857b7c5 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -52,7 +52,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: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; @@ -89,6 +89,7 @@ static const struct option longopts[] = { {"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 @@ -160,12 +161,10 @@ read_pid(const char *pidfile) 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] \n"); -#endif + " [-I clientID] [-C hookscript] [-X ipaddr] \n"); } static char * @@ -561,6 +560,17 @@ parse_option(int opt, char *oarg, struct options *options) 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; } @@ -983,6 +993,7 @@ abort: free(options->environ[len++]); free(options->environ); } + free(options->blacklist); free(options); #ifdef THERE_IS_NO_FORK diff --git a/dhcpcd.h b/dhcpcd.h index b06f5da1..c9a42e1c 100644 --- a/dhcpcd.h +++ b/dhcpcd.h @@ -93,5 +93,8 @@ struct options { 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