Sync
This commit is contained in:
parent
71f31e7121
commit
f6e48aaf0c
159
external/bsd/dhcpcd/dist/dhcp.c
vendored
159
external/bsd/dhcpcd/dist/dhcp.c
vendored
@ -1,5 +1,5 @@
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: dhcp.c,v 1.6 2013/07/29 20:39:28 roy Exp $");
|
||||
__RCSID("$NetBSD: dhcp.c,v 1.7 2013/09/20 10:56:32 roy Exp $");
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
@ -1702,7 +1702,6 @@ dhcp_rebind(void *arg)
|
||||
send_rebind(ifp);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
dhcp_bind(void *arg)
|
||||
{
|
||||
@ -1724,10 +1723,10 @@ dhcp_bind(void *arg)
|
||||
state->offer = NULL;
|
||||
get_lease(lease, state->new);
|
||||
if (ifo->options & DHCPCD_STATIC) {
|
||||
syslog(LOG_INFO, "%s: using static address %s",
|
||||
iface->name, inet_ntoa(lease->addr));
|
||||
syslog(LOG_INFO, "%s: using static address %s/%d",
|
||||
iface->name, inet_ntoa(lease->addr),
|
||||
inet_ntocidr(lease->net));
|
||||
lease->leasetime = ~0U;
|
||||
lease->net.s_addr = ifo->req_mask.s_addr;
|
||||
state->reason = "STATIC";
|
||||
} else if (state->new->cookie != htonl(MAGIC_COOKIE)) {
|
||||
syslog(LOG_INFO, "%s: using IPv4LL address %s",
|
||||
@ -1834,7 +1833,7 @@ dhcp_timeout(void *arg)
|
||||
}
|
||||
|
||||
struct dhcp_message *
|
||||
dhcp_message_new(struct in_addr *addr, struct in_addr *mask)
|
||||
dhcp_message_new(const struct in_addr *addr, const struct in_addr *mask)
|
||||
{
|
||||
struct dhcp_message *dhcp;
|
||||
uint8_t *p;
|
||||
@ -1854,60 +1853,65 @@ dhcp_message_new(struct in_addr *addr, struct in_addr *mask)
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_3rdparty(struct interface *ifp)
|
||||
{
|
||||
struct if_options *ifo;
|
||||
struct dhcp_state *state;
|
||||
struct in_addr addr, net, dst;
|
||||
|
||||
ifo = ifp->options;
|
||||
if (ifo->req_addr.s_addr != INADDR_ANY)
|
||||
return 0;
|
||||
|
||||
if (ipv4_getaddress(ifp->name, &addr, &net, &dst) == 1)
|
||||
ipv4_handleifa(RTM_NEWADDR, ifp->name, &addr, &net, &dst);
|
||||
else {
|
||||
syslog(LOG_INFO,
|
||||
"%s: waiting for 3rd party to configure IP address",
|
||||
ifp->name);
|
||||
state = D_STATE(ifp);
|
||||
state->reason = "3RDPARTY";
|
||||
script_runreason(ifp, state->reason);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp_static(struct interface *ifp)
|
||||
{
|
||||
struct if_options *ifo;
|
||||
struct dhcp_state *state;
|
||||
|
||||
if (handle_3rdparty(ifp))
|
||||
return;
|
||||
ifo = ifp->options;
|
||||
state = D_STATE(ifp);
|
||||
ifo = ifp->options;
|
||||
if (ifo->req_addr.s_addr == INADDR_ANY) {
|
||||
syslog(LOG_INFO,
|
||||
"%s: waiting for 3rd party to "
|
||||
"configure IP address",
|
||||
ifp->name);
|
||||
state->reason = "3RDPARTY";
|
||||
script_runreason(ifp, state->reason);
|
||||
return;
|
||||
}
|
||||
state->offer = dhcp_message_new(&ifo->req_addr, &ifo->req_mask);
|
||||
eloop_timeout_delete(NULL, ifp);
|
||||
dhcp_bind(ifp);
|
||||
if (state->offer) {
|
||||
eloop_timeout_delete(NULL, ifp);
|
||||
dhcp_bind(ifp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dhcp_inform(struct interface *ifp)
|
||||
{
|
||||
struct dhcp_state *state;
|
||||
|
||||
if (handle_3rdparty(ifp))
|
||||
return;
|
||||
struct if_options *ifo;
|
||||
struct ipv4_addr *ap;
|
||||
|
||||
state = D_STATE(ifp);
|
||||
ifo = ifp->options;
|
||||
if (options & DHCPCD_TEST) {
|
||||
state->addr.s_addr = ifp->options->req_addr.s_addr;
|
||||
state->net.s_addr = ifp->options->req_mask.s_addr;
|
||||
state->addr.s_addr = ifo->req_addr.s_addr;
|
||||
state->net.s_addr = ifo->req_mask.s_addr;
|
||||
} else {
|
||||
ifp->options->options |= DHCPCD_STATIC;
|
||||
dhcp_static(ifp);
|
||||
if (ifo->req_addr.s_addr == INADDR_ANY) {
|
||||
state = D_STATE(ifp);
|
||||
ap = ipv4_findaddr(ifp, NULL, NULL);
|
||||
if (ap == NULL) {
|
||||
syslog(LOG_INFO,
|
||||
"%s: waiting for 3rd party to "
|
||||
"configure IP address",
|
||||
ifp->name);
|
||||
state->reason = "3RDPARTY";
|
||||
script_runreason(ifp, state->reason);
|
||||
return;
|
||||
}
|
||||
state->offer =
|
||||
dhcp_message_new(&ap->addr, &ap->net);
|
||||
} else
|
||||
state->offer =
|
||||
dhcp_message_new(&ifo->req_addr, &ifo->req_mask);
|
||||
if (state->offer) {
|
||||
ifo->options |= DHCPCD_STATIC;
|
||||
dhcp_bind(ifp);
|
||||
ifo->options &= ~DHCPCD_STATIC;
|
||||
}
|
||||
}
|
||||
|
||||
state->state = DHS_INFORM;
|
||||
@ -2220,6 +2224,8 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
|
||||
|
||||
if (!(ifo->options & DHCPCD_INFORM))
|
||||
log_dhcp(LOG_DEBUG, "acknowledged", iface, dhcp, from);
|
||||
else
|
||||
ifo->options &= ~DHCPCD_STATIC;
|
||||
}
|
||||
|
||||
/* BOOTP could have already assigned this above, so check we still
|
||||
@ -2244,7 +2250,7 @@ dhcp_handle(struct interface *iface, struct dhcp_message **dhcpp,
|
||||
/* If the interface already has the address configured
|
||||
* then we can't ARP for duplicate detection. */
|
||||
addr.s_addr = state->offer->yiaddr;
|
||||
if (ipv4_hasaddress(iface->name, &addr, NULL) != 1) {
|
||||
if (!ipv4_findaddr(iface, &addr, NULL)) {
|
||||
state->claims = 0;
|
||||
state->probes = 0;
|
||||
state->conflicts = 0;
|
||||
@ -2687,3 +2693,70 @@ dhcp_start(struct interface *ifp)
|
||||
else
|
||||
dhcp_reboot(ifp);
|
||||
}
|
||||
|
||||
void
|
||||
dhcp_handleifa(int type, struct interface *ifp,
|
||||
const struct in_addr *addr,
|
||||
const struct in_addr *net,
|
||||
const struct in_addr *dst)
|
||||
{
|
||||
struct dhcp_state *state;
|
||||
struct if_options *ifo;
|
||||
int i;
|
||||
|
||||
state = D_STATE(ifp);
|
||||
if (state == NULL)
|
||||
return;
|
||||
|
||||
if (type == RTM_DELADDR) {
|
||||
if (state->new &&
|
||||
(state->new->yiaddr == addr->s_addr ||
|
||||
(state->new->yiaddr == INADDR_ANY &&
|
||||
state->new->ciaddr == addr->s_addr)))
|
||||
{
|
||||
syslog(LOG_INFO, "%s: removing IP address %s/%d",
|
||||
ifp->name, inet_ntoa(state->lease.addr),
|
||||
inet_ntocidr(state->lease.net));
|
||||
dhcp_drop(ifp, "EXPIRE");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (type != RTM_NEWADDR)
|
||||
return;
|
||||
|
||||
ifo = ifp->options;
|
||||
if (ifo->options & DHCPCD_INFORM) {
|
||||
if (state->state != DHS_INFORM)
|
||||
dhcp_inform(ifp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(ifo->options & DHCPCD_STATIC))
|
||||
return;
|
||||
if (ifo->req_addr.s_addr != INADDR_ANY)
|
||||
return;
|
||||
|
||||
free(state->old);
|
||||
state->old = state->new;
|
||||
state->new = dhcp_message_new(addr, net);
|
||||
if (state->new == NULL)
|
||||
return;
|
||||
state->dst.s_addr = dst ? dst->s_addr : INADDR_ANY;
|
||||
if (dst) {
|
||||
for (i = 1; i < 255; i++)
|
||||
if (i != DHO_ROUTER && has_option_mask(ifo->dstmask,i))
|
||||
dhcp_message_add_addr(state->new, i, *dst);
|
||||
}
|
||||
state->reason = "STATIC";
|
||||
ipv4_buildroutes();
|
||||
script_runreason(ifp, state->reason);
|
||||
if (ifo->options & DHCPCD_INFORM) {
|
||||
state->state = DHS_INFORM;
|
||||
state->xid = dhcp_xid(ifp);
|
||||
state->lease.server.s_addr = dst ? dst->s_addr : INADDR_ANY;
|
||||
state->addr = *addr;
|
||||
state->net = *net;
|
||||
dhcp_inform(ifp);
|
||||
}
|
||||
}
|
||||
|
82
external/bsd/dhcpcd/dist/dhcpcd.8.in
vendored
82
external/bsd/dhcpcd/dist/dhcpcd.8.in
vendored
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: dhcpcd.8.in,v 1.21 2013/07/29 20:39:28 roy Exp $
|
||||
.\" $NetBSD: dhcpcd.8.in,v 1.22 2013/09/20 10:56:32 roy Exp $
|
||||
.\" Copyright (c) 2006-2013 Roy Marples
|
||||
.\" All rights reserved
|
||||
.\"
|
||||
@ -23,7 +23,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd June 6, 2013
|
||||
.Dd September 12, 2013
|
||||
.Dt DHCPCD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -31,7 +31,7 @@
|
||||
.Nd a DHCP client
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl 46ABbDdEGgHJKkLnpqTVw
|
||||
.Op Fl 46ABbDdEGgHJKLpqTV
|
||||
.Op Fl C , Fl Fl nohook Ar hook
|
||||
.Op Fl c , Fl Fl script Ar script
|
||||
.Op Fl e , Fl Fl env Ar value
|
||||
@ -52,6 +52,7 @@
|
||||
.Op Fl u , Fl Fl userclass Ar class
|
||||
.Op Fl v , Fl Fl vendor Ar code , Ar value
|
||||
.Op Fl W , Fl Fl whitelist Ar address Ns Op Ar /cidr
|
||||
.Op Fl w , Fl Fl waitip Op 4 | 6
|
||||
.Op Fl y , Fl Fl reboot Ar seconds
|
||||
.Op Fl X , Fl Fl blacklist Ar address Ns Op Ar /cidr
|
||||
.Op Fl Z , Fl Fl denyinterfaces Ar pattern
|
||||
@ -59,6 +60,9 @@
|
||||
.Op interface
|
||||
.Op ...
|
||||
.Nm
|
||||
.Fl n , Fl Fl rebind
|
||||
.Op interface
|
||||
.Nm
|
||||
.Fl k , Fl Fl release
|
||||
.Op interface
|
||||
.Nm
|
||||
@ -300,16 +304,19 @@ For example
|
||||
If not set then none is sent.
|
||||
Some badly configured DHCP servers reject unknown vendorclassids.
|
||||
To work around it, try and impersonate Windows by using the MSFT vendorclassid.
|
||||
.It Fl k , Fl Fl release
|
||||
.It Fl k , Fl Fl release Op Ar interface
|
||||
This causes an existing
|
||||
.Nm
|
||||
process running on the
|
||||
.Ar interface
|
||||
to release its lease, de-configure the
|
||||
to release its lease and de-configure the
|
||||
.Ar interface .
|
||||
If no
|
||||
.Ar interface
|
||||
and then exit.
|
||||
is specified then this applies to all interfaces.
|
||||
If no interfaces are left running,
|
||||
.Nm
|
||||
then waits until this process has exited.
|
||||
will exit.
|
||||
.It Fl l , Fl Fl leasetime Ar seconds
|
||||
Request a specific lease time in
|
||||
.Ar seconds .
|
||||
@ -323,10 +330,12 @@ Metrics are used to prefer an interface over another one, lowest wins.
|
||||
will supply a default metic of 200 +
|
||||
.Xr if_nametoindex 3 .
|
||||
An extra 100 will be added for wireless interfaces.
|
||||
.It Fl n , Fl Fl rebind
|
||||
.It Fl n , Fl Fl rebind Op Ar interface
|
||||
Notifies
|
||||
.Nm
|
||||
to reload its configuration and rebind its interfaces.
|
||||
to reload its configuration and rebind the specified
|
||||
.Ar interface .
|
||||
If no interface is specified then this applies to all interfaces.
|
||||
If
|
||||
.Nm
|
||||
is not running, then it starts up as normal.
|
||||
@ -344,7 +353,8 @@ normally de-configures the
|
||||
.Ar interface
|
||||
and configuration when it exits.
|
||||
Sometimes, this isn't desirable if, for example, you have root mounted over
|
||||
NFS.
|
||||
NFS or SSH clients connect to this host and they need to be notified of
|
||||
the host shutting down.
|
||||
You can use this option to stop this from happening.
|
||||
.It Fl r , Fl Fl request Op Ar address
|
||||
Request the
|
||||
@ -374,6 +384,21 @@ If
|
||||
.Nm
|
||||
fails to contact a DHCP server then it returns a failure instead of falling
|
||||
back on IPv4LL.
|
||||
.It Fl S, Fl Fl static Ar value
|
||||
Configures a static
|
||||
.Ar value .
|
||||
If you set
|
||||
.Ic ip_address
|
||||
then
|
||||
.Nm
|
||||
will not attempt to obtain a lease and just use the value for the address with
|
||||
an infinite lease time.
|
||||
.Pp
|
||||
Here is an example which configures a static address, routes and dns.
|
||||
.D1 dhcpcd -S ip_address=192.168.0.10/24 \e
|
||||
.D1 -S routers=192.168.0.1 \e
|
||||
.D1 -S domain_name_servers=192.168.0.1 \e
|
||||
.D1 eth0
|
||||
.It Fl t , Fl Fl timeout Ar seconds
|
||||
Timeout after
|
||||
.Ar seconds ,
|
||||
@ -409,9 +434,17 @@ Set un-encapsulated vendor option to hello world.
|
||||
Display both program version and copyright information.
|
||||
.Nm
|
||||
then exits before doing any configuration.
|
||||
.It Fl w , Fl Fl waitip
|
||||
.It Fl w , Fl Fl waitip Op 4 | 6
|
||||
Wait for an address to be assigned before forking to the background.
|
||||
.It Fl x , Fl Fl exit
|
||||
4 means wait for an IPv4 address to be assigned.
|
||||
6 means wait for an IPv6 address to be assigned.
|
||||
If no argument is given,
|
||||
.Nm
|
||||
will wait for any address protocol to be assigned.
|
||||
It is possible to wait for more than one address protocol and
|
||||
.Nm
|
||||
will only fork to the background when all waiting conditions are satisfied.
|
||||
.It Fl x , Fl Fl exit Op Ar interface
|
||||
This will signal an existing
|
||||
.Nm
|
||||
process running on the
|
||||
@ -419,6 +452,7 @@ process running on the
|
||||
to de-configure the
|
||||
.Ar interface
|
||||
and exit.
|
||||
If no interface is specified, then the above is applied to all interfaces.
|
||||
.Nm
|
||||
then waits until this process has exited.
|
||||
.It Fl y , Fl Fl reboot Ar seconds
|
||||
@ -494,21 +528,6 @@ Quiet
|
||||
.Nm
|
||||
on the command line, only warnings and errors will be displayed.
|
||||
The messages are still logged though.
|
||||
.It Fl S, Fl Fl static Ar value
|
||||
Configures a static
|
||||
.Ar value .
|
||||
If you set
|
||||
.Ic ip_address
|
||||
then
|
||||
.Nm
|
||||
will not attempt to obtain a lease and just use the value for the address with
|
||||
an infinite lease time.
|
||||
.Pp
|
||||
Here is an example which configures a static address, routes and dns.
|
||||
.D1 dhcpcd -S ip_address=192.168.0.10/24 \e
|
||||
.D1 -S routers=192.168.0.1 \e
|
||||
.D1 -S domain_name_servers=192.168.0.1 \e
|
||||
.D1 eth0
|
||||
.It Fl T, Fl Fl test
|
||||
On receipt of DHCP messages just call
|
||||
.Pa @SCRIPT@
|
||||
@ -554,6 +573,10 @@ which is a space or comma separated list of patterns passed to
|
||||
If the same interface is matched in
|
||||
.Fl Z , Fl Fl denyinterfaces
|
||||
then it is still denied.
|
||||
.It Fl Fl nodev
|
||||
Don't load any
|
||||
.Pa /dev
|
||||
management modules.
|
||||
.El
|
||||
.Sh 3RDPARTY LINK MANAGEMENT
|
||||
Some interfaces require configuration by 3rd parties, such as PPP or VPN.
|
||||
@ -582,6 +605,9 @@ If you always use the same options, put them here.
|
||||
Text file that holds the DUID used to identify the host.
|
||||
.It Pa @SCRIPT@
|
||||
Bourne shell script that is run to configure or de-configure an interface.
|
||||
.It Pa @LIBDIR@/dhcpcd/dev
|
||||
.Pa /dev
|
||||
management modules.
|
||||
.It Pa @HOOKDIR@
|
||||
A directory containing bourne shell scripts that are run by the above script.
|
||||
Each script can be disabled by using the
|
||||
@ -612,7 +638,7 @@ running on the
|
||||
RFC\ 951 RFC\ 1534 RFC\ 2131, RFC\ 2132, RFC\ 2855, RFC\ 3004, RFC\ 3315,
|
||||
RFC\ 3361, RFC\ 3633, RFC\ 3396, RFC\ 3397, RFC\ 3442, RFC\ 3927, RFC\ 4039
|
||||
RFC\ 4075, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4704, RFC\ 4861, RFC\ 4833,
|
||||
RFC\ 5227, RFC\ 5969, RFC\ 6106.
|
||||
RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106.
|
||||
.Sh AUTHORS
|
||||
.An Roy Marples Aq Mt roy@marples.name
|
||||
.Sh BUGS
|
||||
|
5
external/bsd/dhcpcd/dist/dhcpcd.conf
vendored
5
external/bsd/dhcpcd/dist/dhcpcd.conf
vendored
@ -1,4 +1,4 @@
|
||||
# $NetBSD: dhcpcd.conf,v 1.7 2013/07/29 20:39:28 roy Exp $
|
||||
# $NetBSD: dhcpcd.conf,v 1.8 2013/09/20 10:56:32 roy Exp $
|
||||
|
||||
# A sample configuration for dhcpcd.
|
||||
# See dhcpcd.conf(5) for details.
|
||||
@ -12,6 +12,9 @@ hostname
|
||||
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
|
||||
duid
|
||||
|
||||
# Persist interface configuration when dhcpcd exits.
|
||||
persistent
|
||||
|
||||
# Rapid commit support.
|
||||
# Safe to enable by default because it requires the equivalent option set
|
||||
# on the server to actually work.
|
||||
|
34
external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
vendored
34
external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
vendored
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: dhcpcd.conf.5.in,v 1.3 2013/07/29 20:39:28 roy Exp $
|
||||
.\" $NetBSD: dhcpcd.conf.5.in,v 1.4 2013/09/20 10:56:32 roy Exp $
|
||||
.\" Copyright (c) 2006-2013 Roy Marples
|
||||
.\" All rights reserved
|
||||
.\"
|
||||
@ -23,7 +23,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd July 25, 2013
|
||||
.Dd September 12, 2013
|
||||
.Dt DHCPCD.CONF 5 SMM
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -91,6 +91,13 @@ such as FireWire and InfiniBand.
|
||||
In most cases,
|
||||
.Nm dhcpcd
|
||||
will set this automatically.
|
||||
.It Ic dev Ar value
|
||||
Load the
|
||||
.Ar value
|
||||
.Pa /dev
|
||||
management module.
|
||||
.Nm dhcpcd
|
||||
will load the first one found to work, if any.
|
||||
.It Ic env Ar value
|
||||
Push
|
||||
.Ar value
|
||||
@ -135,6 +142,13 @@ is generated, otherwise DUID-LL is generated (link local address).
|
||||
The DUID-LLT generated will be held in
|
||||
.Pa @SYSCONFDIR@/dhcpcd.duid
|
||||
and should not be copied to other hosts.
|
||||
.It Ic persistent
|
||||
.Nm dhcpcd
|
||||
normally de-configures the interface and configuration when it exits.
|
||||
Sometimes, this isn't desirable if, for example, you have root mounted over
|
||||
NFS or SSH clients connect to this host and they need to be notified of
|
||||
the host shutting down.
|
||||
You can use this option to stop this from happening.
|
||||
.It Ic fallback Ar profile
|
||||
Fallback to using this profile if DHCP fails.
|
||||
This allows you to configure a static profile instead of using ZeroConf.
|
||||
@ -164,9 +178,11 @@ If none is specified, a default
|
||||
is used.
|
||||
If the interface name is 4 characters or less then that is used,
|
||||
otherwise the interface index is used.
|
||||
You can request more than one ia_na by specifying a unique iaid for each one.
|
||||
.It Ic ia_ta Op Ar iaid
|
||||
Request a DHCPv6 Temporary Address for
|
||||
.Ar iaid .
|
||||
You can request more than one ia_ta by specifying a unique iaid for each one.
|
||||
.It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len
|
||||
Request a DHCPv6 Delegated Prefix for
|
||||
.Ar iaid .
|
||||
@ -255,6 +271,10 @@ alongside.
|
||||
.It Ic noarp
|
||||
Don't send any ARP requests.
|
||||
This also disables IPv4LL.
|
||||
.It Ic nodev
|
||||
Don't load
|
||||
.Pa /dev
|
||||
management modules.
|
||||
.It Ic nogateway
|
||||
Don't install any default routes.
|
||||
.It Ic nohook Ar script
|
||||
@ -404,8 +424,16 @@ For example
|
||||
If not set then none is sent.
|
||||
Some badly configured DHCP servers reject unknown vendorclassids.
|
||||
To work around it, try and impersonate Windows by using the MSFT vendorclassid.
|
||||
.It Ic waitip
|
||||
.It Ic waitip Op 4 | 6
|
||||
Wait for an address to be assigned before forking to the background.
|
||||
4 means wait for an IPv4 address to be assigned.
|
||||
6 means wait for an IPv6 address to be assigned.
|
||||
If no argument is given,
|
||||
.Nm
|
||||
will wait for any address protocol to be assigned.
|
||||
It is possible to wait for more than one address protocol and
|
||||
.Nm
|
||||
will only fork to the background when all waiting conditions are satisfied.
|
||||
.It Ic xidhwaddr
|
||||
Use the last four bytes of the hardware address as the DHCP xid instead
|
||||
of a randomly generated number.
|
||||
|
690
external/bsd/dhcpcd/dist/ipv6ns.c
vendored
690
external/bsd/dhcpcd/dist/ipv6ns.c
vendored
@ -1,690 +0,0 @@
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: ipv6ns.c,v 1.1.1.3 2013/06/21 19:33:08 roy Exp $");
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __linux__
|
||||
# define _LINUX_IN6_H
|
||||
# include <linux/ipv6.h>
|
||||
#endif
|
||||
|
||||
#define ELOOP_QUEUE 2
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "dhcp6.h"
|
||||
#include "eloop.h"
|
||||
#include "ipv6.h"
|
||||
#include "ipv6ns.h"
|
||||
#include "script.h"
|
||||
|
||||
#define MIN_RANDOM_FACTOR 500 /* millisecs */
|
||||
#define MAX_RANDOM_FACTOR 1500 /* millisecs */
|
||||
#define MIN_RANDOM_FACTOR_U MIN_RANDOM_FACTOR * 1000 /* usecs */
|
||||
#define MAX_RANDOM_FACTOR_U MAX_RANDOM_FACTOR * 1000 /* usecs */
|
||||
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define IPV6_ADDR_INT32_ONE 1
|
||||
#define IPV6_ADDR_INT16_MLL 0xff02
|
||||
#elif BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define IPV6_ADDR_INT32_ONE 0x01000000
|
||||
#define IPV6_ADDR_INT16_MLL 0x02ff
|
||||
#endif
|
||||
|
||||
/* Debugging Neighbor Solicitations is a lot of spam, so disable it */
|
||||
//#define DEBUG_NS
|
||||
//
|
||||
|
||||
/* Currently, no known kernel allows us to send from the unspecified address
|
||||
* which is required for DAD to work. This isn't that much of a problem as
|
||||
* the kernel will do DAD for us correctly, however we don't know the exact
|
||||
* randomness the kernel applies to the timeouts. So we just follow the same
|
||||
* logic and have a little faith.
|
||||
* This define is purely for completeness */
|
||||
// #define IPV6_SEND_DAD
|
||||
|
||||
static int sock = -1;
|
||||
#ifdef IPV6_SEND_DAD
|
||||
static int unspec_sock = -1;
|
||||
#endif
|
||||
static struct sockaddr_in6 from;
|
||||
static struct msghdr sndhdr;
|
||||
static struct iovec sndiov[2];
|
||||
static unsigned char *sndbuf;
|
||||
static struct msghdr rcvhdr;
|
||||
static struct iovec rcviov[2];
|
||||
static unsigned char *rcvbuf;
|
||||
static unsigned char ansbuf[1500];
|
||||
static char ntopbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
static void ipv6ns_handledata(__unused void *arg);
|
||||
|
||||
#if DEBUG_MEMORY
|
||||
static void
|
||||
ipv6ns_cleanup(void)
|
||||
{
|
||||
|
||||
free(sndbuf);
|
||||
free(rcvbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ipv6ns_open(void)
|
||||
{
|
||||
int on;
|
||||
int len;
|
||||
struct icmp6_filter filt;
|
||||
#ifdef IPV6_SEND_DAD
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in6 sin;
|
||||
} su;
|
||||
#endif
|
||||
|
||||
if (sock != -1)
|
||||
return sock;
|
||||
|
||||
sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
if (sock == -1)
|
||||
return -1;
|
||||
on = 1;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
|
||||
&on, sizeof(on)) == -1)
|
||||
goto eexit;
|
||||
|
||||
on = 1;
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
|
||||
&on, sizeof(on)) == -1)
|
||||
goto eexit;
|
||||
|
||||
ICMP6_FILTER_SETBLOCKALL(&filt);
|
||||
|
||||
#ifdef IPV6_SEND_DAD
|
||||
/* We send DAD requests from the unspecified address. */
|
||||
unspec_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
if (unspec_sock == -1)
|
||||
goto eexit;
|
||||
if (setsockopt(unspec_sock, IPPROTO_ICMPV6, ICMP6_FILTER,
|
||||
&filt, sizeof(filt)) == -1)
|
||||
goto eexit;
|
||||
memset(&su, 0, sizeof(su));
|
||||
su.sin.sin6_family = AF_INET6;
|
||||
#ifdef SIN6_LEN
|
||||
su.sin.sin6_len = sizeof(su.sin);
|
||||
#endif
|
||||
if (bind(unspec_sock, &su.sa, sizeof(su.sin)) == -1)
|
||||
goto eexit;
|
||||
#endif
|
||||
|
||||
ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
|
||||
if (setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER,
|
||||
&filt, sizeof(filt)) == -1)
|
||||
goto eexit;
|
||||
|
||||
set_cloexec(sock);
|
||||
#if DEBUG_MEMORY
|
||||
atexit(ipv6ns_cleanup);
|
||||
#endif
|
||||
|
||||
#ifdef LISTEN_DAD
|
||||
syslog(LOG_WARNING, "kernel does not report DAD results to userland");
|
||||
syslog(LOG_WARNING,
|
||||
"warning listening to duplicated addresses on the wire");
|
||||
#endif
|
||||
|
||||
len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
|
||||
sndbuf = calloc(1, len);
|
||||
if (sndbuf == NULL)
|
||||
goto eexit;
|
||||
sndhdr.msg_namelen = sizeof(struct sockaddr_in6);
|
||||
sndhdr.msg_iov = sndiov;
|
||||
sndhdr.msg_iovlen = 1;
|
||||
sndhdr.msg_control = sndbuf;
|
||||
sndhdr.msg_controllen = len;
|
||||
rcvbuf = calloc(1, len);
|
||||
if (rcvbuf == NULL)
|
||||
goto eexit;
|
||||
rcvhdr.msg_name = &from;
|
||||
rcvhdr.msg_namelen = sizeof(from);
|
||||
rcvhdr.msg_iov = rcviov;
|
||||
rcvhdr.msg_iovlen = 1;
|
||||
rcvhdr.msg_control = rcvbuf;
|
||||
rcvhdr.msg_controllen = len;
|
||||
rcviov[0].iov_base = ansbuf;
|
||||
rcviov[0].iov_len = sizeof(ansbuf);
|
||||
|
||||
eloop_event_add(sock, ipv6ns_handledata, NULL);
|
||||
return sock;
|
||||
|
||||
eexit:
|
||||
syslog(LOG_ERR, "%s: %m", __func__);
|
||||
close(sock);
|
||||
sock = -1;
|
||||
free(sndbuf);
|
||||
sndbuf = NULL;
|
||||
free(rcvbuf);
|
||||
rcvbuf = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
ipv6ns_unreachable(void *arg)
|
||||
{
|
||||
struct ra *rap = arg;
|
||||
struct timeval tv;
|
||||
|
||||
/* We could add an unreachable flag and persist the information,
|
||||
* but that is more effort than it's probably worth. */
|
||||
syslog(LOG_WARNING, "%s: %s is unreachable, expiring it",
|
||||
rap->iface->name, rap->sfrom);
|
||||
rap->expired = 1;
|
||||
ipv6_buildroutes();
|
||||
script_runreason(rap->iface, "ROUTERADVERT"); /* XXX not RA */
|
||||
|
||||
/* We should still test if it's reachable or not so
|
||||
* incase it comes back to life and it's preferable. */
|
||||
if (rap->reachable) {
|
||||
ms_to_tv(&tv, rap->reachable);
|
||||
} else {
|
||||
tv.tv_sec = REACHABLE_TIME;
|
||||
tv.tv_usec = 0;
|
||||
}
|
||||
eloop_timeout_add_tv(&tv, ipv6ns_proberouter, rap);
|
||||
}
|
||||
|
||||
#ifdef LISTEN_DAD
|
||||
void
|
||||
ipv6ns_cancelprobeaddr(struct ipv6_addr *ap)
|
||||
{
|
||||
|
||||
eloop_timeout_delete(ipv6ns_probeaddr, ap);
|
||||
if (ap->dadcallback)
|
||||
eloop_timeout_delete(ap->dadcallback, ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ipv6ns_probeaddr(void *arg)
|
||||
{
|
||||
struct ipv6_addr *ap = arg;
|
||||
#ifdef IPV6_SEND_DAD
|
||||
struct nd_neighbor_solicit *ns;
|
||||
struct nd_opt_hdr *nd;
|
||||
struct sockaddr_in6 dst;
|
||||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo pi;
|
||||
int hoplimit = HOPLIMIT;
|
||||
#else
|
||||
#ifdef LISTEN_DAD
|
||||
struct timeval tv, rtv;
|
||||
struct timeval mtv;
|
||||
int i;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (ap->dadcallback &&
|
||||
((ap->flags & IPV6_AF_NEW) == 0 ||
|
||||
ap->nsprobes >= ap->iface->options->dadtransmits))
|
||||
{
|
||||
#ifdef IPV6_SEND_DAD
|
||||
ap->dadcallback(ap);
|
||||
#else
|
||||
ipv6_addaddr(ap);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (ipv6ns_open() == -1)
|
||||
return;
|
||||
|
||||
ap->flags &= ~IPV6_AF_DADCOMPLETED;
|
||||
|
||||
#ifdef IPV6_SEND_DAD
|
||||
if (!ap->ns) {
|
||||
ap->nslen = sizeof(*ns) + ROUNDUP8(ap->iface->hwlen + 2);
|
||||
ap->ns = calloc(1, ap->nslen);
|
||||
if (ap->ns == NULL) {
|
||||
syslog(LOG_ERR, "%s: %m", __func__);
|
||||
return;
|
||||
}
|
||||
ns = (struct nd_neighbor_solicit *)(void *)ap->ns;
|
||||
ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
|
||||
//ns->nd_ns_cksum = 0;
|
||||
//ns->nd_ns_code = 0;
|
||||
//ns->nd_ns_reserved = 0;
|
||||
ns->nd_ns_target = ap->addr;
|
||||
nd = (struct nd_opt_hdr *)(ap->ns + sizeof(*ns));
|
||||
nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
|
||||
nd->nd_opt_len = (ROUNDUP8(ap->iface->hwlen + 2)) >> 3;
|
||||
memcpy(nd + 1, ap->iface->hwaddr, ap->iface->hwlen);
|
||||
}
|
||||
|
||||
memset(&dst, 0, sizeof(dst));
|
||||
dst.sin6_family = AF_INET6;
|
||||
#ifdef SIN6_LEN
|
||||
dst.sin6_len = sizeof(dst);
|
||||
#endif
|
||||
dst.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
|
||||
dst.sin6_addr.s6_addr16[1] = 0;
|
||||
dst.sin6_addr.s6_addr32[1] = 0;
|
||||
dst.sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
|
||||
dst.sin6_addr.s6_addr32[3] = ap->addr.s6_addr32[3];
|
||||
dst.sin6_addr.s6_addr[12] = 0xff;
|
||||
|
||||
//memcpy(&dst.sin6_addr, &ap->addr, sizeof(dst.sin6_addr));
|
||||
dst.sin6_scope_id = ap->iface->index;
|
||||
|
||||
sndhdr.msg_name = (caddr_t)&dst;
|
||||
sndhdr.msg_iov[0].iov_base = ap->ns;
|
||||
sndhdr.msg_iov[0].iov_len = ap->nslen;
|
||||
|
||||
/* Set the outbound interface */
|
||||
cm = CMSG_FIRSTHDR(&sndhdr);
|
||||
cm->cmsg_level = IPPROTO_IPV6;
|
||||
cm->cmsg_type = IPV6_PKTINFO;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(pi));
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
pi.ipi6_ifindex = ap->iface->index;
|
||||
memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
|
||||
|
||||
/* Hop limit */
|
||||
cm = CMSG_NXTHDR(&sndhdr, cm);
|
||||
cm->cmsg_level = IPPROTO_IPV6;
|
||||
cm->cmsg_type = IPV6_HOPLIMIT;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(hoplimit));
|
||||
memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit));
|
||||
|
||||
#ifdef DEBUG_NS
|
||||
syslog(LOG_INFO, "%s: sending IPv6 NS for %s",
|
||||
ap->iface->name, ap->saddr);
|
||||
if (ap->dadcallback == NULL)
|
||||
syslog(LOG_WARNING, "%s: no callback!", ap->iface->name);
|
||||
#endif
|
||||
if (sendmsg(unspec_sock, &sndhdr, 0) == -1) {
|
||||
syslog(LOG_ERR, "%s: %s: sendmsg: %m",
|
||||
ap->iface->name, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ap->dadcallback) {
|
||||
ms_to_tv(&tv, RETRANS_TIMER);
|
||||
ms_to_tv(&rtv, MIN_RANDOM_FACTOR);
|
||||
timeradd(&tv, &rtv, &tv);
|
||||
rtv.tv_sec = 0;
|
||||
rtv.tv_usec = arc4random() %
|
||||
(MAX_RANDOM_FACTOR_U - MIN_RANDOM_FACTOR_U);
|
||||
timeradd(&tv, &rtv, &tv);
|
||||
|
||||
eloop_timeout_add_tv(&tv,
|
||||
++(ap->nsprobes) < ap->iface->options->dadtransmits ?
|
||||
ipv6ns_probeaddr : ap->dadcallback,
|
||||
ap);
|
||||
}
|
||||
#else /* IPV6_SEND_DAD */
|
||||
ipv6_addaddr(ap);
|
||||
#ifdef LISTEN_DAD
|
||||
/* Let the kernel handle DAD.
|
||||
* We don't know the timings, so just wait for the max */
|
||||
if (ap->dadcallback) {
|
||||
mtv.tv_sec = 0;
|
||||
mtv.tv_usec = 0;
|
||||
for (i = 0; i < ap->iface->options->dadtransmits; i++) {
|
||||
ms_to_tv(&tv, RETRANS_TIMER);
|
||||
ms_to_tv(&rtv, MAX_RANDOM_FACTOR);
|
||||
timeradd(&tv, &rtv, &tv);
|
||||
timeradd(&mtv, &tv, &mtv);
|
||||
}
|
||||
eloop_timeout_add_tv(&mtv, ap->dadcallback, ap);
|
||||
}
|
||||
#endif
|
||||
#endif /* IPV6_SEND_DAD */
|
||||
}
|
||||
|
||||
ssize_t
|
||||
ipv6ns_probeaddrs(struct ipv6_addrhead *addrs)
|
||||
{
|
||||
struct ipv6_addr *ap, *apn;
|
||||
ssize_t i;
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
|
||||
if (ap->prefix_vltime == 0) {
|
||||
TAILQ_REMOVE(addrs, ap, next);
|
||||
if (ap->flags & IPV6_AF_ADDED) {
|
||||
syslog(LOG_INFO, "%s: deleting address %s",
|
||||
ap->iface->name, ap->saddr);
|
||||
i++;
|
||||
}
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
|
||||
del_address6(ap) == -1 &&
|
||||
errno != EADDRNOTAVAIL && errno != ENXIO)
|
||||
syslog(LOG_ERR, "del_address6 %m");
|
||||
if (ap->dadcallback)
|
||||
eloop_q_timeout_delete(0, NULL,
|
||||
ap->dadcallback);
|
||||
free(ap);
|
||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&ap->addr) &&
|
||||
!(ap->flags & IPV6_AF_DELEGATED))
|
||||
{
|
||||
ipv6ns_probeaddr(ap);
|
||||
if (ap->flags & IPV6_AF_NEW)
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
ipv6ns_proberouter(void *arg)
|
||||
{
|
||||
struct ra *rap = arg;
|
||||
struct nd_neighbor_solicit *ns;
|
||||
struct nd_opt_hdr *nd;
|
||||
struct sockaddr_in6 dst;
|
||||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo pi;
|
||||
int hoplimit = HOPLIMIT;
|
||||
struct timeval tv, rtv;
|
||||
|
||||
if (ipv6ns_open() == -1)
|
||||
return;
|
||||
|
||||
if (!rap->ns) {
|
||||
rap->nslen = sizeof(*ns) + ROUNDUP8(rap->iface->hwlen + 2);
|
||||
rap->ns = calloc(1, rap->nslen);
|
||||
if (rap->ns == NULL) {
|
||||
syslog(LOG_ERR, "%s: %m", __func__);
|
||||
return;
|
||||
}
|
||||
ns = (struct nd_neighbor_solicit *)(void *)rap->ns;
|
||||
ns->nd_ns_type = ND_NEIGHBOR_SOLICIT;
|
||||
//ns->nd_ns_cksum = 0;
|
||||
//ns->nd_ns_code = 0;
|
||||
//ns->nd_ns_reserved = 0;
|
||||
ns->nd_ns_target = rap->from;
|
||||
nd = (struct nd_opt_hdr *)(rap->ns + sizeof(*ns));
|
||||
nd->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
|
||||
nd->nd_opt_len = (ROUNDUP8(rap->iface->hwlen + 2)) >> 3;
|
||||
memcpy(nd + 1, rap->iface->hwaddr, rap->iface->hwlen);
|
||||
}
|
||||
|
||||
memset(&dst, 0, sizeof(dst));
|
||||
dst.sin6_family = AF_INET6;
|
||||
#ifdef SIN6_LEN
|
||||
dst.sin6_len = sizeof(dst);
|
||||
#endif
|
||||
memcpy(&dst.sin6_addr, &rap->from, sizeof(dst.sin6_addr));
|
||||
dst.sin6_scope_id = rap->iface->index;
|
||||
|
||||
sndhdr.msg_name = (caddr_t)&dst;
|
||||
sndhdr.msg_iov[0].iov_base = rap->ns;
|
||||
sndhdr.msg_iov[0].iov_len = rap->nslen;
|
||||
|
||||
/* Set the outbound interface */
|
||||
cm = CMSG_FIRSTHDR(&sndhdr);
|
||||
cm->cmsg_level = IPPROTO_IPV6;
|
||||
cm->cmsg_type = IPV6_PKTINFO;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(pi));
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
pi.ipi6_ifindex = rap->iface->index;
|
||||
memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
|
||||
|
||||
/* Hop limit */
|
||||
cm = CMSG_NXTHDR(&sndhdr, cm);
|
||||
cm->cmsg_level = IPPROTO_IPV6;
|
||||
cm->cmsg_type = IPV6_HOPLIMIT;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(hoplimit));
|
||||
memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit));
|
||||
|
||||
#ifdef DEBUG_NS
|
||||
syslog(LOG_INFO, "%s: sending IPv6 NS for %s",
|
||||
rap->iface->name, rap->sfrom);
|
||||
#endif
|
||||
if (sendmsg(sock, &sndhdr, 0) == -1) {
|
||||
syslog(LOG_ERR, "%s: %s: sendmsg: %m",
|
||||
rap->iface->name, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ms_to_tv(&tv, rap->retrans == 0 ? RETRANS_TIMER : rap->retrans);
|
||||
ms_to_tv(&rtv, MIN_RANDOM_FACTOR);
|
||||
timeradd(&tv, &rtv, &tv);
|
||||
rtv.tv_sec = 0;
|
||||
rtv.tv_usec = arc4random() % (MAX_RANDOM_FACTOR_U -MIN_RANDOM_FACTOR_U);
|
||||
timeradd(&tv, &rtv, &tv);
|
||||
eloop_timeout_add_tv(&tv, ipv6ns_proberouter, rap);
|
||||
|
||||
if (rap->nsprobes++ == 0)
|
||||
eloop_timeout_add_sec(DELAY_FIRST_PROBE_TIME,
|
||||
ipv6ns_unreachable, rap);
|
||||
}
|
||||
|
||||
void
|
||||
ipv6ns_cancelproberouter(struct ra *rap)
|
||||
{
|
||||
|
||||
eloop_timeout_delete(ipv6ns_proberouter, rap);
|
||||
eloop_timeout_delete(ipv6ns_unreachable, rap);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
ipv6ns_handledata(__unused void *arg)
|
||||
{
|
||||
ssize_t len;
|
||||
struct cmsghdr *cm;
|
||||
int hoplimit;
|
||||
struct in6_pktinfo pkt;
|
||||
struct icmp6_hdr *icp;
|
||||
struct interface *ifp;
|
||||
const char *sfrom;
|
||||
struct nd_neighbor_advert *nd_na;
|
||||
struct ra *rap;
|
||||
int is_router, is_solicited;
|
||||
#ifdef DEBUG_NS
|
||||
int found;
|
||||
#endif
|
||||
struct timeval tv;
|
||||
|
||||
#ifdef LISTEN_DAD
|
||||
struct dhcp6_state *d6state;
|
||||
struct ipv6_addr *ap;
|
||||
#endif
|
||||
|
||||
len = recvmsg(sock, &rcvhdr, 0);
|
||||
if (len == -1) {
|
||||
syslog(LOG_ERR, "recvmsg: %m");
|
||||
return;
|
||||
}
|
||||
sfrom = inet_ntop(AF_INET6, &from.sin6_addr,
|
||||
ntopbuf, INET6_ADDRSTRLEN);
|
||||
if ((size_t)len < sizeof(struct nd_neighbor_advert)) {
|
||||
syslog(LOG_ERR, "IPv6 NA packet too short from %s", sfrom);
|
||||
return;
|
||||
}
|
||||
|
||||
pkt.ipi6_ifindex = hoplimit = 0;
|
||||
for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvhdr);
|
||||
cm;
|
||||
cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvhdr, cm))
|
||||
{
|
||||
if (cm->cmsg_level != IPPROTO_IPV6)
|
||||
continue;
|
||||
switch(cm->cmsg_type) {
|
||||
case IPV6_PKTINFO:
|
||||
if (cm->cmsg_len == CMSG_LEN(sizeof(pkt)))
|
||||
memcpy(&pkt, CMSG_DATA(cm), sizeof(pkt));
|
||||
break;
|
||||
case IPV6_HOPLIMIT:
|
||||
if (cm->cmsg_len == CMSG_LEN(sizeof(int)))
|
||||
memcpy(&hoplimit, CMSG_DATA(cm), sizeof(int));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pkt.ipi6_ifindex == 0 || hoplimit != 255) {
|
||||
syslog(LOG_ERR,
|
||||
"IPv6 NA did not contain index or hop limit from %s",
|
||||
sfrom);
|
||||
return;
|
||||
}
|
||||
|
||||
icp = (struct icmp6_hdr *)rcvhdr.msg_iov[0].iov_base;
|
||||
if (icp->icmp6_type != ND_NEIGHBOR_ADVERT ||
|
||||
icp->icmp6_code != 0)
|
||||
{
|
||||
syslog(LOG_ERR, "invalid IPv6 type or code from %s", sfrom);
|
||||
return;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(ifp, ifaces, next) {
|
||||
if (ifp->index == (unsigned int)pkt.ipi6_ifindex)
|
||||
break;
|
||||
}
|
||||
if (ifp == NULL) {
|
||||
#ifdef DEBUG_NS
|
||||
syslog(LOG_DEBUG, "NA for unexpected interface from %s", sfrom);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
nd_na = (struct nd_neighbor_advert *)icp;
|
||||
is_router = nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER;
|
||||
is_solicited = nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED;
|
||||
|
||||
if (IN6_IS_ADDR_MULTICAST(&nd_na->nd_na_target)) {
|
||||
syslog(LOG_ERR, "%s: NA for multicast address from %s",
|
||||
ifp->name, sfrom);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NS
|
||||
found = 0;
|
||||
#endif
|
||||
TAILQ_FOREACH(rap, &ipv6_routers, next) {
|
||||
if (rap->iface != ifp)
|
||||
continue;
|
||||
if (memcmp(rap->from.s6_addr, nd_na->nd_na_target.s6_addr,
|
||||
sizeof(rap->from.s6_addr)) == 0)
|
||||
break;
|
||||
#ifdef LISTEN_DAD
|
||||
TAILQ_FOREACH(ap, &rap->addrs, next) {
|
||||
if (memcmp(ap->addr.s6_addr,
|
||||
nd_na->nd_na_target.s6_addr,
|
||||
sizeof(ap->addr.s6_addr)) == 0)
|
||||
{
|
||||
ap->flags |= IPV6_AF_DUPLICATED;
|
||||
if (ap->dadcallback)
|
||||
ap->dadcallback(ap);
|
||||
#ifdef DEBUG_NS
|
||||
found++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (rap == NULL) {
|
||||
#ifdef LISTEN_DAD
|
||||
d6state = D6_STATE(ifp);
|
||||
if (d6state) {
|
||||
TAILQ_FOREACH(ap, &d6state->addrs, next) {
|
||||
if (memcmp(ap->addr.s6_addr,
|
||||
nd_na->nd_na_target.s6_addr,
|
||||
sizeof(ap->addr.s6_addr)) == 0)
|
||||
{
|
||||
ap->flags |= IPV6_AF_DUPLICATED;
|
||||
if (ap->dadcallback)
|
||||
ap->dadcallback(ap);
|
||||
#ifdef DEBUG_NS
|
||||
found++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_NS
|
||||
if (found == 0)
|
||||
syslog(LOG_DEBUG, "%s: unexpected NA from %s",
|
||||
ifp->name, sfrom);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NS
|
||||
syslog(LOG_DEBUG, "%s: %sNA from %s",
|
||||
ifp->name, is_solicited ? "solicited " : "", sfrom);
|
||||
#endif
|
||||
|
||||
/* Node is no longer a router, so remove it from consideration */
|
||||
if (!is_router && !rap->expired) {
|
||||
syslog(LOG_INFO, "%s: %s is no longer a router",
|
||||
ifp->name, sfrom);
|
||||
rap->expired = 1;
|
||||
ipv6ns_cancelproberouter(rap);
|
||||
ipv6_buildroutes();
|
||||
script_runreason(ifp, "ROUTERADVERT");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_solicited && is_router && rap->lifetime) {
|
||||
if (rap->expired) {
|
||||
rap->expired = 0;
|
||||
syslog(LOG_INFO, "%s: %s is reachable again",
|
||||
ifp->name, sfrom);
|
||||
ipv6_buildroutes();
|
||||
script_runreason(rap->iface, "ROUTERADVERT"); /* XXX */
|
||||
}
|
||||
rap->nsprobes = 0;
|
||||
if (rap->reachable) {
|
||||
ms_to_tv(&tv, rap->reachable);
|
||||
} else {
|
||||
tv.tv_sec = REACHABLE_TIME;
|
||||
tv.tv_usec = 0;
|
||||
}
|
||||
eloop_timeout_add_tv(&tv, ipv6ns_proberouter, rap);
|
||||
eloop_timeout_delete(ipv6ns_unreachable, rap);
|
||||
}
|
||||
}
|
51
external/bsd/dhcpcd/dist/ipv6ns.h
vendored
51
external/bsd/dhcpcd/dist/ipv6ns.h
vendored
@ -1,51 +0,0 @@
|
||||
/* $NetBSD: ipv6ns.h,v 1.1.1.3 2013/06/21 19:33:08 roy Exp $ */
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef IPV6NS_H
|
||||
#define IPV6NS_H
|
||||
|
||||
#include "dhcpcd.h"
|
||||
#include "ipv6rs.h"
|
||||
|
||||
#define MAX_REACHABLE_TIME 3600 /* seconds */
|
||||
#define REACHABLE_TIME 30 /* seconds */
|
||||
#define RETRANS_TIMER 1000 /* milliseconds */
|
||||
#define DELAY_FIRST_PROBE_TIME 5 /* seconds */
|
||||
|
||||
void ipv6ns_probeaddr(void *);
|
||||
ssize_t ipv6ns_probeaddrs(struct ipv6_addrhead *);
|
||||
void ipv6ns_proberouter(void *);
|
||||
void ipv6ns_cancelproberouter(struct ra *);
|
||||
|
||||
#ifdef LISTEN_DAD
|
||||
void ipv6ns_cancelprobeaddr(struct ipv6_addr *);
|
||||
#else
|
||||
#define ipv6ns_cancelprobeaddr(a)
|
||||
#endif
|
||||
#endif
|
1277
external/bsd/dhcpcd/dist/ipv6rs.c
vendored
1277
external/bsd/dhcpcd/dist/ipv6rs.c
vendored
File diff suppressed because it is too large
Load Diff
100
external/bsd/dhcpcd/dist/ipv6rs.h
vendored
100
external/bsd/dhcpcd/dist/ipv6rs.h
vendored
@ -1,100 +0,0 @@
|
||||
/* $NetBSD: ipv6rs.h,v 1.1.1.5 2013/06/21 19:33:08 roy Exp $ */
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright (c) 2006-2013 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef IPV6RS_H
|
||||
#define IPV6RS_H
|
||||
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "dhcpcd.h"
|
||||
#include "ipv6.h"
|
||||
|
||||
struct ra_opt {
|
||||
TAILQ_ENTRY(ra_opt) next;
|
||||
uint8_t type;
|
||||
struct timeval expire;
|
||||
char *option;
|
||||
};
|
||||
|
||||
struct ra {
|
||||
TAILQ_ENTRY(ra) next;
|
||||
struct interface *iface;
|
||||
struct in6_addr from;
|
||||
char sfrom[INET6_ADDRSTRLEN];
|
||||
unsigned char *data;
|
||||
ssize_t data_len;
|
||||
struct timeval received;
|
||||
unsigned char flags;
|
||||
uint32_t lifetime;
|
||||
uint32_t reachable;
|
||||
uint32_t retrans;
|
||||
uint32_t mtu;
|
||||
struct ipv6_addrhead addrs;
|
||||
TAILQ_HEAD(, ra_opt) options;
|
||||
|
||||
unsigned char *ns;
|
||||
size_t nslen;
|
||||
int nsprobes;
|
||||
|
||||
int expired;
|
||||
};
|
||||
|
||||
extern TAILQ_HEAD(rahead, ra) ipv6_routers;
|
||||
|
||||
struct rs_state {
|
||||
unsigned char *rs;
|
||||
size_t rslen;
|
||||
int rsprobes;
|
||||
};
|
||||
|
||||
#define RS_STATE(a) ((struct rs_state *)(ifp)->if_data[IF_DATA_IPV6RS])
|
||||
|
||||
#ifdef INET6
|
||||
int ipv6rs_start(struct interface *);
|
||||
ssize_t ipv6rs_env(char **, const char *, const struct interface *);
|
||||
const struct ipv6_addr * ipv6rs_findprefix(const struct ipv6_addr *);
|
||||
int ipv6rs_addrexists(const struct ipv6_addr *);
|
||||
void ipv6rs_freedrop_ra(struct ra *, int);
|
||||
#define ipv6rs_free_ra(ra) ipv6rs_freedrop_ra((ra), 0)
|
||||
#define ipv6rs_drop_ra(ra) ipv6rs_freedrop_ra((ra), 1)
|
||||
ssize_t ipv6rs_free(struct interface *);
|
||||
void ipv6rs_expire(void *arg);
|
||||
int ipv6rs_has_ra(const struct interface *);
|
||||
void ipv6rs_handleifa(int, const char *, const struct in6_addr *, int);
|
||||
void ipv6rs_drop(struct interface *);
|
||||
#else
|
||||
#define ipv6rs_start(a) {}
|
||||
#define ipv6rs_free(a)
|
||||
#define ipv6rs_has_ra(a) 0
|
||||
#define ipv6rs_drop(a)
|
||||
#endif
|
||||
|
||||
#endif
|
45
external/bsd/dhcpcd/dist/net.c
vendored
45
external/bsd/dhcpcd/dist/net.c
vendored
@ -1,5 +1,5 @@
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: net.c,v 1.2 2013/09/11 18:50:00 drochner Exp $");
|
||||
__RCSID("$NetBSD: net.c,v 1.3 2013/09/20 10:56:32 roy Exp $");
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
@ -70,10 +70,12 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "dev.h"
|
||||
#include "dhcp.h"
|
||||
#include "dhcp6.h"
|
||||
#include "if-options.h"
|
||||
#include "ipv6rs.h"
|
||||
#include "ipv4.h"
|
||||
#include "ipv6nd.h"
|
||||
#include "net.h"
|
||||
|
||||
int socket_afnet = -1;
|
||||
@ -141,10 +143,11 @@ free_interface(struct interface *ifp)
|
||||
|
||||
if (ifp == NULL)
|
||||
return;
|
||||
ipv4_free(ifp);
|
||||
dhcp_free(ifp);
|
||||
ipv6_free(ifp);
|
||||
dhcp6_free(ifp);
|
||||
ipv6rs_free(ifp);
|
||||
ipv6nd_free(ifp);
|
||||
free_options(ifp->options);
|
||||
free(ifp);
|
||||
}
|
||||
@ -226,6 +229,10 @@ discover_interfaces(int argc, char * const *argv)
|
||||
#ifdef __linux__
|
||||
char ifn[IF_NAMESIZE];
|
||||
#endif
|
||||
#ifdef INET
|
||||
const struct sockaddr_in *addr;
|
||||
const struct sockaddr_in *net;
|
||||
const struct sockaddr_in *dst;
|
||||
#ifdef INET6
|
||||
const struct sockaddr_in6 *sin6;
|
||||
int ifa_flags;
|
||||
@ -264,6 +271,10 @@ discover_interfaces(int argc, char * const *argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Ensure that the interface name has settled */
|
||||
if (!dev_initialized(ifa->ifa_name))
|
||||
continue;
|
||||
|
||||
/* It's possible for an interface to have >1 AF_LINK.
|
||||
* For our purposes, we use the first one. */
|
||||
TAILQ_FOREACH(ifp, ifs, next) {
|
||||
@ -444,11 +455,29 @@ discover_interfaces(int argc, char * const *argv)
|
||||
TAILQ_INSERT_TAIL(ifs, ifp, next);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr != NULL &&
|
||||
ifa->ifa_addr->sa_family == AF_INET6)
|
||||
{
|
||||
if (ifa->ifa_addr == NULL)
|
||||
continue;
|
||||
switch(ifa->ifa_addr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
addr = (const struct sockaddr_in *)
|
||||
(void *)ifa->ifa_addr;
|
||||
net = (const struct sockaddr_in *)
|
||||
(void *)ifa->ifa_netmask;
|
||||
if (ifa->ifa_flags & IFF_POINTOPOINT)
|
||||
dst = (const struct sockaddr_in *)
|
||||
(void *)ifa->ifa_dstaddr;
|
||||
else
|
||||
dst = NULL;
|
||||
ipv4_handleifa(RTM_NEWADDR, ifs, ifa->ifa_name,
|
||||
&addr->sin_addr,
|
||||
&net->sin_addr,
|
||||
dst ? &dst->sin_addr : NULL);
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6 = (const struct sockaddr_in6 *)
|
||||
(void *)ifa->ifa_addr;
|
||||
ifa_flags = in6_addr_flags(ifa->ifa_name,
|
||||
@ -457,6 +486,8 @@ discover_interfaces(int argc, char * const *argv)
|
||||
ipv6_handleifa(RTM_NEWADDR, ifs,
|
||||
ifa->ifa_name,
|
||||
&sin6->sin6_addr, ifa_flags);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user