version 1.1.1.3, 2016/11/02 09:57:01
|
version 1.1.1.4, 2021/03/17 00:56:46
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2021 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 82 void ra_init(time_t now)
|
Line 82 void ra_init(time_t now)
|
/* ensure this is around even if we're not doing DHCPv6 */ |
/* ensure this is around even if we're not doing DHCPv6 */ |
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet)); |
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet)); |
|
|
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */ | /* See if we're guessing SLAAC addresses, if so we need to receive ping replies */ |
for (context = daemon->dhcp6; context; context = context->next) |
for (context = daemon->dhcp6; context; context = context->next) |
if ((context->flags & CONTEXT_RA_NAME)) |
if ((context->flags & CONTEXT_RA_NAME)) |
break; |
break; |
Line 112 void ra_init(time_t now)
|
Line 112 void ra_init(time_t now)
|
daemon->icmp6fd = fd; |
daemon->icmp6fd = fd; |
|
|
if (daemon->doing_ra) |
if (daemon->doing_ra) |
ra_start_unsolicted(now, NULL); | ra_start_unsolicited(now, NULL); |
} |
} |
|
|
void ra_start_unsolicted(time_t now, struct dhcp_context *context) | void ra_start_unsolicited(time_t now, struct dhcp_context *context) |
{ |
{ |
/* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed |
/* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed |
if it's not appropriate to advertise those contexts. |
if it's not appropriate to advertise those contexts. |
Line 198 void icmp6_packet(time_t now)
|
Line 198 void icmp6_packet(time_t now)
|
/* look for link-layer address option for logging */ |
/* look for link-layer address option for logging */ |
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) |
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) |
{ |
{ |
|
if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) { |
|
return; |
|
} |
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2); |
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2); |
mac = daemon->namebuff; |
mac = daemon->namebuff; |
} |
} |
Line 243 static void send_ra_alias(time_t now, int iface, char
|
Line 246 static void send_ra_alias(time_t now, int iface, char
|
struct dhcp_netid iface_id; |
struct dhcp_netid iface_id; |
struct dhcp_opt *opt_cfg; |
struct dhcp_opt *opt_cfg; |
struct ra_interface *ra_param = find_iface_param(iface_name); |
struct ra_interface *ra_param = find_iface_param(iface_name); |
int done_dns = 0, old_prefix = 0; | int done_dns = 0, old_prefix = 0, mtu = 0; |
unsigned int min_pref_time; |
unsigned int min_pref_time; |
#ifdef HAVE_LINUX_NETWORK |
#ifdef HAVE_LINUX_NETWORK |
FILE *f; |
FILE *f; |
Line 261 static void send_ra_alias(time_t now, int iface, char
|
Line 264 static void send_ra_alias(time_t now, int iface, char
|
parm.adv_interval = calc_interval(ra_param); |
parm.adv_interval = calc_interval(ra_param); |
parm.prio = calc_prio(ra_param); |
parm.prio = calc_prio(ra_param); |
|
|
save_counter(0); | reset_counter(); |
ra = expand(sizeof(struct ra_packet)); | |
|
|
|
if (!(ra = expand(sizeof(struct ra_packet)))) |
|
return; |
|
|
ra->type = ND_ROUTER_ADVERT; |
ra->type = ND_ROUTER_ADVERT; |
ra->code = 0; |
ra->code = 0; |
ra->hop_limit = hop_limit; |
ra->hop_limit = hop_limit; |
Line 283 static void send_ra_alias(time_t now, int iface, char
|
Line 288 static void send_ra_alias(time_t now, int iface, char
|
context->netid.next = &context->netid; |
context->netid.next = &context->netid; |
} |
} |
|
|
if (!iface_enumerate(AF_INET6, &parm, add_prefixes)) | /* If no link-local address then we can't advertise since source address of |
| advertisement must be link local address: RFC 4861 para 6.1.2. */ |
| if (!iface_enumerate(AF_INET6, &parm, add_prefixes) || |
| parm.link_pref_time == 0) |
return; |
return; |
|
|
/* Find smallest preferred time within address classes, |
/* Find smallest preferred time within address classes, |
Line 397 static void send_ra_alias(time_t now, int iface, char
|
Line 405 static void send_ra_alias(time_t now, int iface, char
|
put_opt6_long(1000 * calc_interval(find_iface_param(iface_name))); |
put_opt6_long(1000 * calc_interval(find_iface_param(iface_name))); |
} |
} |
|
|
|
/* Set the MTU from ra_param if any, an MTU of 0 mean automatic for linux, */ |
|
/* an MTU of -1 prevents the option from being sent. */ |
|
if (ra_param) |
|
mtu = ra_param->mtu; |
#ifdef HAVE_LINUX_NETWORK |
#ifdef HAVE_LINUX_NETWORK |
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU | /* Note that IPv6 MTU is not necessarily the same as the IPv4 MTU |
available from SIOCGIFMTU */ |
available from SIOCGIFMTU */ |
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name); | if (mtu == 0) |
if ((f = fopen(daemon->namebuff, "r"))) | |
{ |
{ |
if (fgets(daemon->namebuff, MAXDNAME, f)) | char *mtu_name = ra_param ? ra_param->mtu_name : NULL; |
{ | sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? mtu_name : iface_name); |
put_opt6_char(ICMP6_OPT_MTU); | if ((f = fopen(daemon->namebuff, "r"))) |
put_opt6_char(1); | { |
put_opt6_short(0); | if (fgets(daemon->namebuff, MAXDNAME, f)) |
put_opt6_long(atoi(daemon->namebuff)); | mtu = atoi(daemon->namebuff); |
} | fclose(f); |
fclose(f); | } |
} |
} |
#endif |
#endif |
|
if (mtu > 0) |
|
{ |
|
put_opt6_char(ICMP6_OPT_MTU); |
|
put_opt6_char(1); |
|
put_opt6_short(0); |
|
put_opt6_long(mtu); |
|
} |
|
|
iface_enumerate(AF_LOCAL, &send_iface, add_lla); |
iface_enumerate(AF_LOCAL, &send_iface, add_lla); |
|
|
Line 526 static void send_ra_alias(time_t now, int iface, char
|
Line 544 static void send_ra_alias(time_t now, int iface, char
|
} |
} |
|
|
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, |
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, |
save_counter(0), 0, (struct sockaddr *)&addr, | save_counter(-1), 0, (struct sockaddr *)&addr, |
sizeof(addr)))); |
sizeof(addr)))); |
|
|
} |
} |
Line 608 static int add_prefixes(struct in6_addr *local, int p
|
Line 626 static int add_prefixes(struct in6_addr *local, int p
|
real_prefix = context->prefix; |
real_prefix = context->prefix; |
} |
} |
|
|
/* find floor time, don't reduce below 3 * RA interval. */ | /* find floor time, don't reduce below 3 * RA interval. |
if (time > context->lease_time) | If the lease time has been left as default, don't |
| use that as a floor. */ |
| if ((context->flags & CONTEXT_SETLEASE) && |
| time > context->lease_time) |
{ |
{ |
time = context->lease_time; |
time = context->lease_time; |
if (time < ((unsigned int)(3 * param->adv_interval))) |
if (time < ((unsigned int)(3 * param->adv_interval))) |
Line 778 time_t periodic_ra(time_t now)
|
Line 799 time_t periodic_ra(time_t now)
|
associated with it, because it's for a subnet we dont |
associated with it, because it's for a subnet we dont |
have an interface on. Probably we're doing DHCP on |
have an interface on. Probably we're doing DHCP on |
a remote subnet via a relay. Zero the timer, since we won't |
a remote subnet via a relay. Zero the timer, since we won't |
ever be able to send ra's and satistfy it. */ | ever be able to send ra's and satisfy it. */ |
context->ra_time = 0; |
context->ra_time = 0; |
|
|
if (param.iface != 0 && |
if (param.iface != 0 && |
Line 873 static int iface_search(struct in6_addr *local, int p
|
Line 894 static int iface_search(struct in6_addr *local, int p
|
{ |
{ |
struct search_param *param = vparam; |
struct search_param *param = vparam; |
struct dhcp_context *context; |
struct dhcp_context *context; |
| struct iname *tmp; |
| |
(void)scope; |
(void)scope; |
(void)preferred; |
(void)preferred; |
(void)valid; |
(void)valid; |
| |
| /* ignore interfaces we're not doing DHCP on. */ |
| if (!indextoname(daemon->icmp6fd, if_index, param->name) || |
| !iface_check(AF_LOCAL, NULL, param->name, NULL)) |
| return 1; |
| |
| for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) |
| if (tmp->name && wildcard_match(tmp->name, param->name)) |
| return 1; |
| |
for (context = daemon->dhcp6; context; context = context->next) |
for (context = daemon->dhcp6; context; context = context->next) |
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) && |
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) && |
prefix <= context->prefix && |
prefix <= context->prefix && |
Line 889 static int iface_search(struct in6_addr *local, int p
|
Line 920 static int iface_search(struct in6_addr *local, int p
|
/* found an interface that's overdue for RA determine new |
/* found an interface that's overdue for RA determine new |
timeout value and arrange for RA to be sent unless interface is |
timeout value and arrange for RA to be sent unless interface is |
still doing DAD.*/ |
still doing DAD.*/ |
|
|
if (!(flags & IFACE_TENTATIVE)) |
if (!(flags & IFACE_TENTATIVE)) |
param->iface = if_index; |
param->iface = if_index; |
|
|
/* should never fail */ |
|
if (!indextoname(daemon->icmp6fd, if_index, param->name)) |
|
{ |
|
param->iface = 0; |
|
return 0; |
|
} |
|
|
|
new_timeout(context, param->name, param->now); |
new_timeout(context, param->name, param->now); |
|
|