Add --dhcp-name-match

This commit is contained in:
Simon Kelley
2018-08-08 23:46:03 +01:00
parent 397c0502e2
commit c822620967
5 changed files with 77 additions and 4 deletions

View File

@@ -49,6 +49,8 @@ version 2.80
DNS configuration which confused systemd-resolvd. Thanks to DNS configuration which confused systemd-resolvd. Thanks to
Steve Dodd for characterising the problem. Steve Dodd for characterising the problem.
Add --dhcp-name-match config option.
version 2.79 version 2.79
Fix parsing of CNAME arguments, which are confused by extra spaces. Fix parsing of CNAME arguments, which are confused by extra spaces.

View File

@@ -1329,6 +1329,9 @@ The special form with vi-encap:<enterprise number> matches against
vendor-identifying vendor classes for the specified enterprise. Please vendor-identifying vendor classes for the specified enterprise. Please
see RFC 3925 for more details of these rare and interesting beasts. see RFC 3925 for more details of these rare and interesting beasts.
.TP .TP
.B --dhcp-name-match=set:<tag>,<name>[*]
Set the tag if the given name is supplied by a dhcp client. There may be a single trailing wildcard *, which has the usual meaning. Combined with dhcp-ignore or dhcp-ignore-names this gives the ability to ignore certain clients by name, or disallow certain hostnames from being claimed by a client.
.TP
.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]] .B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
Perform boolean operations on tags. Any tag appearing as set:<tag> is set if Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used) all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)

View File

@@ -822,6 +822,13 @@ struct dhcp_boot {
struct dhcp_boot *next; struct dhcp_boot *next;
}; };
struct dhcp_match_name {
char *name;
int wildcard;
struct dhcp_netid *netid;
struct dhcp_match_name *next;
};
struct pxe_service { struct pxe_service {
unsigned short CSA, type; unsigned short CSA, type;
char *menu, *basename, *sname; char *menu, *basename, *sname;
@@ -1014,6 +1021,7 @@ extern struct daemon {
struct ra_interface *ra_interfaces; struct ra_interface *ra_interfaces;
struct dhcp_config *dhcp_conf; struct dhcp_config *dhcp_conf;
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6; struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
struct dhcp_match_name *dhcp_name_match;
struct dhcp_vendor *dhcp_vendors; struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs; struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config; struct dhcp_boot *boot_config;

View File

@@ -164,6 +164,7 @@ struct myoption {
#define LOPT_DUMPFILE 352 #define LOPT_DUMPFILE 352
#define LOPT_DUMPMASK 353 #define LOPT_DUMPMASK 353
#define LOPT_UBUS 354 #define LOPT_UBUS 354
#define LOPT_NAME_MATCH 355
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -274,6 +275,7 @@ static const struct myoption opts[] =
{ "rebind-domain-ok", 1, 0, LOPT_NO_REBIND }, { "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
{ "all-servers", 0, 0, LOPT_NOLAST }, { "all-servers", 0, 0, LOPT_NOLAST },
{ "dhcp-match", 1, 0, LOPT_MATCH }, { "dhcp-match", 1, 0, LOPT_MATCH },
{ "dhcp-name-match", 1, 0, LOPT_NAME_MATCH },
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST }, { "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
{ "neg-ttl", 1, 0, LOPT_NEGTTL }, { "neg-ttl", 1, 0, LOPT_NEGTTL },
{ "max-ttl", 1, 0, LOPT_MAXTTL }, { "max-ttl", 1, 0, LOPT_MAXTTL },
@@ -456,6 +458,7 @@ static struct {
{ LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL }, { LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL }, { LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
{ LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL }, { LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
{ LOPT_NAME_MATCH, ARG_DUP, "set:<tag>,<string>[*]", gettext_noop("Set tag if client provides given name."), NULL },
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL }, { LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL }, { LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL }, { LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
@@ -3287,6 +3290,32 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
(option == LOPT_MATCH ? DHOPT_MATCH : (option == LOPT_MATCH ? DHOPT_MATCH :
(option == LOPT_OPTS ? DHOPT_BANK : 0))); (option == LOPT_OPTS ? DHOPT_BANK : 0)));
case LOPT_NAME_MATCH: /* --dhcp-name-match */
{
struct dhcp_match_name *new = opt_malloc(sizeof(struct dhcp_match_name));
struct dhcp_netid *id = opt_malloc(sizeof(struct dhcp_netid));
ssize_t len;
if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
ret_err(gen_err);
new->wildcard = 0;
new->netid = id;
id->net = opt_string_alloc(set_prefix(arg));
if (comma[len-1] == '*')
{
comma[len-1] = 0;
new->wildcard = 1;
}
new->name = opt_string_alloc(comma);
new->next = daemon->dhcp_name_match;
daemon->dhcp_name_match = new;
break;
}
case 'M': /* --dhcp-boot */ case 'M': /* --dhcp-boot */
{ {
struct dhcp_netid *id = NULL; struct dhcp_netid *id = NULL;

View File

@@ -700,9 +700,40 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
client_hostname = daemon->dhcp_buff; client_hostname = daemon->dhcp_buff;
} }
if (client_hostname && option_bool(OPT_LOG_OPTS)) if (client_hostname)
{
struct dhcp_match_name *m;
size_t nl = strlen(client_hostname);
if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname); my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
for (m = daemon->dhcp_name_match; m; m = m->next)
{
size_t ml = strlen(m->name);
char save = 0;
if (nl < ml)
continue;
if (nl > ml)
{
save = client_hostname[ml];
client_hostname[ml] = 0;
}
if (hostname_isequal(client_hostname, m->name) &&
(save == 0 || m->wildcard))
{
m->netid->next = netid;
netid = m->netid;
}
if (save != 0)
client_hostname[ml] = save;
}
}
if (have_config(config, CONFIG_NAME)) if (have_config(config, CONFIG_NAME))
{ {
hostname = config->hostname; hostname = config->hostname;