Compare commits

...
11 Commits
23 changed files with 5255 additions and 4692 deletions

No files matched your search

+5
View File
@@ -119,6 +119,11 @@ version 2.67
6939 for this to work. It always works for directly
connected clients. Thanks to Vladislav Grishenko
for prompting this feature.
Remove the rule for constructed DHCP ranges that the local
address must be either the first or last address in the
range. This was originally to avoid SLAAC addresses, but
we now explicitly autoconfig and privacy addresses instead.
version 2.66
+36
View File
@@ -0,0 +1,36 @@
#!/bin/bash
STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
# Script for dnsmasq lease-change hook.
# Maintains the above file with a IP address/MAC address pairs,
# one lease per line. Works with IPv4 and IPv6 leases, file is
# atomically updated, so no races for users of the data.
action="$1"
mac="$2" # IPv4
ip="$3"
# ensure it always exists.
if [ ! -f "$STATUS_FILE" ]; then
touch "$STATUS_FILE"
fi
if [ -n "$DNSMASQ_IAID" ]; then
mac="$DNSMASQ_MAC" # IPv6
fi
# worry about an add or old action when the MAC address is not known:
# leave any old one in place in that case.
if [ "$action" = "add" -o "$action" = "old" -o "$action" = "del" ]; then
if [ -n "$mac" -o "$action" = "del" ]; then
sed "/^${ip//./\.} / d" "$STATUS_FILE" > "$STATUS_FILE".new
if [ "$action" = "add" -o "$action" = "old" ]; then
echo "$ip $mac" >> "$STATUS_FILE".new
fi
mv "$STATUS_FILE".new "$STATUS_FILE" # atomic update.
fi
fi
+3 -7
View File
@@ -652,24 +652,20 @@ This forms a template which describes how to create ranges, based on the address
.B --dhcp-range=::1,::400,constructor:eth0
will look for addresses of the form <network>::1 or <network>:400 on
will look for addresses on
eth0 and then create a range from <network>::1 to <network>::400. If
the interface is assigned more than one network, then the
corresponding ranges will be automatically created, and then
deprecated and finally removed again as the address is deprecated and
then deleted. The interface name may have a final "*" wildcard. Note
that just any address on eth0 will not do: the non-prefix part must be
equal either the start or end address given in the dhcp-range. This is
to prevent prefixes becoming perpetual if the interface
gains a SLAAC address for the prefix when it is advertised by dnsmasq.
that just any address on eth0 will not do: it must not be an
autoconfigured or privacy address, or be deprecated.
If a dhcp-range is only being used for stateless DHCP and/or SLAAC,
then the address can be simply ::
.B --dhcp-range=::,constructor:eth0
This removes the condition above, and will pick up the prefix from any address on eth0 which is NOT
autoconfigured, slaac, temporary or deprecated.
There is a variant of the constructor: syntax using the keyword
.B constructor-noauth.
+465 -413
View File
File diff suppressed because it is too large. Load diff
+460 -410
View File
File diff suppressed because it is too large. Load diff
+516 -467
View File
File diff suppressed because it is too large. Load diff
+464 -410
View File
File diff suppressed because it is too large. Load diff
+490 -441
View File
File diff suppressed because it is too large. Load diff
+516 -467
View File
File diff suppressed because it is too large. Load diff
+479 -432
View File
File diff suppressed because it is too large. Load diff
+464 -410
View File
File diff suppressed because it is too large. Load diff
+516 -467
View File
File diff suppressed because it is too large. Load diff
+479 -432
View File
File diff suppressed because it is too large. Load diff
+5 -1
View File
@@ -627,6 +627,8 @@ int lookup_dhcp_opt(int prot, char *name)
const struct opttab_t *t;
int i;
(void)prot;
#ifdef HAVE_DHCP6
if (prot == AF_INET6)
t = opttab6;
@@ -646,6 +648,8 @@ int lookup_dhcp_len(int prot, int val)
const struct opttab_t *t;
int i;
(void)prot;
#ifdef HAVE_DHCP6
if (prot == AF_INET6)
t = opttab6;
@@ -823,7 +827,7 @@ void log_context(int family, struct dhcp_context *context)
template = 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, "%s for %s", (context->flags & CONTEXT_OLD) ? "old prefix" : "constructed", ifrn_name);
}
else if (context->flags & CONTEXT_TEMPLATE)
+61 -56
View File
@@ -29,7 +29,7 @@ struct iface_param {
struct mac_param {
struct in6_addr *target;
unsigned char mac[DHCP_CHADDR_MAX];
unsigned char *mac;
unsigned int maclen;
};
@@ -99,7 +99,6 @@ void dhcp6_packet(time_t now)
struct dhcp_context *context;
struct dhcp_relay *relay;
struct iface_param parm;
struct mac_param mac_param;
struct cmsghdr *cmptr;
struct msghdr msg;
int if_index = 0;
@@ -145,8 +144,6 @@ void dhcp6_packet(time_t now)
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
{
int i;
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
return;
@@ -182,48 +179,6 @@ void dhcp6_packet(time_t now)
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
return;
/* Recieving a packet from a host does not populate the neighbour
cache, so we send a neighbour discovery request if we can't
find the sender. Repeat a few times in case of packet loss. */
for (i = 0; i < 5; i++)
{
struct timespec ts;
struct neigh_packet *neigh;
struct sockaddr_in6 addr;
mac_param.target = &from.sin6_addr;
mac_param.maclen = 0;
iface_enumerate(AF_UNSPEC, &mac_param, find_mac);
if (mac_param.maclen != 0)
break;
save_counter(0);
neigh = expand(sizeof(struct neigh_packet));
neigh->type = ND_NEIGHBOR_SOLICIT;
neigh->code = 0;
neigh->reserved = 0;
neigh->target = from.sin6_addr;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.sin6_len = sizeof(struct sockaddr_in6);
#endif
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = from.sin6_addr;
addr.sin6_scope_id = from.sin6_scope_id;
sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
(struct sockaddr *)&addr, sizeof(addr));
ts.tv_sec = 0;
ts.tv_nsec = 100000000; /* 100ms */
nanosleep(&ts, NULL);
}
if (daemon->if_names || daemon->if_addrs)
{
@@ -244,8 +199,7 @@ void dhcp6_packet(time_t now)
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,
mac_param.maclen == 0 ? NULL : &mac_param.mac[0], mac_param.maclen, ARPHRD_ETHER);
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id);
return;
}
@@ -256,8 +210,7 @@ void dhcp6_packet(time_t now)
lease_prune(NULL, now); /* lose any expired leases */
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
sz, IN6_IS_ADDR_MULTICAST(&from.sin6_addr), now,
mac_param.maclen == 0 ? NULL : &mac_param.mac[0], mac_param.maclen, ARPHRD_ETHER);
sz, &from.sin6_addr, now);
lease_update_file(now);
lease_update_dns(0);
@@ -276,6 +229,55 @@ void dhcp6_packet(time_t now)
}
}
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep)
{
/* Recieving a packet from a host does not populate the neighbour
cache, so we send a neighbour discovery request if we can't
find the sender. Repeat a few times in case of packet loss. */
struct neigh_packet neigh;
struct sockaddr_in6 addr;
struct mac_param mac_param;
int i;
neigh.type = ND_NEIGHBOR_SOLICIT;
neigh.code = 0;
neigh.reserved = 0;
neigh.target = *client;
memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN
addr.sin6_len = sizeof(struct sockaddr_in6);
#endif
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(IPPROTO_ICMPV6);
addr.sin6_addr = *client;
addr.sin6_scope_id = iface;
mac_param.target = client;
mac_param.maclen = 0;
mac_param.mac = mac;
for (i = 0; i < 5; i++)
{
struct timespec ts;
iface_enumerate(AF_UNSPEC, &mac_param, find_mac);
if (mac_param.maclen != 0)
break;
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, (struct sockaddr *)&addr, sizeof(addr));
ts.tv_sec = 0;
ts.tv_nsec = 100000000; /* 100ms */
nanosleep(&ts, NULL);
}
*maclenp = mac_param.maclen;
*mactypep = ARPHRD_ETHER;
}
static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
{
struct mac_param *parm = parmv;
@@ -552,6 +554,7 @@ static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, vo
unsigned char *p;
(void)index;
(void)parm;
if (type >= 256)
return 1;
@@ -599,7 +602,13 @@ static int construct_worker(struct in6_addr *local, int prefix,
IN6_IS_ADDR_MULTICAST(local))
return 1;
if (!indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, if_index, ifrn_name))
if (!(flags & IFACE_PERMANENT))
return 1;
if (flags & IFACE_DEPRECATED)
return 1;
if (!indextoname(daemon->icmp6fd, if_index, ifrn_name))
return 0;
for (template = daemon->dhcp6; template; template = template->next)
@@ -615,11 +624,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
}
}
else if ((addr6part(local) == addr6part(&template->start6) ||
addr6part(local) == addr6part(&template->end6) ||
(IN6_IS_ADDR_UNSPECIFIED(&template->start6) &&
IFACE_PERMANENT == (flags & (IFACE_PERMANENT | IFACE_DEPRECATED)))) &&
wildcard_match(template->template_interface, ifrn_name))
else if (wildcard_match(template->template_interface, ifrn_name))
{
start6 = *local;
setaddr6part(&start6, addr6part(&template->start6));
+4
View File
@@ -51,8 +51,10 @@ int main (int argc, char **argv)
cap_user_header_t hdr = NULL;
cap_user_data_t data = NULL;
#endif
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
struct dhcp_context *context;
struct dhcp_relay *relay;
#endif
#ifdef LOCALEDIR
setlocale(LC_ALL, "");
@@ -1231,6 +1233,8 @@ void poll_resolv(int force, int do_reload, time_t now)
void clear_cache_and_reload(time_t now)
{
(void)now;
if (daemon->port != 0)
cache_reload();
+5 -5
View File
@@ -1212,15 +1212,15 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
int prefix, u64 addr);
void make_duid(time_t now);
void dhcp_construct_contexts(time_t now);
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
unsigned int *maclenp, unsigned int *mactypep);
#endif
/* rfc3315.c */
#ifdef HAVE_DHCP6
unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
struct in6_addr *fallback, size_t sz, int is_multicast, time_t now,
unsigned char *mac, unsigned int mac_len, unsigned int mac_type);
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id,
unsigned char *mac, unsigned int mac_len, unsigned int mac_type);
struct in6_addr *fallback, size_t sz, struct in6_addr *client_addr, time_t now);
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id);
unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
#endif
+10 -5
View File
@@ -61,6 +61,9 @@ struct script_data
#else
time_t expires;
#endif
#ifdef HAVE_TFTP
off_t file_len;
#endif
#ifdef HAVE_DHCP6
struct in6_addr addr6;
int iaid, vendorclass_count;
@@ -289,10 +292,12 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
#endif
#ifdef HAVE_TFTP
/* file length */
if (data.action == ACTION_TFTP)
sprintf(daemon->dhcp_buff, "%u", data.hwaddr_len);
sprintf(is6 ? daemon->packet : daemon->dhcp_buff, "%lu", (unsigned long)data.file_len);
#endif
#ifdef HAVE_LUASCRIPT
if (daemon->luascript)
{
@@ -309,7 +314,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
lua_setfield(lua, -2, "destination_address");
lua_pushstring(lua, hostname);
lua_setfield(lua, -2, "file_name");
lua_pushstring(lua, daemon->dhcp_buff);
lua_pushstring(lua, is6 ? daemon->packet : daemon->dhcp_buff);
lua_setfield(lua, -2, "file_size");
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
}
@@ -739,13 +744,13 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
buf->action = ACTION_TFTP;
buf->hostname_len = filename_len;
buf->hwaddr_len = file_len;
buf->file_len = file_len;
if ((buf->flags = peer->sa.sa_family) == AF_INET)
buf->addr = peer->in.sin_addr;
#ifdef HAVE_IPV6
else
memcpy(buf->hwaddr, &peer->in6.sin6_addr, IN6ADDRSZ);
buf->addr6 = peer->in6.sin6_addr;
#endif
memcpy((unsigned char *)(buf+1), filename, filename_len);
+5
View File
@@ -788,6 +788,7 @@ void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
#endif
(void)force;
(void)now;
if (hw_len != lease->hwaddr_len ||
hw_type != lease->hwaddr_type ||
@@ -956,6 +957,8 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *do
void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now)
{
(void)now;
if (lease->last_interface == interface)
return;
@@ -984,6 +987,8 @@ int do_script_run(time_t now)
{
struct dhcp_lease *lease;
(void)now;
#ifdef HAVE_DBUS
/* If we're going to be sending DBus signals, but the connection is not yet up,
delay everything until it is. */
+2
View File
@@ -402,6 +402,8 @@ static int nl_async(struct nlmsghdr *h)
static void nl_newaddress(time_t now)
{
(void)now;
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
enumerate_interfaces(0);
+2
View File
@@ -709,6 +709,8 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
struct listener *l = NULL;
int fd = -1, tcpfd = -1, tftpfd = -1;
(void)do_tftp;
if (daemon->port != 0)
{
fd = make_sock(addr, SOCK_DGRAM, dienow);
+6 -3
View File
@@ -391,10 +391,13 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
addr.sin6_scope_id = iface;
}
else
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
{
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
}
send_from(daemon->icmp6fd, 0, daemon->outpacket.iov_base, save_counter(0),
(union mysockaddr *)&addr, (struct all_addr *)&parm.link_local, iface);
while (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
(struct sockaddr *)&addr, sizeof(addr)) == -1 && retry_send());
}
+262 -266
View File
File diff suppressed because it is too large. Load diff