version 1.1.1.1, 2013/07/29 19:37:40
|
version 1.1.1.5, 2023/09/27 11:02:07
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley |
|
|
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
Line 20
|
Line 20
|
|
|
void dhcp_common_init(void) |
void dhcp_common_init(void) |
{ |
{ |
/* These each hold a DHCP option max size 255 | /* These each hold a DHCP option max size 255 |
and get a terminating zero added */ | and get a terminating zero added */ |
daemon->dhcp_buff = safe_malloc(256); | daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ); |
daemon->dhcp_buff2 = safe_malloc(256); | daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ); |
daemon->dhcp_buff3 = safe_malloc(256); | daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ); |
|
|
/* dhcp_packet is used by v4 and v6, outpacket only by v6 |
/* dhcp_packet is used by v4 and v6, outpacket only by v6 |
sizeof(struct dhcp_packet) is as good an initial size as any, |
sizeof(struct dhcp_packet) is as good an initial size as any, |
Line 38 void dhcp_common_init(void)
|
Line 38 void dhcp_common_init(void)
|
|
|
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg) |
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg) |
{ |
{ |
ssize_t sz; | ssize_t sz, new_sz; |
|
|
while (1) |
while (1) |
{ |
{ |
Line 65 ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
Line 65 ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
} |
} |
} |
} |
|
|
while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR); | while ((new_sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR); |
| |
| /* Some kernels seem to ignore MSG_PEEK, and dequeue the packet anyway. |
| If that happens we get EAGAIN here because the socket is non-blocking. |
| Use the result of the original testing recvmsg as long as the buffer |
| was big enough. There's a small race here that may lose the odd packet, |
| but it's UDP anyway. */ |
|
|
return (msg->msg_flags & MSG_TRUNC) ? -1 : sz; | if (new_sz == -1 && (errno == EWOULDBLOCK || errno == EAGAIN)) |
| new_sz = sz; |
| |
| return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz; |
} |
} |
|
|
|
/* like match_netid() except that the check can have a trailing * for wildcard */ |
|
/* started as a direct copy of match_netid() */ |
|
int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool) |
|
{ |
|
struct dhcp_netid *tmp1; |
|
|
|
for (; check; check = check->next) |
|
{ |
|
const int check_len = strlen(check->net); |
|
const int is_wc = (check_len > 0 && check->net[check_len - 1] == '*'); |
|
|
|
/* '#' for not is for backwards compat. */ |
|
if (check->net[0] != '!' && check->net[0] != '#') |
|
{ |
|
for (tmp1 = pool; tmp1; tmp1 = tmp1->next) |
|
if (is_wc ? (strncmp(check->net, tmp1->net, check_len-1) == 0) : |
|
(strcmp(check->net, tmp1->net) == 0)) |
|
break; |
|
if (!tmp1) |
|
return 0; |
|
} |
|
else |
|
for (tmp1 = pool; tmp1; tmp1 = tmp1->next) |
|
if (is_wc ? (strncmp((check->net)+1, tmp1->net, check_len-2) == 0) : |
|
(strcmp((check->net)+1, tmp1->net) == 0)) |
|
return 0; |
|
} |
|
return 1; |
|
} |
|
|
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags) |
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags) |
{ |
{ |
struct tag_if *exprs; |
struct tag_if *exprs; |
struct dhcp_netid_list *list; |
struct dhcp_netid_list *list; |
|
|
|
/* this now uses match_netid_wild() above so that tag_if can |
|
* be used to set a 'group of interfaces' tag. |
|
*/ |
for (exprs = daemon->tag_if; exprs; exprs = exprs->next) |
for (exprs = daemon->tag_if; exprs; exprs = exprs->next) |
if (match_netid(exprs->tag, tags, 1)) | if (match_netid_wild(exprs->tag, tags)) |
for (list = exprs->set; list; list = list->next) |
for (list = exprs->set; list; list = list->next) |
{ |
{ |
list->list->next = tags; |
list->list->next = tags; |
Line 253 int match_bytes(struct dhcp_opt *o, unsigned char *p,
|
Line 295 int match_bytes(struct dhcp_opt *o, unsigned char *p,
|
return 0; |
return 0; |
} |
} |
|
|
|
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type) |
|
{ |
|
struct hwaddr_config *conf_addr; |
|
|
|
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next) |
|
if (conf_addr->wildcard_mask == 0 && |
|
conf_addr->hwaddr_len == len && |
|
(conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) && |
|
memcmp(conf_addr->hwaddr, hwaddr, len) == 0) |
|
return 1; |
|
|
|
return 0; |
|
} |
|
|
|
static int is_config_in_context(struct dhcp_context *context, struct dhcp_config *config) |
|
{ |
|
if (!context) /* called via find_config() from lease_update_from_configs() */ |
|
return 1; |
|
|
|
if (!(config->flags & (CONFIG_ADDR | CONFIG_ADDR6))) |
|
return 1; |
|
|
|
#ifdef HAVE_DHCP6 |
|
if (context->flags & CONTEXT_V6) |
|
{ |
|
struct addrlist *addr_list; |
|
|
|
if (config->flags & CONFIG_ADDR6) |
|
for (; context; context = context->current) |
|
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next) |
|
{ |
|
if ((addr_list->flags & ADDRLIST_WILDCARD) && context->prefix == 64) |
|
return 1; |
|
|
|
if (is_same_net6(&addr_list->addr.addr6, &context->start6, context->prefix)) |
|
return 1; |
|
} |
|
} |
|
else |
|
#endif |
|
{ |
|
for (; context; context = context->current) |
|
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask)) |
|
return 1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
static struct dhcp_config *find_config_match(struct dhcp_config *configs, |
|
struct dhcp_context *context, |
|
unsigned char *clid, int clid_len, |
|
unsigned char *hwaddr, int hw_len, |
|
int hw_type, char *hostname, |
|
struct dhcp_netid *tags, int tag_not_needed) |
|
{ |
|
int count, new; |
|
struct dhcp_config *config, *candidate; |
|
struct hwaddr_config *conf_addr; |
|
|
|
if (clid) |
|
for (config = configs; config; config = config->next) |
|
if (config->flags & CONFIG_CLID) |
|
{ |
|
if (config->clid_len == clid_len && |
|
memcmp(config->clid, clid, clid_len) == 0 && |
|
is_config_in_context(context, config) && |
|
match_netid(config->filter, tags, tag_not_needed)) |
|
|
|
return config; |
|
|
|
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and |
|
cope with that here. This is IPv4 only. context==NULL implies IPv4, |
|
see lease_update_from_configs() */ |
|
if ((!context || !(context->flags & CONTEXT_V6)) && *clid == 0 && config->clid_len == clid_len-1 && |
|
memcmp(config->clid, clid+1, clid_len-1) == 0 && |
|
is_config_in_context(context, config) && |
|
match_netid(config->filter, tags, tag_not_needed)) |
|
return config; |
|
} |
|
|
|
|
|
if (hwaddr) |
|
for (config = configs; config; config = config->next) |
|
if (config_has_mac(config, hwaddr, hw_len, hw_type) && |
|
is_config_in_context(context, config) && |
|
match_netid(config->filter, tags, tag_not_needed)) |
|
return config; |
|
|
|
if (hostname && context) |
|
for (config = configs; config; config = config->next) |
|
if ((config->flags & CONFIG_NAME) && |
|
hostname_isequal(config->hostname, hostname) && |
|
is_config_in_context(context, config) && |
|
match_netid(config->filter, tags, tag_not_needed)) |
|
return config; |
|
|
|
|
|
if (!hwaddr) |
|
return NULL; |
|
|
|
/* use match with fewest wildcard octets */ |
|
for (candidate = NULL, count = 0, config = configs; config; config = config->next) |
|
if (is_config_in_context(context, config) && |
|
match_netid(config->filter, tags, tag_not_needed)) |
|
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next) |
|
if (conf_addr->wildcard_mask != 0 && |
|
conf_addr->hwaddr_len == hw_len && |
|
(conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) && |
|
(new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count) |
|
{ |
|
count = new; |
|
candidate = config; |
|
} |
|
|
|
return candidate; |
|
} |
|
|
|
/* Find tagged configs first. */ |
|
struct dhcp_config *find_config(struct dhcp_config *configs, |
|
struct dhcp_context *context, |
|
unsigned char *clid, int clid_len, |
|
unsigned char *hwaddr, int hw_len, |
|
int hw_type, char *hostname, struct dhcp_netid *tags) |
|
{ |
|
struct dhcp_config *ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 0); |
|
|
|
if (!ret) |
|
ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 1); |
|
|
|
return ret; |
|
} |
|
|
void dhcp_update_configs(struct dhcp_config *configs) |
void dhcp_update_configs(struct dhcp_config *configs) |
{ |
{ |
/* Some people like to keep all static IP addresses in /etc/hosts. |
/* Some people like to keep all static IP addresses in /etc/hosts. |
Line 267 void dhcp_update_configs(struct dhcp_config *configs)
|
Line 442 void dhcp_update_configs(struct dhcp_config *configs)
|
int prot = AF_INET; |
int prot = AF_INET; |
|
|
for (config = configs; config; config = config->next) |
for (config = configs; config; config = config->next) |
|
{ |
if (config->flags & CONFIG_ADDR_HOSTS) |
if (config->flags & CONFIG_ADDR_HOSTS) |
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR6 | CONFIG_ADDR_HOSTS); | config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS); |
| #ifdef HAVE_DHCP6 |
| if (config->flags & CONFIG_ADDR6_HOSTS) |
| config->flags &= ~(CONFIG_ADDR6 | CONFIG_ADDR6_HOSTS); |
| #endif |
| } |
|
|
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
again: |
again: |
Line 295 void dhcp_update_configs(struct dhcp_config *configs)
|
Line 476 void dhcp_update_configs(struct dhcp_config *configs)
|
if (cache_find_by_name(crec, config->hostname, 0, cacheflags)) |
if (cache_find_by_name(crec, config->hostname, 0, cacheflags)) |
{ |
{ |
/* use primary (first) address */ |
/* use primary (first) address */ |
while (crec && !(crec->flags & F_REVERSE)) | while (crec && !(crec->flags & F_REVERSE)) |
crec = cache_find_by_name(crec, config->hostname, 0, cacheflags); | crec = cache_find_by_name(crec, config->hostname, 0, cacheflags); |
if (!crec) | if (!crec) |
continue; /* should be never */ | continue; /* should be never */ |
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN); | inet_ntop(prot, &crec->addr, daemon->addrbuff, ADDRSTRLEN); |
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"), | my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"), |
config->hostname, daemon->addrbuff); | config->hostname, daemon->addrbuff); |
} |
} |
|
|
if (prot == AF_INET && |
if (prot == AF_INET && |
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config)) | (!(conf_tmp = config_find_by_address(configs, crec->addr.addr4)) || conf_tmp == config)) |
{ |
{ |
config->addr = crec->addr.addr.addr.addr4; | config->addr = crec->addr.addr4; |
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS; |
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS; |
continue; |
continue; |
} |
} |
|
|
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
if (prot == AF_INET6 && |
if (prot == AF_INET6 && |
(!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config)) | (!(conf_tmp = config_find_by_address6(configs, NULL, 0, &crec->addr.addr6)) || conf_tmp == config)) |
{ |
{ |
memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ); | /* host must have exactly one address if comming from /etc/hosts. */ |
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS; | if (!config->addr6 && (config->addr6 = whine_malloc(sizeof(struct addrlist)))) |
| { |
| config->addr6->next = NULL; |
| config->addr6->flags = 0; |
| } |
| |
| if (config->addr6 && !config->addr6->next && !(config->addr6->flags & (ADDRLIST_WILDCARD|ADDRLIST_PREFIX))) |
| { |
| memcpy(&config->addr6->addr.addr6, &crec->addr.addr6, IN6ADDRSZ); |
| config->flags |= CONFIG_ADDR6 | CONFIG_ADDR6_HOSTS; |
| } |
| |
continue; |
continue; |
} |
} |
#endif |
#endif |
|
|
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN); | inet_ntop(prot, &crec->addr, daemon->addrbuff, ADDRSTRLEN); |
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"), |
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"), |
daemon->addrbuff, config->hostname); |
daemon->addrbuff, config->hostname); |
|
|
Line 341 void dhcp_update_configs(struct dhcp_config *configs)
|
Line 533 void dhcp_update_configs(struct dhcp_config *configs)
|
} |
} |
|
|
#ifdef HAVE_LINUX_NETWORK |
#ifdef HAVE_LINUX_NETWORK |
void bindtodevice(int fd) | char *whichdevice(void) |
{ |
{ |
/* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE |
/* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE |
to that device. This is for the use case of (eg) OpenStack, which runs a new |
to that device. This is for the use case of (eg) OpenStack, which runs a new |
dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE, |
dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE, |
individual processes don't always see the packets they should. |
individual processes don't always see the packets they should. |
SO_BINDTODEVICE is only available Linux. */ | SO_BINDTODEVICE is only available Linux. |
| |
| Note that if wildcards are used in --interface, or --interface is not used at all, |
| or a configured interface doesn't yet exist, then more interfaces may arrive later, |
| so we can't safely assert there is only one interface and proceed. |
| */ |
|
|
struct irec *iface, *found; |
struct irec *iface, *found; |
|
struct iname *if_tmp; |
|
|
|
if (!daemon->if_names) |
|
return NULL; |
|
|
|
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next) |
|
if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*'))) |
|
return NULL; |
|
|
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next) |
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next) |
if (iface->dhcp_ok) |
if (iface->dhcp_ok) |
{ |
{ |
if (!found) |
if (!found) |
found = iface; |
found = iface; |
else if (strcmp(found->name, iface->name) != 0) |
else if (strcmp(found->name, iface->name) != 0) |
{ | return NULL; /* more than one. */ |
/* more than one. */ | |
found = NULL; | |
break; | |
} | |
} |
} |
| |
if (found) |
if (found) |
{ |
{ |
struct ifreq ifr; | char *ret = safe_malloc(strlen(found->name)+1); |
strcpy(ifr.ifr_name, found->name); | strcpy(ret, found->name); |
/* only allowed by root. */ | return ret; |
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 && | |
errno != EPERM) | |
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET); | |
} |
} |
|
|
|
return NULL; |
} |
} |
|
|
|
static int bindtodevice(char *device, int fd) |
|
{ |
|
size_t len = strlen(device)+1; |
|
if (len > IFNAMSIZ) |
|
len = IFNAMSIZ; |
|
/* only allowed by root. */ |
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 && |
|
errno != EPERM) |
|
return 2; |
|
|
|
return 1; |
|
} |
|
|
|
int bind_dhcp_devices(char *bound_device) |
|
{ |
|
int ret = 0; |
|
|
|
if (bound_device) |
|
{ |
|
if (daemon->dhcp) |
|
{ |
|
if (!daemon->relay4) |
|
ret |= bindtodevice(bound_device, daemon->dhcpfd); |
|
|
|
if (daemon->enable_pxe && daemon->pxefd != -1) |
|
ret |= bindtodevice(bound_device, daemon->pxefd); |
|
} |
|
|
|
#if defined(HAVE_DHCP6) |
|
if (daemon->doing_dhcp6 && !daemon->relay6) |
|
ret |= bindtodevice(bound_device, daemon->dhcp6fd); |
#endif |
#endif |
|
} |
|
|
|
return ret; |
|
} |
|
#endif |
|
|
static const struct opttab_t { |
static const struct opttab_t { |
char *name; |
char *name; |
Line 426 static const struct opttab_t {
|
Line 663 static const struct opttab_t {
|
{ "parameter-request", 55, OT_INTERNAL }, |
{ "parameter-request", 55, OT_INTERNAL }, |
{ "message", 56, OT_INTERNAL }, |
{ "message", 56, OT_INTERNAL }, |
{ "max-message-size", 57, OT_INTERNAL }, |
{ "max-message-size", 57, OT_INTERNAL }, |
{ "T1", 58, OT_INTERNAL | OT_TIME}, | { "T1", 58, OT_TIME}, |
{ "T2", 59, OT_INTERNAL | OT_TIME}, | { "T2", 59, OT_TIME}, |
{ "vendor-class", 60, 0 }, |
{ "vendor-class", 60, 0 }, |
{ "client-id", 61, OT_INTERNAL }, |
{ "client-id", 61, OT_INTERNAL }, |
{ "nis+-domain", 64, OT_NAME }, |
{ "nis+-domain", 64, OT_NAME }, |
Line 440 static const struct opttab_t {
|
Line 677 static const struct opttab_t {
|
{ "nntp-server", 71, OT_ADDR_LIST }, |
{ "nntp-server", 71, OT_ADDR_LIST }, |
{ "irc-server", 74, OT_ADDR_LIST }, |
{ "irc-server", 74, OT_ADDR_LIST }, |
{ "user-class", 77, 0 }, |
{ "user-class", 77, 0 }, |
|
{ "rapid-commit", 80, 0 }, |
{ "FQDN", 81, OT_INTERNAL }, |
{ "FQDN", 81, OT_INTERNAL }, |
{ "agent-id", 82, OT_INTERNAL }, |
{ "agent-id", 82, OT_INTERNAL }, |
{ "client-arch", 93, 2 | OT_DEC }, |
{ "client-arch", 93, 2 | OT_DEC }, |
{ "client-interface-id", 94, 0 }, |
{ "client-interface-id", 94, 0 }, |
{ "client-machine-id", 97, 0 }, |
{ "client-machine-id", 97, 0 }, |
|
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */ |
|
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */ |
|
{ "ipv6-only", 108, 4 | OT_DEC }, /* RFC 8925 */ |
{ "subnet-select", 118, OT_INTERNAL }, |
{ "subnet-select", 118, OT_INTERNAL }, |
{ "domain-search", 119, OT_RFC1035_NAME }, |
{ "domain-search", 119, OT_RFC1035_NAME }, |
{ "sip-server", 120, 0 }, |
{ "sip-server", 120, 0 }, |
{ "classless-static-route", 121, 0 }, |
{ "classless-static-route", 121, 0 }, |
{ "vendor-id-encap", 125, 0 }, |
{ "vendor-id-encap", 125, 0 }, |
|
{ "tftp-server-address", 150, OT_ADDR_LIST }, |
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */ |
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */ |
{ NULL, 0, 0 } |
{ NULL, 0, 0 } |
}; |
}; |
Line 480 static const struct opttab_t opttab6[] = {
|
Line 722 static const struct opttab_t opttab6[] = {
|
{ "sntp-server", 31, OT_ADDR_LIST }, |
{ "sntp-server", 31, OT_ADDR_LIST }, |
{ "information-refresh-time", 32, OT_TIME }, |
{ "information-refresh-time", 32, OT_TIME }, |
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME }, |
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME }, |
{ "ntp-server", 56, OT_ADDR_LIST }, | { "posix-timezone", 41, OT_NAME }, /* RFC 4833, Sec. 3 */ |
| { "tzdb-timezone", 42, OT_NAME }, /* RFC 4833, Sec. 3 */ |
| { "ntp-server", 56, 0 /* OT_ADDR_LIST | OT_RFC1035_NAME */ }, |
{ "bootfile-url", 59, OT_NAME }, |
{ "bootfile-url", 59, OT_NAME }, |
{ "bootfile-param", 60, OT_CSTRING }, |
{ "bootfile-param", 60, OT_CSTRING }, |
{ NULL, 0, 0 } |
{ NULL, 0, 0 } |
Line 512 void display_opts6(void)
|
Line 756 void display_opts6(void)
|
} |
} |
#endif |
#endif |
|
|
u16 lookup_dhcp_opt(int prot, char *name) | int lookup_dhcp_opt(int prot, char *name) |
{ |
{ |
const struct opttab_t *t; |
const struct opttab_t *t; |
int i; |
int i; |
|
|
|
(void)prot; |
|
|
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
if (prot == AF_INET6) |
if (prot == AF_INET6) |
t = opttab6; |
t = opttab6; |
Line 528 u16 lookup_dhcp_opt(int prot, char *name)
|
Line 774 u16 lookup_dhcp_opt(int prot, char *name)
|
if (strcasecmp(t[i].name, name) == 0) |
if (strcasecmp(t[i].name, name) == 0) |
return t[i].val; |
return t[i].val; |
|
|
return 0; | return -1; |
} |
} |
|
|
u16 lookup_dhcp_len(int prot, u16 val) | int lookup_dhcp_len(int prot, int val) |
{ |
{ |
const struct opttab_t *t; |
const struct opttab_t *t; |
int i; |
int i; |
|
|
|
(void)prot; |
|
|
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
if (prot == AF_INET6) |
if (prot == AF_INET6) |
t = opttab6; |
t = opttab6; |
Line 569 char *option_string(int prot, unsigned int opt, unsign
|
Line 817 char *option_string(int prot, unsigned int opt, unsign
|
|
|
if (ot[o].size & OT_ADDR_LIST) |
if (ot[o].size & OT_ADDR_LIST) |
{ |
{ |
struct all_addr addr; | union all_addr addr; |
int addr_len = INADDRSZ; |
int addr_len = INADDRSZ; |
|
|
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
Line 590 char *option_string(int prot, unsigned int opt, unsign
|
Line 838 char *option_string(int prot, unsigned int opt, unsign
|
for (i = 0, j = 0; i < opt_len && j < buf_len ; i++) |
for (i = 0, j = 0; i < opt_len && j < buf_len ; i++) |
{ |
{ |
char c = val[i]; |
char c = val[i]; |
if (isprint((int)c)) | if (isprint((unsigned char)c)) |
buf[j++] = c; |
buf[j++] = c; |
} |
} |
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
Line 604 char *option_string(int prot, unsigned int opt, unsign
|
Line 852 char *option_string(int prot, unsigned int opt, unsign
|
for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++) |
for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++) |
{ |
{ |
char c = val[k]; |
char c = val[k]; |
if (isprint((int)c)) | if (isprint((unsigned char)c)) |
buf[j++] = c; |
buf[j++] = c; |
} |
} |
i = l; |
i = l; |
Line 625 char *option_string(int prot, unsigned int opt, unsign
|
Line 873 char *option_string(int prot, unsigned int opt, unsign
|
for (k = 0; k < len && j < buf_len; k++) |
for (k = 0; k < len && j < buf_len; k++) |
{ |
{ |
char c = *p++; |
char c = *p++; |
if (isprint((int)c)) | if (isprint((unsigned char)c)) |
buf[j++] = c; |
buf[j++] = c; |
} |
} |
i += len +2; |
i += len +2; |
Line 713 void log_context(int family, struct dhcp_context *cont
|
Line 961 void log_context(int family, struct dhcp_context *cont
|
template = p; |
template = p; |
p += sprintf(p, ", "); |
p += sprintf(p, ", "); |
|
|
if (indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, context->if_index, ifrn_name)) | if (indextoname(daemon->icmp6fd, context->if_index, ifrn_name)) |
sprintf(p, "constructed for %s", ifrn_name); | sprintf(p, "%s for %s", (context->flags & CONTEXT_OLD) ? "old prefix" : "constructed", ifrn_name); |
} |
} |
else if (context->flags & CONTEXT_TEMPLATE) | else if (context->flags & CONTEXT_TEMPLATE && !(context->flags & CONTEXT_RA_STATELESS)) |
{ |
{ |
template = p; |
template = p; |
p += sprintf(p, ", "); |
p += sprintf(p, ", "); |
| |
sprintf(p, "template for %s", context->template_interface); |
sprintf(p, "template for %s", context->template_interface); |
} |
} |
#endif |
#endif |
|
|
if ((context->flags & CONTEXT_DHCP) || family == AF_INET) | if (!(context->flags & CONTEXT_OLD) && |
| ((context->flags & CONTEXT_DHCP) || family == AF_INET)) |
{ |
{ |
inet_ntop(family, start, daemon->dhcp_buff, 256); | #ifdef HAVE_DHCP6 |
inet_ntop(family, end, daemon->dhcp_buff3, 256); | if (context->flags & CONTEXT_RA_STATELESS) |
| { |
| if (context->flags & CONTEXT_TEMPLATE) |
| strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ); |
| else |
| strcpy(daemon->dhcp_buff, daemon->addrbuff); |
| } |
| else |
| #endif |
| inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ); |
| inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ); |
my_syslog(MS_DHCP | LOG_INFO, |
my_syslog(MS_DHCP | LOG_INFO, |
(context->flags & CONTEXT_RA_STATELESS) ? | (context->flags & CONTEXT_RA_STATELESS) ? |
_("%s stateless on %s%.0s%.0s%s") : | _("%s stateless on %s%.0s%.0s%s") : |
(context->flags & CONTEXT_STATIC) ? | (context->flags & CONTEXT_STATIC) ? |
_("%s, static leases only on %.0s%s%s%.0s") : | _("%s, static leases only on %.0s%s%s%.0s") : |
(context->flags & CONTEXT_PROXY) ? | (context->flags & CONTEXT_PROXY) ? |
_("%s, proxy on subnet %.0s%s%.0s%.0s") : | _("%s, proxy on subnet %.0s%s%.0s%.0s") : |
_("%s, IP range %s -- %s%s%.0s"), | _("%s, IP range %s -- %s%s%.0s"), |
(family != AF_INET) ? "DHCPv6" : "DHCP", | (family != AF_INET) ? "DHCPv6" : "DHCP", |
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff, template); |
daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff, template); |
} |
} |
|
|
#ifdef HAVE_DHCP6 |
#ifdef HAVE_DHCP6 |
if (context->flags & CONTEXT_RA_NAME) | if (context->flags & CONTEXT_TEMPLATE) |
| { |
| strcpy(daemon->addrbuff, context->template_interface); |
| template = ""; |
| } |
| |
| if ((context->flags & CONTEXT_RA_NAME) && !(context->flags & CONTEXT_OLD)) |
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"), daemon->addrbuff, template); |
my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"), daemon->addrbuff, template); |
| |
if ((context->flags & CONTEXT_RA) || (option_bool(OPT_RA) && (context->flags & CONTEXT_DHCP) && family == AF_INET6)) |
if ((context->flags & CONTEXT_RA) || (option_bool(OPT_RA) && (context->flags & CONTEXT_DHCP) && family == AF_INET6)) |
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s"), daemon->addrbuff, template); |
my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s"), daemon->addrbuff, template); |
#endif |
#endif |
|
|
} |
} |
|
|
|
|
|
void log_relay(int family, struct dhcp_relay *relay) |
|
{ |
|
int broadcast = relay->server.addr4.s_addr == 0; |
|
inet_ntop(family, &relay->local, daemon->addrbuff, ADDRSTRLEN); |
|
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN); |
|
|
|
if (family == AF_INET && relay->port != DHCP_SERVER_PORT) |
|
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port); |
|
|
|
#ifdef HAVE_DHCP6 |
|
struct in6_addr multicast; |
|
|
|
inet_pton(AF_INET6, ALL_SERVERS, &multicast); |
|
|
|
if (family == AF_INET6) |
|
{ |
|
broadcast = IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast); |
|
if (relay->port != DHCPV6_SERVER_PORT) |
|
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port); |
|
} |
|
#endif |
|
|
|
|
|
if (relay->interface) |
|
{ |
|
if (broadcast) |
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s via %s"), daemon->addrbuff, relay->interface); |
|
else |
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface); |
|
} |
|
else |
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s"), daemon->addrbuff, daemon->namebuff); |
|
} |
|
|
#endif |
#endif |