version 1.1.1.4, 2021/03/17 00:56:46
|
version 1.1.1.5, 2023/09/27 11:02:07
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2021 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 22
|
Line 22
|
|
|
struct iface_param { |
struct iface_param { |
struct dhcp_context *current; |
struct dhcp_context *current; |
struct dhcp_relay *relay; | struct in6_addr fallback, ll_addr, ula_addr; |
struct in6_addr fallback, relay_local, ll_addr, ula_addr; | |
int ind, addr_match; |
int ind, addr_match; |
}; |
}; |
|
|
Line 90 void dhcp6_init(void)
|
Line 89 void dhcp6_init(void)
|
void dhcp6_packet(time_t now) |
void dhcp6_packet(time_t now) |
{ |
{ |
struct dhcp_context *context; |
struct dhcp_context *context; |
struct dhcp_relay *relay; |
|
struct iface_param parm; |
struct iface_param parm; |
struct cmsghdr *cmptr; |
struct cmsghdr *cmptr; |
struct msghdr msg; |
struct msghdr msg; |
Line 105 void dhcp6_packet(time_t now)
|
Line 103 void dhcp6_packet(time_t now)
|
struct iname *tmp; |
struct iname *tmp; |
unsigned short port; |
unsigned short port; |
struct in6_addr dst_addr; |
struct in6_addr dst_addr; |
| struct in6_addr all_servers; |
| |
memset(&dst_addr, 0, sizeof(dst_addr)); |
memset(&dst_addr, 0, sizeof(dst_addr)); |
|
|
msg.msg_control = control_u.control6; |
msg.msg_control = control_u.control6; |
Line 119 void dhcp6_packet(time_t now)
|
Line 118 void dhcp6_packet(time_t now)
|
if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1) |
if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1) |
return; |
return; |
|
|
|
#ifdef HAVE_DUMPFILE |
|
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz, |
|
(union mysockaddr *)&from, NULL, daemon->dhcp6fd); |
|
#endif |
|
|
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) |
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) |
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) |
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) |
{ |
{ |
Line 135 void dhcp6_packet(time_t now)
|
Line 139 void dhcp6_packet(time_t now)
|
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name)) |
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name)) |
return; |
return; |
|
|
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0) | if (relay_reply6(&from, sz, ifr.ifr_name)) |
{ |
{ |
from.sin6_port = htons(port); | #ifdef HAVE_DUMPFILE |
| dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, |
| (union mysockaddr *)&from, daemon->dhcp6fd); |
| #endif |
| |
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, |
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, |
save_counter(-1), 0, (struct sockaddr *)&from, |
save_counter(-1), 0, (struct sockaddr *)&from, |
sizeof(from)))); |
sizeof(from)))); |
Line 145 void dhcp6_packet(time_t now)
|
Line 153 void dhcp6_packet(time_t now)
|
else |
else |
{ |
{ |
struct dhcp_bridge *bridge, *alias; |
struct dhcp_bridge *bridge, *alias; |
| |
for (tmp = daemon->if_except; tmp; tmp = tmp->next) |
for (tmp = daemon->if_except; tmp; tmp = tmp->next) |
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name)) |
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name)) |
return; |
return; |
Line 155 void dhcp6_packet(time_t now)
|
Line 163 void dhcp6_packet(time_t now)
|
return; |
return; |
|
|
parm.current = NULL; |
parm.current = NULL; |
parm.relay = NULL; |
|
memset(&parm.relay_local, 0, IN6ADDRSZ); |
|
parm.ind = if_index; |
parm.ind = if_index; |
parm.addr_match = 0; |
parm.addr_match = 0; |
memset(&parm.fallback, 0, IN6ADDRSZ); |
memset(&parm.fallback, 0, IN6ADDRSZ); |
memset(&parm.ll_addr, 0, IN6ADDRSZ); |
memset(&parm.ll_addr, 0, IN6ADDRSZ); |
memset(&parm.ula_addr, 0, IN6ADDRSZ); |
memset(&parm.ula_addr, 0, IN6ADDRSZ); |
| |
/* If the interface on which the DHCPv6 request was received is |
/* If the interface on which the DHCPv6 request was received is |
an alias of some other interface (as specified by the |
an alias of some other interface (as specified by the |
--bridge-interface option), change parm.ind so that we look |
--bridge-interface option), change parm.ind so that we look |
Line 200 void dhcp6_packet(time_t now)
|
Line 206 void dhcp6_packet(time_t now)
|
context->current = context; |
context->current = context; |
memset(&context->local6, 0, IN6ADDRSZ); |
memset(&context->local6, 0, IN6ADDRSZ); |
} |
} |
|
|
for (relay = daemon->relay6; relay; relay = relay->next) |
|
relay->current = relay; |
|
|
|
|
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when |
|
we're listening there for DHCPv6 server reasons. */ |
|
inet_pton(AF_INET6, ALL_SERVERS, &all_servers); |
|
|
|
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) && |
|
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now)) |
|
return; |
|
|
if (!iface_enumerate(AF_INET6, &parm, complete_context6)) |
if (!iface_enumerate(AF_INET6, &parm, complete_context6)) |
return; |
return; |
| |
| /* Check for a relay again after iface_enumerate/complete_context has had |
| chance to fill in relay->iface_index fields. This handles first time through |
| and any changes in interface config. */ |
| if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) && |
| relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now)) |
| return; |
| |
if (daemon->if_names || daemon->if_addrs) |
if (daemon->if_names || daemon->if_addrs) |
{ |
{ |
|
|
Line 218 void dhcp6_packet(time_t now)
|
Line 236 void dhcp6_packet(time_t now)
|
return; |
return; |
} |
} |
|
|
if (parm.relay) |
|
{ |
|
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when |
|
we're listening there for DHCPv6 server reasons. */ |
|
struct in6_addr all_servers; |
|
|
|
inet_pton(AF_INET6, ALL_SERVERS, &all_servers); |
|
|
|
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers)) |
|
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now); |
|
return; |
|
} |
|
|
|
/* May have configured relay, but not DHCP server */ |
/* May have configured relay, but not DHCP server */ |
if (!daemon->doing_dhcp6) |
if (!daemon->doing_dhcp6) |
return; |
return; |
| |
lease_prune(NULL, now); /* lose any expired leases */ |
lease_prune(NULL, now); /* lose any expired leases */ |
|
|
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback, |
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback, |
Line 247 void dhcp6_packet(time_t now)
|
Line 252 void dhcp6_packet(time_t now)
|
if (port != 0) |
if (port != 0) |
{ |
{ |
from.sin6_port = htons(port); |
from.sin6_port = htons(port); |
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, | |
save_counter(-1), 0, (struct sockaddr *)&from, | #ifdef HAVE_DUMPFILE |
sizeof(from)))); | dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), |
| NULL, (union mysockaddr *)&from, daemon->dhcp6fd); |
| #endif |
| |
| while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, |
| save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from)))); |
} |
} |
| |
/* These need to be called _after_ we send DHCPv6 packet, since lease_update_file() |
/* These need to be called _after_ we send DHCPv6 packet, since lease_update_file() |
may trigger sending an RA packet, which overwrites our buffer. */ |
may trigger sending an RA packet, which overwrites our buffer. */ |
lease_update_file(now); |
lease_update_file(now); |
Line 292 void get_client_mac(struct in6_addr *client, int iface
|
Line 302 void get_client_mac(struct in6_addr *client, int iface
|
if ((maclen = find_mac(&addr, mac, 0, now)) != 0) |
if ((maclen = find_mac(&addr, mac, 0, now)) != 0) |
break; |
break; |
|
|
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr)); | while(retry_send(sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr)))); |
|
|
ts.tv_sec = 0; |
ts.tv_sec = 0; |
ts.tv_nsec = 100000000; /* 100ms */ |
ts.tv_nsec = 100000000; /* 100ms */ |
Line 312 static int complete_context6(struct in6_addr *local,
|
Line 322 static int complete_context6(struct in6_addr *local,
|
struct dhcp_relay *relay; |
struct dhcp_relay *relay; |
struct iface_param *param = vparam; |
struct iface_param *param = vparam; |
struct iname *tmp; |
struct iname *tmp; |
|
int match = !daemon->if_addrs; |
|
|
(void)scope; /* warning */ |
(void)scope; /* warning */ |
|
|
Line 333 static int complete_context6(struct in6_addr *local,
|
Line 344 static int complete_context6(struct in6_addr *local,
|
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) |
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) |
if (tmp->addr.sa.sa_family == AF_INET6 && |
if (tmp->addr.sa.sa_family == AF_INET6 && |
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local)) |
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local)) |
param->addr_match = 1; | match = param->addr_match = 1; |
|
|
/* Determine a globally address on the arrival interface, even |
/* Determine a globally address on the arrival interface, even |
if we have no matching dhcp-context, because we're only |
if we have no matching dhcp-context, because we're only |
Line 405 static int complete_context6(struct in6_addr *local,
|
Line 416 static int complete_context6(struct in6_addr *local,
|
} |
} |
} |
} |
} |
} |
| |
for (relay = daemon->relay6; relay; relay = relay->next) | if (match) |
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay && | for (relay = daemon->relay6; relay; relay = relay->next) |
(IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local))) | if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6)) |
{ | relay->iface_index = if_index; |
relay->current = param->relay; | |
param->relay = relay; | |
param->relay_local = *local; | |
} | |
| |
return 1; |
return 1; |
} |
} |
|
|
Line 825 void dhcp_construct_contexts(time_t now)
|
Line 832 void dhcp_construct_contexts(time_t now)
|
} |
} |
} |
} |
|
|
#endif | #endif /* HAVE_DHCP6 */ |
| |
| |