Apply pserialize and psref to struct ifaddr and its variants
This change makes struct ifaddr and its variants (in_ifaddr and in6_ifaddr) MP-safe by using pserialize and psref. At this moment, pserialize_perform and psref_target_destroy are disabled because (1) we don't need them because of softnet_lock (2) they cause a deadlock because of softnet_lock. So we'll enable them when we remove softnet_lock in the future.
This commit is contained in:
parent
74fbff1628
commit
a403cbd4f5
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vmt.c,v 1.13 2016/07/07 09:32:01 ozaki-r Exp $ */
|
||||
/* $NetBSD: vmt.c,v 1.14 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
/* $OpenBSD: vmt.c,v 1.11 2011/01/27 21:29:25 dtucker Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -801,15 +801,16 @@ vmt_tclo_tick(void *xarg)
|
|||
sc->sc_rpc_error = 1;
|
||||
}
|
||||
} else if (strcmp(sc->sc_rpc_buf, "Set_Option broadcastIP 1") == 0) {
|
||||
struct ifaddr *iface_addr = NULL;
|
||||
struct ifnet *iface;
|
||||
struct sockaddr_in *guest_ip;
|
||||
int s;
|
||||
struct psref psref;
|
||||
|
||||
/* find first available ipv4 address */
|
||||
guest_ip = NULL;
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(iface) {
|
||||
struct ifaddr *iface_addr;
|
||||
|
||||
/* skip loopback */
|
||||
if (strncmp(iface->if_xname, "lo", 2) == 0 &&
|
||||
|
@ -823,6 +824,7 @@ vmt_tclo_tick(void *xarg)
|
|||
}
|
||||
|
||||
guest_ip = satosin(iface_addr->ifa_addr);
|
||||
ifa_acquire(iface_addr, &psref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -834,6 +836,7 @@ vmt_tclo_tick(void *xarg)
|
|||
device_printf(sc->sc_dev, "unable to send guest IP address\n");
|
||||
sc->sc_rpc_error = 1;
|
||||
}
|
||||
ifa_release(iface_addr, &psref);
|
||||
|
||||
if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
|
||||
device_printf(sc->sc_dev, "error sending broadcastIP response\n");
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/* $NetBSD: uipc_syscalls_40.c,v 1.11 2016/07/07 09:32:02 ozaki-r Exp $ */
|
||||
/* $NetBSD: uipc_syscalls_40.c,v 1.12 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/* written by Pavel Cahyna, 2006. Public domain. */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.11 2016/07/07 09:32:02 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.12 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
/*
|
||||
* System call interface to the socket abstraction.
|
||||
|
@ -34,7 +34,6 @@ compat_ifconf(u_long cmd, void *data)
|
|||
{
|
||||
struct oifconf *ifc = data;
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
struct oifreq ifr, *ifrp = NULL;
|
||||
int space = 0, error = 0;
|
||||
const int sz = (int)sizeof(ifr);
|
||||
|
@ -51,8 +50,9 @@ compat_ifconf(u_long cmd, void *data)
|
|||
bound = curlwp_bind();
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
struct ifaddr *ifa;
|
||||
|
||||
psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
(void)strncpy(ifr.ifr_name, ifp->if_xname,
|
||||
sizeof(ifr.ifr_name));
|
||||
|
@ -74,6 +74,10 @@ compat_ifconf(u_long cmd, void *data)
|
|||
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct sockaddr *sa = ifa->ifa_addr;
|
||||
struct psref psref_ifa;
|
||||
|
||||
ifa_acquire(ifa, &psref_ifa);
|
||||
pserialize_read_exit(s);
|
||||
#ifdef COMPAT_OSOCK
|
||||
if (cmd == OOSIOCGIFCONF) {
|
||||
struct osockaddr *osa =
|
||||
|
@ -81,8 +85,11 @@ compat_ifconf(u_long cmd, void *data)
|
|||
/*
|
||||
* If it does not fit, we don't bother with it
|
||||
*/
|
||||
if (sa->sa_len > sizeof(*osa))
|
||||
if (sa->sa_len > sizeof(*osa)) {
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
continue;
|
||||
}
|
||||
memcpy(&ifr.ifr_addr, sa, sa->sa_len);
|
||||
osa->sa_family = sa->sa_family;
|
||||
if (space >= sz) {
|
||||
|
@ -112,12 +119,13 @@ compat_ifconf(u_long cmd, void *data)
|
|||
(char *)&ifrp->ifr_addr);
|
||||
}
|
||||
}
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
if (error != 0)
|
||||
goto release_exit;
|
||||
space -= sz;
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
@ -130,6 +138,7 @@ compat_ifconf(u_long cmd, void *data)
|
|||
return (0);
|
||||
|
||||
release_exit:
|
||||
pserialize_read_exit(s);
|
||||
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_socket.c,v 1.131 2016/07/07 09:32:02 ozaki-r Exp $ */
|
||||
/* $NetBSD: linux_socket.c,v 1.132 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.131 2016/07/07 09:32:02 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.132 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_inet.h"
|
||||
|
@ -1117,7 +1117,6 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
struct linux_ifreq ifr, *ifrp = NULL;
|
||||
struct linux_ifconf ifc;
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr *sa;
|
||||
struct osockaddr *osa;
|
||||
int space = 0, error;
|
||||
|
@ -1140,8 +1139,8 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
bound = curlwp_bind();
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
struct ifaddr *ifa;
|
||||
psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
(void)strncpy(ifr.ifr_name, ifp->if_xname,
|
||||
sizeof(ifr.ifr_name));
|
||||
|
@ -1151,23 +1150,32 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
}
|
||||
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct psref psref_ifa;
|
||||
ifa_acquire(ifa, &psref_ifa);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
sa = ifa->ifa_addr;
|
||||
if (sa->sa_family != AF_INET ||
|
||||
sa->sa_len > sizeof(*osa))
|
||||
continue;
|
||||
goto next;
|
||||
memcpy(&ifr.ifr_addr, sa, sa->sa_len);
|
||||
osa = (struct osockaddr *)&ifr.ifr_addr;
|
||||
osa->sa_family = sa->sa_family;
|
||||
if (space >= sz) {
|
||||
error = copyout(&ifr, ifrp, sz);
|
||||
if (error != 0)
|
||||
if (error != 0) {
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
goto release_exit;
|
||||
}
|
||||
ifrp++;
|
||||
}
|
||||
space -= sz;
|
||||
next:
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
@ -1181,6 +1189,7 @@ linux_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
return copyout(&ifc, data, sizeof(ifc));
|
||||
|
||||
release_exit:
|
||||
pserialize_read_exit(s);
|
||||
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux32_socket.c,v 1.25 2016/07/07 09:32:02 ozaki-r Exp $ */
|
||||
/* $NetBSD: linux32_socket.c,v 1.26 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.25 2016/07/07 09:32:02 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.26 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -418,7 +418,6 @@ linux32_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
struct linux32_ifreq ifr, *ifrp = NULL;
|
||||
struct linux32_ifconf ifc;
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr *sa;
|
||||
struct osockaddr *osa;
|
||||
int space = 0, error;
|
||||
|
@ -441,8 +440,8 @@ linux32_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
bound = curlwp_bind();
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
struct ifaddr *ifa;
|
||||
psref_acquire(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
(void)strncpy(ifr.ifr_name, ifp->if_xname,
|
||||
sizeof(ifr.ifr_name));
|
||||
|
@ -452,23 +451,32 @@ linux32_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
}
|
||||
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct psref psref_ifa;
|
||||
ifa_acquire(ifa, &psref_ifa);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
sa = ifa->ifa_addr;
|
||||
if (sa->sa_family != AF_INET ||
|
||||
sa->sa_len > sizeof(*osa))
|
||||
continue;
|
||||
goto next;
|
||||
memcpy(&ifr.ifr_addr, sa, sa->sa_len);
|
||||
osa = (struct osockaddr *)&ifr.ifr_addr;
|
||||
osa->sa_family = sa->sa_family;
|
||||
if (space >= sz) {
|
||||
error = copyout(&ifr, ifrp, sz);
|
||||
if (error != 0)
|
||||
if (error != 0) {
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
goto release_exit;
|
||||
}
|
||||
ifrp++;
|
||||
}
|
||||
space -= sz;
|
||||
next:
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
@ -482,6 +490,7 @@ linux32_getifconf(struct lwp *l, register_t *retval, void *data)
|
|||
return copyout(&ifc, data, sizeof(ifc));
|
||||
|
||||
release_exit:
|
||||
pserialize_read_exit(s);
|
||||
psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
|
|
238
sys/net/if.c
238
sys/net/if.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if.c,v 1.356 2016/07/22 07:13:56 knakahara Exp $ */
|
||||
/* $NetBSD: if.c,v 1.357 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -90,7 +90,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.356 2016/07/22 07:13:56 knakahara Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.357 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#if defined(_KERNEL_OPT)
|
||||
#include "opt_inet.h"
|
||||
|
@ -183,6 +183,8 @@ static kmutex_t if_clone_mtx;
|
|||
struct ifnet *lo0ifp;
|
||||
int ifqmaxlen = IFQ_MAXLEN;
|
||||
|
||||
struct psref_class *ifa_psref_class __read_mostly;
|
||||
|
||||
static int if_rt_walktree(struct rtentry *, void *);
|
||||
|
||||
static struct if_clone *if_clone_lookup(const char *, int *);
|
||||
|
@ -281,11 +283,14 @@ void
|
|||
ifinit1(void)
|
||||
{
|
||||
mutex_init(&if_clone_mtx, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
TAILQ_INIT(&ifnet_list);
|
||||
mutex_init(&ifnet_mtx, MUTEX_DEFAULT, IPL_NONE);
|
||||
ifnet_psz = pserialize_create();
|
||||
ifnet_psref_class = psref_class_create("ifnet", IPL_SOFTNET);
|
||||
ifa_psref_class = psref_class_create("ifa", IPL_SOFTNET);
|
||||
PSLIST_INIT(&ifnet_pslist);
|
||||
|
||||
if_indexlim = 8;
|
||||
|
||||
if_pfil = pfil_head_create(PFIL_TYPE_IFNET, NULL);
|
||||
|
@ -427,6 +432,7 @@ if_dl_create(const struct ifnet *ifp, const struct sockaddr_dl **sdlp)
|
|||
ifa->ifa_rtrequest = link_rtrequest;
|
||||
ifa->ifa_addr = (struct sockaddr *)sdl;
|
||||
ifa->ifa_netmask = (struct sockaddr *)mask;
|
||||
ifa_psref_init(ifa);
|
||||
|
||||
*sdlp = sdl;
|
||||
|
||||
|
@ -486,20 +492,34 @@ if_deactivate_sadl(struct ifnet *ifp)
|
|||
}
|
||||
|
||||
void
|
||||
if_activate_sadl(struct ifnet *ifp, struct ifaddr *ifa,
|
||||
if_activate_sadl(struct ifnet *ifp, struct ifaddr *ifa0,
|
||||
const struct sockaddr_dl *sdl)
|
||||
{
|
||||
int s;
|
||||
int s, ss;
|
||||
struct ifaddr *ifa;
|
||||
int bound = curlwp_bind();
|
||||
|
||||
s = splnet();
|
||||
|
||||
if_deactivate_sadl(ifp);
|
||||
|
||||
if_sadl_setrefs(ifp, ifa);
|
||||
IFADDR_READER_FOREACH(ifa, ifp)
|
||||
if_sadl_setrefs(ifp, ifa0);
|
||||
|
||||
ss = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct psref psref;
|
||||
ifa_acquire(ifa, &psref);
|
||||
pserialize_read_exit(ss);
|
||||
|
||||
rtinit(ifa, RTM_LLINFO_UPD, 0);
|
||||
|
||||
ss = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
pserialize_read_exit(ss);
|
||||
|
||||
splx(s);
|
||||
curlwp_bindx(bound);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1023,13 +1043,20 @@ void
|
|||
if_purgeaddrs(struct ifnet *ifp, int family, void (*purgeaddr)(struct ifaddr *))
|
||||
{
|
||||
struct ifaddr *ifa, *nifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
for (ifa = IFADDR_READER_FIRST(ifp); ifa; ifa = nifa) {
|
||||
nifa = IFADDR_READER_NEXT(ifa);
|
||||
if (ifa->ifa_addr->sa_family != family)
|
||||
continue;
|
||||
pserialize_read_exit(s);
|
||||
|
||||
(*purgeaddr)(ifa);
|
||||
|
||||
s = pserialize_read_enter();
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
#ifdef IFAREF_DEBUG
|
||||
|
@ -1134,6 +1161,10 @@ if_detach(struct ifnet *ifp)
|
|||
pserialize_perform(ifnet_psz);
|
||||
IFNET_UNLOCK();
|
||||
|
||||
/* Wait for all readers to drain before freeing. */
|
||||
psref_target_destroy(&ifp->if_psref, ifnet_psref_class);
|
||||
PSLIST_ENTRY_DESTROY(ifp, if_pslist_entry);
|
||||
|
||||
mutex_obj_free(ifp->if_ioctl_lock);
|
||||
ifp->if_ioctl_lock = NULL;
|
||||
|
||||
|
@ -1178,6 +1209,10 @@ if_detach(struct ifnet *ifp)
|
|||
* least one ifaddr.
|
||||
*/
|
||||
again:
|
||||
/*
|
||||
* At this point, no other one tries to remove ifa in the list,
|
||||
* so we don't need to take a lock or psref.
|
||||
*/
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
family = ifa->ifa_addr->sa_family;
|
||||
#ifdef IFAREF_DEBUG
|
||||
|
@ -1303,10 +1338,6 @@ again:
|
|||
xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
|
||||
xc_wait(xc);
|
||||
|
||||
/* Wait for all readers to drain before freeing. */
|
||||
psref_target_destroy(&ifp->if_psref, ifnet_psref_class);
|
||||
PSLIST_ENTRY_DESTROY(ifp, if_pslist_entry);
|
||||
|
||||
if (ifp->if_percpuq != NULL) {
|
||||
if_percpuq_destroy(ifp->if_percpuq);
|
||||
ifp->if_percpuq = NULL;
|
||||
|
@ -1542,6 +1573,13 @@ if_clone_list(int buf_count, char *buffer, int *total)
|
|||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
ifa_psref_init(struct ifaddr *ifa)
|
||||
{
|
||||
|
||||
psref_target_init(&ifa->ifa_psref, ifa_psref_class);
|
||||
}
|
||||
|
||||
void
|
||||
ifaref(struct ifaddr *ifa)
|
||||
{
|
||||
|
@ -1562,24 +1600,63 @@ ifafree(struct ifaddr *ifa)
|
|||
void
|
||||
ifa_insert(struct ifnet *ifp, struct ifaddr *ifa)
|
||||
{
|
||||
|
||||
ifa->ifa_ifp = ifp;
|
||||
|
||||
IFNET_LOCK();
|
||||
TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);
|
||||
IFADDR_ENTRY_INIT(ifa);
|
||||
IFADDR_WRITER_INSERT_TAIL(ifp, ifa);
|
||||
IFNET_UNLOCK();
|
||||
|
||||
ifaref(ifa);
|
||||
}
|
||||
|
||||
void
|
||||
ifa_remove(struct ifnet *ifp, struct ifaddr *ifa)
|
||||
{
|
||||
|
||||
KASSERT(ifa->ifa_ifp == ifp);
|
||||
|
||||
IFNET_LOCK();
|
||||
TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
|
||||
IFADDR_WRITER_REMOVE(ifa);
|
||||
/* TODO psref_target_destroy */
|
||||
IFADDR_ENTRY_DESTROY(ifa);
|
||||
#if notyet
|
||||
pserialize_perform(ifnet_psz);
|
||||
#endif
|
||||
IFNET_UNLOCK();
|
||||
|
||||
#if notyet
|
||||
psref_target_destroy(&ifa->ifa_psref, ifa_psref_class);
|
||||
#endif
|
||||
ifafree(ifa);
|
||||
}
|
||||
|
||||
void
|
||||
ifa_acquire(struct ifaddr *ifa, struct psref *psref)
|
||||
{
|
||||
|
||||
psref_acquire(psref, &ifa->ifa_psref, ifa_psref_class);
|
||||
}
|
||||
|
||||
void
|
||||
ifa_release(struct ifaddr *ifa, struct psref *psref)
|
||||
{
|
||||
|
||||
if (ifa == NULL)
|
||||
return;
|
||||
|
||||
psref_release(psref, &ifa->ifa_psref, ifa_psref_class);
|
||||
}
|
||||
|
||||
bool
|
||||
ifa_held(struct ifaddr *ifa)
|
||||
{
|
||||
|
||||
return psref_held(&ifa->ifa_psref, ifa_psref_class);
|
||||
}
|
||||
|
||||
static inline int
|
||||
equal(const struct sockaddr *sa1, const struct sockaddr *sa2)
|
||||
{
|
||||
|
@ -1595,9 +1672,7 @@ ifa_ifwithaddr(const struct sockaddr *addr)
|
|||
{
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
if (if_is_deactivated(ifp))
|
||||
continue;
|
||||
|
@ -1614,10 +1689,23 @@ ifa_ifwithaddr(const struct sockaddr *addr)
|
|||
return ifa;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ifaddr *
|
||||
ifa_ifwithaddr_psref(const struct sockaddr *addr, struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
ifa = ifa_ifwithaddr(addr);
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ifa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate the point to point interface with a given destination address.
|
||||
*/
|
||||
|
@ -1627,9 +1715,7 @@ ifa_ifwithdstaddr(const struct sockaddr *addr)
|
|||
{
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
if (if_is_deactivated(ifp))
|
||||
continue;
|
||||
|
@ -1643,10 +1729,25 @@ ifa_ifwithdstaddr(const struct sockaddr *addr)
|
|||
return ifa;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ifaddr *
|
||||
ifa_ifwithdstaddr_psref(const struct sockaddr *addr, struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithdstaddr(addr);
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ifa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an interface on a specific network. If many, choice
|
||||
* is most specific found.
|
||||
|
@ -1655,12 +1756,10 @@ struct ifaddr *
|
|||
ifa_ifwithnet(const struct sockaddr *addr)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
struct ifaddr *ifa;
|
||||
struct ifaddr *ifa, *ifa_maybe = NULL;
|
||||
const struct sockaddr_dl *sdl;
|
||||
struct ifaddr *ifa_maybe = 0;
|
||||
u_int af = addr->sa_family;
|
||||
const char *addr_data = addr->sa_data, *cplim;
|
||||
int s;
|
||||
|
||||
if (af == AF_LINK) {
|
||||
sdl = satocsdl(addr);
|
||||
|
@ -1674,7 +1773,6 @@ ifa_ifwithnet(const struct sockaddr *addr)
|
|||
if (af == AF_APPLETALK) {
|
||||
const struct sockaddr_at *sat, *sat2;
|
||||
sat = (const struct sockaddr_at *)addr;
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
if (if_is_deactivated(ifp))
|
||||
continue;
|
||||
|
@ -1689,11 +1787,9 @@ ifa_ifwithnet(const struct sockaddr *addr)
|
|||
ifa_maybe = ifa;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
return ifa_maybe;
|
||||
}
|
||||
#endif
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
if (if_is_deactivated(ifp))
|
||||
continue;
|
||||
|
@ -1720,10 +1816,24 @@ ifa_ifwithnet(const struct sockaddr *addr)
|
|||
ifa_maybe = ifa;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
return ifa_maybe;
|
||||
}
|
||||
|
||||
struct ifaddr *
|
||||
ifa_ifwithnet_psref(const struct sockaddr *addr, struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithnet(addr);
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ifa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the interface of the addresss.
|
||||
*/
|
||||
|
@ -1738,6 +1848,21 @@ ifa_ifwithladdr(const struct sockaddr *addr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct ifaddr *
|
||||
ifa_ifwithladdr_psref(const struct sockaddr *addr, struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithladdr(addr);
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ifa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an interface using a specific address family
|
||||
*/
|
||||
|
@ -1806,6 +1931,22 @@ ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp)
|
|||
return ifa_maybe;
|
||||
}
|
||||
|
||||
struct ifaddr *
|
||||
ifaof_ifpforaddr_psref(const struct sockaddr *addr, struct ifnet *ifp,
|
||||
struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifaof_ifpforaddr(addr, ifp);
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ifa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default action when installing a route with a Link Level gateway.
|
||||
* Lookup an appropriate real ifa to point to.
|
||||
|
@ -1817,14 +1958,16 @@ link_rtrequest(int cmd, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
struct ifaddr *ifa;
|
||||
const struct sockaddr *dst;
|
||||
struct ifnet *ifp;
|
||||
struct psref psref;
|
||||
|
||||
if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL ||
|
||||
(ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL)
|
||||
return;
|
||||
if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
|
||||
if ((ifa = ifaof_ifpforaddr_psref(dst, ifp, &psref)) != NULL) {
|
||||
rt_replace_ifa(rt, ifa);
|
||||
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
|
||||
ifa->ifa_rtrequest(cmd, rt, info);
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2026,6 +2169,7 @@ p2p_rtrequest(int req, struct rtentry *rt,
|
|||
{
|
||||
struct ifnet *ifp = rt->rt_ifp;
|
||||
struct ifaddr *ifa, *lo0ifa;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
switch (req) {
|
||||
case RTM_ADD:
|
||||
|
@ -2064,6 +2208,7 @@ p2p_rtrequest(int req, struct rtentry *rt,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2076,11 +2221,26 @@ if_down(struct ifnet *ifp)
|
|||
{
|
||||
struct ifaddr *ifa;
|
||||
struct domain *dp;
|
||||
int s, bound;
|
||||
struct psref psref;
|
||||
|
||||
ifp->if_flags &= ~IFF_UP;
|
||||
nanotime(&ifp->if_lastchange);
|
||||
IFADDR_READER_FOREACH(ifa, ifp)
|
||||
|
||||
bound = curlwp_bind();
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
ifa_acquire(ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
IFQ_PURGE(&ifp->if_snd);
|
||||
#if NCARP > 0
|
||||
if (ifp->if_carp)
|
||||
|
@ -2296,7 +2456,12 @@ if_put(const struct ifnet *ifp, struct psref *psref)
|
|||
ifnet_t *
|
||||
if_byindex(u_int idx)
|
||||
{
|
||||
return (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL;
|
||||
ifnet_t *ifp;
|
||||
|
||||
ifp = (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL;
|
||||
if (ifp != NULL && if_is_deactivated(ifp))
|
||||
ifp = NULL;
|
||||
return ifp;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2312,6 +2477,8 @@ if_get_byindex(u_int idx, struct psref *psref)
|
|||
|
||||
s = pserialize_read_enter();
|
||||
ifp = (__predict_true(idx < if_indexlim)) ? ifindex2ifnet[idx] : NULL;
|
||||
if (ifp != NULL && if_is_deactivated(ifp))
|
||||
ifp = NULL;
|
||||
if (__predict_true(ifp != NULL))
|
||||
psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);
|
||||
pserialize_read_exit(s);
|
||||
|
@ -2503,6 +2670,7 @@ ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
struct sockaddr sa;
|
||||
struct sockaddr_storage ss;
|
||||
} u, v;
|
||||
int s, error = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDRPREF:
|
||||
|
@ -2531,6 +2699,7 @@ ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
|
||||
sockaddr_externalize(&v.sa, sizeof(v.ss), sa);
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family != sa->sa_family)
|
||||
continue;
|
||||
|
@ -2538,22 +2707,27 @@ ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
if (sockaddr_cmp(&u.sa, &v.sa) == 0)
|
||||
break;
|
||||
}
|
||||
if (ifa == NULL)
|
||||
return EADDRNOTAVAIL;
|
||||
if (ifa == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCSIFADDRPREF:
|
||||
ifa->ifa_preference = ifap->ifap_preference;
|
||||
return 0;
|
||||
goto out;
|
||||
case SIOCGIFADDRPREF:
|
||||
/* fill in the if_laddrreq structure */
|
||||
(void)sockaddr_copy(sstosa(&ifap->ifap_addr),
|
||||
sizeof(ifap->ifap_addr), ifa->ifa_addr);
|
||||
ifap->ifap_preference = ifa->ifa_preference;
|
||||
return 0;
|
||||
goto out;
|
||||
default:
|
||||
return EOPNOTSUPP;
|
||||
error = EOPNOTSUPP;
|
||||
}
|
||||
out:
|
||||
pserialize_read_exit(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
19
sys/net/if.h
19
sys/net/if.h
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if.h,v 1.223 2016/08/01 02:50:03 ozaki-r Exp $ */
|
||||
/* $NetBSD: if.h,v 1.224 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -598,6 +598,7 @@ struct ifaddr {
|
|||
int16_t ifa_preference; /* preference level for this address */
|
||||
#ifdef _KERNEL
|
||||
struct pslist_entry ifa_pslist_entry;
|
||||
struct psref_target ifa_psref;
|
||||
#endif
|
||||
};
|
||||
#define IFA_ROUTE RTF_UP /* (0x01) route installed */
|
||||
|
@ -984,17 +985,29 @@ void
|
|||
void ifa_insert(struct ifnet *, struct ifaddr *);
|
||||
void ifa_remove(struct ifnet *, struct ifaddr *);
|
||||
|
||||
void ifa_psref_init(struct ifaddr *);
|
||||
void ifa_acquire(struct ifaddr *, struct psref *);
|
||||
void ifa_release(struct ifaddr *, struct psref *);
|
||||
bool ifa_held(struct ifaddr *);
|
||||
|
||||
void ifaref(struct ifaddr *);
|
||||
void ifafree(struct ifaddr *);
|
||||
|
||||
struct ifaddr *ifa_ifwithaddr(const struct sockaddr *);
|
||||
struct ifaddr *ifa_ifwithaddr_psref(const struct sockaddr *, struct psref *);
|
||||
struct ifaddr *ifa_ifwithaf(int);
|
||||
struct ifaddr *ifa_ifwithdstaddr(const struct sockaddr *);
|
||||
struct ifaddr *ifa_ifwithdstaddr_psref(const struct sockaddr *,
|
||||
struct psref *);
|
||||
struct ifaddr *ifa_ifwithnet(const struct sockaddr *);
|
||||
struct ifaddr *ifa_ifwithnet_psref(const struct sockaddr *, struct psref *);
|
||||
struct ifaddr *ifa_ifwithladdr(const struct sockaddr *);
|
||||
struct ifaddr *ifa_ifwithroute(int, const struct sockaddr *,
|
||||
const struct sockaddr *);
|
||||
struct ifaddr *ifa_ifwithladdr_psref(const struct sockaddr *, struct psref *);
|
||||
struct ifaddr *ifa_ifwithroute_psref(int, const struct sockaddr *,
|
||||
const struct sockaddr *, struct psref *);
|
||||
struct ifaddr *ifaof_ifpforaddr(const struct sockaddr *, struct ifnet *);
|
||||
struct ifaddr *ifaof_ifpforaddr_psref(const struct sockaddr *, struct ifnet *,
|
||||
struct psref *);
|
||||
void link_rtrequest(int, struct rtentry *, const struct rt_addrinfo *);
|
||||
void p2p_rtrequest(int, struct rtentry *, const struct rt_addrinfo *);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_ethersubr.c,v 1.226 2016/07/25 23:46:09 rjs Exp $ */
|
||||
/* $NetBSD: if_ethersubr.c,v 1.227 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -61,7 +61,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.226 2016/07/25 23:46:09 rjs Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.227 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -218,12 +218,17 @@ ether_output(struct ifnet * const ifp0, struct mbuf * const m0,
|
|||
#if NCARP > 0
|
||||
if (ifp->if_type == IFT_CARP) {
|
||||
struct ifaddr *ifa;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
/* loop back if this is going to the carp interface */
|
||||
if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
|
||||
(ifa = ifa_ifwithaddr(dst)) != NULL &&
|
||||
ifa->ifa_ifp == ifp0)
|
||||
return looutput(ifp0, m, dst, rt);
|
||||
(ifa = ifa_ifwithaddr(dst)) != NULL) {
|
||||
if (ifa->ifa_ifp == ifp0) {
|
||||
pserialize_read_exit(s);
|
||||
return looutput(ifp0, m, dst, rt);
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
ifp = ifp->if_carpdev;
|
||||
/* ac = (struct arpcom *)ifp; */
|
||||
|
@ -298,7 +303,10 @@ ether_output(struct ifnet * const ifp0, struct mbuf * const m0,
|
|||
break;
|
||||
#endif
|
||||
#ifdef NETATALK
|
||||
case AF_APPLETALK:
|
||||
case AF_APPLETALK: {
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
KERNEL_LOCK(1, NULL);
|
||||
if (!aarpresolve(ifp, m, (const struct sockaddr_at *)dst, edst)) {
|
||||
#ifdef NETATALKDEBUG
|
||||
|
@ -310,12 +318,14 @@ ether_output(struct ifnet * const ifp0, struct mbuf * const m0,
|
|||
/*
|
||||
* ifaddr is the first thing in at_ifaddr
|
||||
*/
|
||||
aa = (struct at_ifaddr *) at_ifawithnet(
|
||||
(const struct sockaddr_at *)dst, ifp);
|
||||
if (aa == NULL) {
|
||||
KERNEL_UNLOCK_ONE(NULL);
|
||||
goto bad;
|
||||
s = pserialize_read_enter();
|
||||
ifa = at_ifawithnet((const struct sockaddr_at *)dst, ifp);
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
KERNEL_UNLOCK_ONE(NULL);
|
||||
goto bad;
|
||||
}
|
||||
aa = (struct at_ifaddr *)ifa;
|
||||
|
||||
/*
|
||||
* In the phase 2 case, we need to prepend an mbuf for the
|
||||
|
@ -336,8 +346,10 @@ ether_output(struct ifnet * const ifp0, struct mbuf * const m0,
|
|||
} else {
|
||||
etype = htons(ETHERTYPE_ATALK);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
KERNEL_UNLOCK_ONE(NULL);
|
||||
break;
|
||||
}
|
||||
#endif /* NETATALK */
|
||||
case pseudo_AF_HDRCMPLT:
|
||||
hdrcmplt = 1;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_fddisubr.c,v 1.99 2016/04/28 00:16:56 ozaki-r Exp $ */
|
||||
/* $NetBSD: if_fddisubr.c,v 1.100 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -96,7 +96,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_fddisubr.c,v 1.99 2016/04/28 00:16:56 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_fddisubr.c,v 1.100 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_gateway.h"
|
||||
|
@ -203,10 +203,16 @@ fddi_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
|
|||
struct ifaddr *ifa;
|
||||
|
||||
/* loop back if this is going to the carp interface */
|
||||
if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
|
||||
(ifa = ifa_ifwithaddr(dst)) != NULL &&
|
||||
ifa->ifa_ifp == ifp0)
|
||||
return (looutput(ifp0, m, dst, rt));
|
||||
if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP) {
|
||||
int s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(dst);
|
||||
if (ifa != NULL &&
|
||||
ifa->ifa_ifp == ifp0) {
|
||||
pserialize_read_exit(s);
|
||||
return (looutput(ifp0, m, dst, rt));
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
ifp = ifp->if_carpdev;
|
||||
/* ac = (struct arpcom *)ifp; */
|
||||
|
@ -285,6 +291,9 @@ fddi_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
|
|||
#ifdef NETATALK
|
||||
case AF_APPLETALK: {
|
||||
struct at_ifaddr *aa;
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
if (!aarpresolve(ifp, m, (const struct sockaddr_at *)dst, edst)) {
|
||||
#ifdef NETATALKDEBUG
|
||||
printf("aarpresolv: failed\n");
|
||||
|
@ -294,9 +303,13 @@ fddi_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
|
|||
/*
|
||||
* ifaddr is the first thing in at_ifaddr
|
||||
*/
|
||||
if ((aa = (struct at_ifaddr *)at_ifawithnet(
|
||||
(const struct sockaddr_at *)dst, ifp)) == NULL)
|
||||
s = pserialize_read_enter();
|
||||
ifa = at_ifawithnet((const struct sockaddr_at *)dst, ifp);
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
goto bad;
|
||||
}
|
||||
aa = (struct at_ifaddr *)ifa;
|
||||
|
||||
/*
|
||||
* In the phase 2 case, we need to prepend an mbuf for the llc
|
||||
|
@ -320,6 +333,7 @@ fddi_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
|
|||
} else {
|
||||
etype = htons(ETHERTYPE_ATALK);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
break;
|
||||
}
|
||||
#endif /* NETATALK */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_stf.c,v 1.96 2016/07/08 04:33:30 ozaki-r Exp $ */
|
||||
/* $NetBSD: if_stf.c,v 1.97 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
/* $KAME: if_stf.c,v 1.62 2001/06/07 22:32:16 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -75,7 +75,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.96 2016/07/08 04:33:30 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_stf.c,v 1.97 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -312,9 +312,10 @@ stf_getsrcifa6(struct ifnet *ifp)
|
|||
struct in_ifaddr *ia4;
|
||||
struct sockaddr_in6 *sin6;
|
||||
struct in_addr in;
|
||||
int s;
|
||||
|
||||
IFADDR_READER_FOREACH(ifa, ifp)
|
||||
{
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
|
||||
|
@ -326,8 +327,11 @@ stf_getsrcifa6(struct ifnet *ifp)
|
|||
if (ia4 == NULL)
|
||||
continue;
|
||||
|
||||
pserialize_read_exit(s);
|
||||
/* TODO NOMPSAFE */
|
||||
return (struct in6_ifaddr *)ifa;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_tokensubr.c,v 1.76 2016/04/28 00:16:56 ozaki-r Exp $ */
|
||||
/* $NetBSD: if_tokensubr.c,v 1.77 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1989, 1993
|
||||
|
@ -92,7 +92,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_tokensubr.c,v 1.76 2016/04/28 00:16:56 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_tokensubr.c,v 1.77 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -175,10 +175,16 @@ token_output(struct ifnet *ifp0, struct mbuf *m0, const struct sockaddr *dst,
|
|||
struct ifaddr *ifa;
|
||||
|
||||
/* loop back if this is going to the carp interface */
|
||||
if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP &&
|
||||
(ifa = ifa_ifwithaddr(dst)) != NULL &&
|
||||
ifa->ifa_ifp == ifp0)
|
||||
return (looutput(ifp0, m, dst, rt));
|
||||
if (dst != NULL && ifp0->if_link_state == LINK_STATE_UP) {
|
||||
int s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(dst);
|
||||
if (ifa != NULL &&
|
||||
ifa->ifa_ifp == ifp0) {
|
||||
pserialize_read_exit(s);
|
||||
return (looutput(ifp0, m, dst, rt));
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
ifp = ifp->if_carpdev;
|
||||
ah = (struct arphdr *)ifp;
|
||||
|
|
197
sys/net/route.c
197
sys/net/route.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: route.c,v 1.172 2016/07/15 09:25:47 martin Exp $ */
|
||||
/* $NetBSD: route.c,v 1.173 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -96,7 +96,7 @@
|
|||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.172 2016/07/15 09:25:47 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.173 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#ifdef RTFLUSH_DEBUG
|
||||
|
@ -495,9 +495,10 @@ rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway,
|
|||
uint64_t *stat = NULL;
|
||||
struct rt_addrinfo info;
|
||||
struct ifaddr *ifa;
|
||||
struct psref psref;
|
||||
|
||||
/* verify the gateway is directly reachable */
|
||||
if ((ifa = ifa_ifwithnet(gateway)) == NULL) {
|
||||
if ((ifa = ifa_ifwithnet_psref(gateway, &psref)) == NULL) {
|
||||
error = ENETUNREACH;
|
||||
goto out;
|
||||
}
|
||||
|
@ -511,8 +512,15 @@ rtredirect(const struct sockaddr *dst, const struct sockaddr *gateway,
|
|||
if (!(flags & RTF_DONE) && rt &&
|
||||
(sockaddr_cmp(src, rt->rt_gateway) != 0 || rt->rt_ifa != ifa))
|
||||
error = EINVAL;
|
||||
else if (ifa_ifwithaddr(gateway))
|
||||
error = EHOSTUNREACH;
|
||||
else {
|
||||
int s = pserialize_read_enter();
|
||||
struct ifaddr *_ifa;
|
||||
|
||||
_ifa = ifa_ifwithaddr(gateway);
|
||||
if (_ifa != NULL)
|
||||
error = EHOSTUNREACH;
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
if (error)
|
||||
goto done;
|
||||
/*
|
||||
|
@ -580,6 +588,7 @@ out:
|
|||
info.rti_info[RTAX_NETMASK] = netmask;
|
||||
info.rti_info[RTAX_AUTHOR] = src;
|
||||
rt_missmsg(RTM_REDIRECT, &info, flags, error);
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -610,10 +619,11 @@ rtdeletemsg(struct rtentry *rt)
|
|||
}
|
||||
|
||||
struct ifaddr *
|
||||
ifa_ifwithroute(int flags, const struct sockaddr *dst,
|
||||
const struct sockaddr *gateway)
|
||||
ifa_ifwithroute_psref(int flags, const struct sockaddr *dst,
|
||||
const struct sockaddr *gateway, struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct ifaddr *ifa = NULL;
|
||||
|
||||
if ((flags & RTF_GATEWAY) == 0) {
|
||||
/*
|
||||
* If we are adding a route to an interface,
|
||||
|
@ -622,35 +632,55 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst,
|
|||
* as our clue to the interface. Otherwise
|
||||
* we can use the local address.
|
||||
*/
|
||||
ifa = NULL;
|
||||
if ((flags & RTF_HOST) && gateway->sa_family != AF_LINK)
|
||||
ifa = ifa_ifwithdstaddr(dst);
|
||||
ifa = ifa_ifwithdstaddr_psref(dst, psref);
|
||||
if (ifa == NULL)
|
||||
ifa = ifa_ifwithaddr(gateway);
|
||||
ifa = ifa_ifwithaddr_psref(gateway, psref);
|
||||
} else {
|
||||
/*
|
||||
* If we are adding a route to a remote net
|
||||
* or host, the gateway may still be on the
|
||||
* other end of a pt to pt link.
|
||||
*/
|
||||
ifa = ifa_ifwithdstaddr(gateway);
|
||||
ifa = ifa_ifwithdstaddr_psref(gateway, psref);
|
||||
}
|
||||
if (ifa == NULL)
|
||||
ifa = ifa_ifwithnet(gateway);
|
||||
ifa = ifa_ifwithnet_psref(gateway, psref);
|
||||
if (ifa == NULL) {
|
||||
struct rtentry *rt = rtalloc1(dst, 0);
|
||||
int s;
|
||||
struct rtentry *rt;
|
||||
|
||||
rt = rtalloc1(dst, 0);
|
||||
if (rt == NULL)
|
||||
return NULL;
|
||||
ifa = rt->rt_ifa;
|
||||
/*
|
||||
* Just in case. May not need to do this workaround.
|
||||
* Revisit when working on rtentry MP-ification.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, rt->rt_ifp) {
|
||||
if (ifa == rt->rt_ifa)
|
||||
break;
|
||||
}
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, psref);
|
||||
pserialize_read_exit(s);
|
||||
rtfree(rt);
|
||||
if (ifa == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (ifa->ifa_addr->sa_family != dst->sa_family) {
|
||||
struct ifaddr *oifa = ifa;
|
||||
ifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
|
||||
if (ifa == NULL)
|
||||
ifa = oifa;
|
||||
struct ifaddr *nifa;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
nifa = ifaof_ifpforaddr(dst, ifa->ifa_ifp);
|
||||
if (nifa != NULL) {
|
||||
ifa_release(ifa, psref);
|
||||
ifa_acquire(nifa, psref);
|
||||
ifa = nifa;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
return ifa;
|
||||
}
|
||||
|
@ -699,48 +729,69 @@ rtrequest_newmsg(const int req, const struct sockaddr *dst,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rt_getifa(struct rt_addrinfo *info)
|
||||
struct ifnet *
|
||||
rt_getifp(struct rt_addrinfo *info, struct psref *psref)
|
||||
{
|
||||
const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP];
|
||||
|
||||
if (info->rti_ifp != NULL)
|
||||
return NULL;
|
||||
/*
|
||||
* ifp may be specified by sockaddr_dl when protocol address
|
||||
* is ambiguous
|
||||
*/
|
||||
if (ifpaddr != NULL && ifpaddr->sa_family == AF_LINK) {
|
||||
struct ifaddr *ifa;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
ifa = ifa_ifwithnet(ifpaddr);
|
||||
if (ifa != NULL)
|
||||
info->rti_ifp = if_get_byindex(ifa->ifa_ifp->if_index,
|
||||
psref);
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
return info->rti_ifp;
|
||||
}
|
||||
|
||||
struct ifaddr *
|
||||
rt_getifa(struct rt_addrinfo *info, struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
const struct sockaddr *dst = info->rti_info[RTAX_DST];
|
||||
const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
|
||||
const struct sockaddr *ifaaddr = info->rti_info[RTAX_IFA];
|
||||
const struct sockaddr *ifpaddr = info->rti_info[RTAX_IFP];
|
||||
int flags = info->rti_flags;
|
||||
const struct sockaddr *sa;
|
||||
|
||||
/*
|
||||
* ifp may be specified by sockaddr_dl when protocol address
|
||||
* is ambiguous
|
||||
*/
|
||||
if (info->rti_ifp == NULL && ifpaddr != NULL
|
||||
&& ifpaddr->sa_family == AF_LINK &&
|
||||
(ifa = ifa_ifwithnet(ifpaddr)) != NULL)
|
||||
info->rti_ifp = ifa->ifa_ifp;
|
||||
if (info->rti_ifa == NULL && ifaaddr != NULL)
|
||||
info->rti_ifa = ifa_ifwithaddr(ifaaddr);
|
||||
if (info->rti_ifa == NULL) {
|
||||
const struct sockaddr *sa;
|
||||
|
||||
sa = ifaaddr != NULL ? ifaaddr :
|
||||
(gateway != NULL ? gateway : dst);
|
||||
if (sa != NULL && info->rti_ifp != NULL)
|
||||
info->rti_ifa = ifaof_ifpforaddr(sa, info->rti_ifp);
|
||||
else if (dst != NULL && gateway != NULL)
|
||||
info->rti_ifa = ifa_ifwithroute(flags, dst, gateway);
|
||||
else if (sa != NULL)
|
||||
info->rti_ifa = ifa_ifwithroute(flags, sa, sa);
|
||||
if (info->rti_ifa == NULL && ifaaddr != NULL) {
|
||||
ifa = ifa_ifwithaddr_psref(ifaaddr, psref);
|
||||
if (ifa != NULL)
|
||||
goto got;
|
||||
}
|
||||
if ((ifa = info->rti_ifa) == NULL)
|
||||
return ENETUNREACH;
|
||||
|
||||
sa = ifaaddr != NULL ? ifaaddr :
|
||||
(gateway != NULL ? gateway : dst);
|
||||
if (sa != NULL && info->rti_ifp != NULL)
|
||||
ifa = ifaof_ifpforaddr_psref(sa, info->rti_ifp, psref);
|
||||
else if (dst != NULL && gateway != NULL)
|
||||
ifa = ifa_ifwithroute_psref(flags, dst, gateway, psref);
|
||||
else if (sa != NULL)
|
||||
ifa = ifa_ifwithroute_psref(flags, sa, sa, psref);
|
||||
if (ifa == NULL)
|
||||
return NULL;
|
||||
got:
|
||||
if (ifa->ifa_getifa != NULL) {
|
||||
info->rti_ifa = ifa = (*ifa->ifa_getifa)(ifa, dst);
|
||||
/* FIXME NOMPSAFE */
|
||||
ifa = (*ifa->ifa_getifa)(ifa, dst);
|
||||
if (ifa == NULL)
|
||||
return ENETUNREACH;
|
||||
return NULL;
|
||||
ifa_acquire(ifa, psref);
|
||||
}
|
||||
info->rti_ifa = ifa;
|
||||
if (info->rti_ifp == NULL)
|
||||
info->rti_ifp = ifa->ifa_ifp;
|
||||
return 0;
|
||||
return ifa;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -750,18 +801,23 @@ rt_getifa(struct rt_addrinfo *info)
|
|||
int
|
||||
rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
|
||||
{
|
||||
int s = splsoftnet();
|
||||
int s = splsoftnet(), ss;
|
||||
int error = 0, rc;
|
||||
struct rtentry *rt;
|
||||
rtbl_t *rtbl;
|
||||
struct ifaddr *ifa, *ifa2;
|
||||
struct ifaddr *ifa = NULL, *ifa2 = NULL;
|
||||
struct sockaddr_storage maskeddst;
|
||||
const struct sockaddr *dst = info->rti_info[RTAX_DST];
|
||||
const struct sockaddr *gateway = info->rti_info[RTAX_GATEWAY];
|
||||
const struct sockaddr *netmask = info->rti_info[RTAX_NETMASK];
|
||||
int flags = info->rti_flags;
|
||||
struct psref psref_ifp, psref_ifa;
|
||||
int bound = 0;
|
||||
struct ifnet *ifp = NULL;
|
||||
bool need_to_release_ifa = true;
|
||||
#define senderr(x) { error = x ; goto bad; }
|
||||
|
||||
bound = curlwp_bind();
|
||||
if ((rtbl = rt_gettable(dst->sa_family)) == NULL)
|
||||
senderr(ESRCH);
|
||||
if (flags & RTF_HOST)
|
||||
|
@ -788,6 +844,7 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
|
|||
}
|
||||
if (ifa->ifa_rtrequest)
|
||||
ifa->ifa_rtrequest(RTM_DELETE, rt, info);
|
||||
ifa = NULL;
|
||||
}
|
||||
rttrash++;
|
||||
if (ret_nrt) {
|
||||
|
@ -802,9 +859,16 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
|
|||
break;
|
||||
|
||||
case RTM_ADD:
|
||||
if (info->rti_ifa == NULL && (error = rt_getifa(info)))
|
||||
senderr(error);
|
||||
ifa = info->rti_ifa;
|
||||
if (info->rti_ifa == NULL) {
|
||||
ifp = rt_getifp(info, &psref_ifp);
|
||||
ifa = rt_getifa(info, &psref_ifa);
|
||||
if (ifa == NULL)
|
||||
senderr(ENETUNREACH);
|
||||
} else {
|
||||
/* Caller should have a reference of ifa */
|
||||
ifa = info->rti_ifa;
|
||||
need_to_release_ifa = false;
|
||||
}
|
||||
rt = pool_get(&rtentry_pool, PR_NOWAIT);
|
||||
if (rt == NULL)
|
||||
senderr(ENOBUFS);
|
||||
|
@ -835,17 +899,23 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
|
|||
senderr(ENOBUFS);
|
||||
}
|
||||
RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
|
||||
if (info->rti_info[RTAX_IFP] != NULL &&
|
||||
(ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP])) != NULL &&
|
||||
ifa2->ifa_ifp != NULL)
|
||||
rt->rt_ifp = ifa2->ifa_ifp;
|
||||
else
|
||||
|
||||
ss = pserialize_read_enter();
|
||||
if (info->rti_info[RTAX_IFP] != NULL) {
|
||||
ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP]);
|
||||
if (ifa2 != NULL)
|
||||
rt->rt_ifp = ifa2->ifa_ifp;
|
||||
else
|
||||
rt->rt_ifp = ifa->ifa_ifp;
|
||||
} else
|
||||
rt->rt_ifp = ifa->ifa_ifp;
|
||||
pserialize_read_exit(ss);
|
||||
|
||||
RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
|
||||
rc = rt_addaddr(rtbl, rt, netmask);
|
||||
RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
|
||||
if (rc != 0) {
|
||||
ifafree(ifa);
|
||||
ifafree(ifa); /* for rt_set_ifa above */
|
||||
rt_destroy(rt);
|
||||
pool_put(&rtentry_pool, rt);
|
||||
senderr(rc);
|
||||
|
@ -853,6 +923,11 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
|
|||
RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
|
||||
if (ifa->ifa_rtrequest)
|
||||
ifa->ifa_rtrequest(req, rt, info);
|
||||
if (need_to_release_ifa)
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
ifa = NULL;
|
||||
if_put(ifp, &psref_ifp);
|
||||
ifp = NULL;
|
||||
RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key);
|
||||
if (ret_nrt) {
|
||||
*ret_nrt = rt;
|
||||
|
@ -875,6 +950,10 @@ rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
|
|||
break;
|
||||
}
|
||||
bad:
|
||||
if (need_to_release_ifa)
|
||||
ifa_release(ifa, &psref_ifa);
|
||||
if_put(ifp, &psref_ifp);
|
||||
curlwp_bindx(bound);
|
||||
splx(s);
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: route.h,v 1.101 2016/04/28 00:16:56 ozaki-r Exp $ */
|
||||
/* $NetBSD: route.h,v 1.102 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
|
@ -396,7 +396,10 @@ int rt_ifa_addlocal(struct ifaddr *);
|
|||
int rt_ifa_remlocal(struct ifaddr *, struct ifaddr *);
|
||||
struct ifaddr *
|
||||
rt_get_ifa(struct rtentry *);
|
||||
int rt_getifa(struct rt_addrinfo *);
|
||||
struct ifaddr *
|
||||
rt_getifa(struct rt_addrinfo *, struct psref *);
|
||||
struct ifnet *
|
||||
rt_getifp(struct rt_addrinfo *, struct psref *);
|
||||
void rt_replace_ifa(struct rtentry *, struct ifaddr *);
|
||||
int rt_setgate(struct rtentry *, const struct sockaddr *);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: rtsock.c,v 1.193 2016/07/28 07:54:31 martin Exp $ */
|
||||
/* $NetBSD: rtsock.c,v 1.194 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -61,7 +61,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.193 2016/07/28 07:54:31 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.194 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -541,13 +541,13 @@ route_output_report(struct rtentry *rt, struct rt_addrinfo *info,
|
|||
|
||||
static struct ifaddr *
|
||||
route_output_get_ifa(const struct rt_addrinfo info, const struct rtentry *rt,
|
||||
struct ifnet **ifp)
|
||||
struct ifnet **ifp, struct psref *psref)
|
||||
{
|
||||
struct ifaddr *ifa = NULL;
|
||||
|
||||
*ifp = NULL;
|
||||
if (info.rti_info[RTAX_IFP] != NULL) {
|
||||
ifa = ifa_ifwithnet(info.rti_info[RTAX_IFP]);
|
||||
ifa = ifa_ifwithnet_psref(info.rti_info[RTAX_IFP], psref);
|
||||
if (ifa == NULL)
|
||||
goto next;
|
||||
*ifp = ifa->ifa_ifp;
|
||||
|
@ -556,29 +556,29 @@ route_output_get_ifa(const struct rt_addrinfo info, const struct rtentry *rt,
|
|||
goto next;
|
||||
if (info.rti_info[RTAX_IFA] == NULL) {
|
||||
/* route change <dst> <gw> -ifp <if> */
|
||||
ifa = ifaof_ifpforaddr(info.rti_info[RTAX_GATEWAY],
|
||||
*ifp);
|
||||
ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_GATEWAY],
|
||||
*ifp, psref);
|
||||
} else {
|
||||
/* route change <dst> -ifp <if> -ifa <addr> */
|
||||
ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]);
|
||||
ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref);
|
||||
if (ifa != NULL)
|
||||
goto out;
|
||||
ifa = ifaof_ifpforaddr(info.rti_info[RTAX_IFA],
|
||||
*ifp);
|
||||
ifa = ifaof_ifpforaddr_psref(info.rti_info[RTAX_IFA],
|
||||
*ifp, psref);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
next:
|
||||
if (info.rti_info[RTAX_IFA] != NULL) {
|
||||
/* route change <dst> <gw> -ifa <addr> */
|
||||
ifa = ifa_ifwithaddr(info.rti_info[RTAX_IFA]);
|
||||
ifa = ifa_ifwithaddr_psref(info.rti_info[RTAX_IFA], psref);
|
||||
if (ifa != NULL)
|
||||
goto out;
|
||||
}
|
||||
if (info.rti_info[RTAX_GATEWAY] != NULL) {
|
||||
/* route change <dst> <gw> */
|
||||
ifa = ifa_ifwithroute(rt->rt_flags, rt_getkey(rt),
|
||||
info.rti_info[RTAX_GATEWAY]);
|
||||
ifa = ifa_ifwithroute_psref(rt->rt_flags, rt_getkey(rt),
|
||||
info.rti_info[RTAX_GATEWAY], psref);
|
||||
}
|
||||
out:
|
||||
if (ifa != NULL && *ifp == NULL)
|
||||
|
@ -601,11 +601,15 @@ COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
|
|||
struct ifaddr *ifa = NULL;
|
||||
sa_family_t family;
|
||||
struct sockaddr_dl sdl;
|
||||
struct psref psref;
|
||||
int bound = curlwp_bind();
|
||||
|
||||
#define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0)
|
||||
if (m == NULL || ((m->m_len < sizeof(int32_t)) &&
|
||||
(m = m_pullup(m, sizeof(int32_t))) == NULL))
|
||||
return ENOBUFS;
|
||||
(m = m_pullup(m, sizeof(int32_t))) == NULL)) {
|
||||
error = ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
if ((m->m_flags & M_PKTHDR) == 0)
|
||||
panic("%s", __func__);
|
||||
len = m->m_pkthdr.len;
|
||||
|
@ -807,30 +811,45 @@ COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
|
|||
}
|
||||
break;
|
||||
|
||||
case RTM_CHANGE:
|
||||
case RTM_CHANGE: {
|
||||
struct ifnet *_ifp;
|
||||
struct ifaddr *_ifa;
|
||||
struct psref _psref, psref_ifp;
|
||||
/*
|
||||
* new gateway could require new ifaddr, ifp;
|
||||
* flags may also be different; ifp may be specified
|
||||
* by ll sockaddr when protocol address is ambiguous
|
||||
*/
|
||||
if ((error = rt_getifa(&info)) != 0)
|
||||
senderr(error);
|
||||
_ifp = rt_getifp(&info, &psref_ifp);
|
||||
ifa = rt_getifa(&info, &psref);
|
||||
if (ifa == NULL) {
|
||||
if_put(_ifp, &psref_ifp);
|
||||
senderr(ENETUNREACH);
|
||||
}
|
||||
if (info.rti_info[RTAX_GATEWAY]) {
|
||||
error = rt_setgate(rt,
|
||||
info.rti_info[RTAX_GATEWAY]);
|
||||
if (error != 0)
|
||||
if (error != 0) {
|
||||
if_put(_ifp, &psref_ifp);
|
||||
senderr(error);
|
||||
}
|
||||
}
|
||||
if (info.rti_info[RTAX_TAG]) {
|
||||
const struct sockaddr *tag;
|
||||
tag = rt_settag(rt, info.rti_info[RTAX_TAG]);
|
||||
if (tag == NULL)
|
||||
if (tag == NULL) {
|
||||
if_put(_ifp, &psref_ifp);
|
||||
senderr(ENOBUFS);
|
||||
}
|
||||
}
|
||||
/* new gateway could require new ifaddr, ifp;
|
||||
flags may also be different; ifp may be specified
|
||||
by ll sockaddr when protocol address is ambiguous */
|
||||
ifa = route_output_get_ifa(info, rt, &ifp);
|
||||
_ifa = route_output_get_ifa(info, rt, &ifp, &_psref);
|
||||
if (_ifa != NULL) {
|
||||
ifa_release(ifa, &psref);
|
||||
ifa = _ifa;
|
||||
}
|
||||
if (ifa) {
|
||||
struct ifaddr *oifa = rt->rt_ifa;
|
||||
if (oifa != ifa) {
|
||||
|
@ -841,7 +860,10 @@ COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
|
|||
rt_replace_ifa(rt, ifa);
|
||||
rt->rt_ifp = ifp;
|
||||
}
|
||||
if (_ifa == NULL)
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
ifa_release(_ifa, &_psref);
|
||||
if (ifp && rt->rt_ifp != ifp)
|
||||
rt->rt_ifp = ifp;
|
||||
rt_setmetrics(rtm->rtm_inits, rtm, rt);
|
||||
|
@ -850,7 +872,9 @@ COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
|
|||
| (rt->rt_flags & PRESERVED_RTF);
|
||||
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
|
||||
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
|
||||
if_put(_ifp, &psref_ifp);
|
||||
/*FALLTHROUGH*/
|
||||
}
|
||||
case RTM_LOCK:
|
||||
rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
|
||||
rt->rt_rmx.rmx_locks |=
|
||||
|
@ -890,7 +914,7 @@ flush:
|
|||
if (rtm)
|
||||
Free(rtm);
|
||||
m_freem(m);
|
||||
return error;
|
||||
goto out;
|
||||
}
|
||||
/* There is another listener, so construct message */
|
||||
rp = sotorawcb(so);
|
||||
|
@ -914,6 +938,8 @@ flush:
|
|||
if (rp)
|
||||
rp->rcb_proto.sp_family = PF_XROUTE;
|
||||
}
|
||||
out:
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: aarp.c,v 1.38 2016/07/07 09:32:02 ozaki-r Exp $ */
|
||||
/* $NetBSD: aarp.c,v 1.39 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990,1991 Regents of The University of Michigan.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: aarp.c,v 1.38 2016/07/07 09:32:02 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: aarp.c,v 1.39 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#include "opt_mbuftrace.h"
|
||||
|
||||
|
@ -131,7 +131,7 @@ aarptimer(void *ignored)
|
|||
struct ifaddr *
|
||||
at_ifawithnet(const struct sockaddr_at *sat, struct ifnet *ifp)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr_at *sat2;
|
||||
struct netrange *nr;
|
||||
|
||||
|
@ -149,6 +149,7 @@ at_ifawithnet(const struct sockaddr_at *sat, struct ifnet *ifp)
|
|||
&& (ntohs(nr->nr_lastnet) >= ntohs(sat->sat_addr.s_net)))
|
||||
break;
|
||||
}
|
||||
|
||||
return ifa;
|
||||
}
|
||||
|
||||
|
@ -251,17 +252,24 @@ aarpresolve(struct ifnet *ifp, struct mbuf *m,
|
|||
int s;
|
||||
|
||||
if (at_broadcast(destsat)) {
|
||||
aa = (struct at_ifaddr *) at_ifawithnet(destsat, ifp);
|
||||
if (aa == NULL) {
|
||||
struct ifaddr *ifa;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa = at_ifawithnet(destsat, ifp);
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
m_freem(m);
|
||||
return (0);
|
||||
}
|
||||
aa = (struct at_ifaddr *)ifa;
|
||||
|
||||
if (aa->aa_flags & AFA_PHASE2)
|
||||
memcpy(desten, atmulticastaddr,
|
||||
sizeof(atmulticastaddr));
|
||||
else
|
||||
memcpy(desten, etherbroadcastaddr,
|
||||
sizeof(etherbroadcastaddr));
|
||||
pserialize_read_exit(s);
|
||||
return 1;
|
||||
}
|
||||
s = splnet();
|
||||
|
@ -331,7 +339,6 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
{
|
||||
struct ether_aarp *ea;
|
||||
struct at_ifaddr *aa;
|
||||
struct ifaddr *ia;
|
||||
struct aarptab *aat;
|
||||
struct ether_header *eh;
|
||||
struct llc *llc;
|
||||
|
@ -340,6 +347,9 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
struct at_addr spa, tpa, ma;
|
||||
int op;
|
||||
u_int16_t net;
|
||||
int s;
|
||||
struct psref psref;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
ea = mtod(m, struct ether_aarp *);
|
||||
|
||||
|
@ -355,11 +365,18 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
sat.sat_len = sizeof(struct sockaddr_at);
|
||||
sat.sat_family = AF_APPLETALK;
|
||||
sat.sat_addr.s_net = net;
|
||||
aa = (struct at_ifaddr *) at_ifawithnet(&sat, ifp);
|
||||
if (aa == NULL) {
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa = at_ifawithnet(&sat, ifp);
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
ifa_acquire(ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
aa = (struct at_ifaddr *)ifa;
|
||||
|
||||
memcpy(&spa.s_net, ea->aarp_spnet, sizeof(spa.s_net));
|
||||
memcpy(&tpa.s_net, ea->aarp_tpnet, sizeof(tpa.s_net));
|
||||
} else {
|
||||
|
@ -367,13 +384,18 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
* Since we don't know the net, we just look for the first
|
||||
* phase 1 address on the interface.
|
||||
*/
|
||||
IFADDR_READER_FOREACH(ia, ifp) {
|
||||
aa = (struct at_ifaddr *)ia;
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
aa = (struct at_ifaddr *)ifa;
|
||||
if (AA_SAT(aa)->sat_family == AF_APPLETALK &&
|
||||
(aa->aa_flags & AFA_PHASE2) == 0)
|
||||
(aa->aa_flags & AFA_PHASE2) == 0) {
|
||||
ifa_acquire(ifa, &psref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ia == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (ifa == NULL) {
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
@ -398,7 +420,7 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
callout_stop(&aa->aa_probe_ch);
|
||||
wakeup(aa);
|
||||
m_freem(m);
|
||||
return;
|
||||
goto out;
|
||||
} else if (op != AARPOP_PROBE) {
|
||||
/*
|
||||
* This is not a probe, and we're not probing.
|
||||
|
@ -408,7 +430,7 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
log(LOG_ERR, "aarp: duplicate AT address!! %s\n",
|
||||
ether_sprintf(ea->aarp_sha));
|
||||
m_freem(m);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
AARPTAB_LOOK(aat, spa);
|
||||
|
@ -421,7 +443,7 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
*/
|
||||
aarptfree(aat);
|
||||
m_freem(m);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
memcpy(aat->aat_enaddr, ea->aarp_sha, sizeof(ea->aarp_sha));
|
||||
aat->aat_flags |= ATF_COM;
|
||||
|
@ -449,7 +471,7 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
if (tpa.s_net != ma.s_net || tpa.s_node != ma.s_node ||
|
||||
op == AARPOP_RESPONSE || (aa->aa_flags & AFA_PROBING)) {
|
||||
m_freem(m);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -467,7 +489,7 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
if (aa->aa_flags & AFA_PHASE2) {
|
||||
M_PREPEND(m, sizeof(struct llc), M_DONTWAIT);
|
||||
if (m == NULL)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
llc = mtod(m, struct llc *);
|
||||
llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
|
||||
|
@ -489,6 +511,8 @@ at_aarpinput(struct ifnet *ifp, struct mbuf *m)
|
|||
sa.sa_len = sizeof(struct sockaddr);
|
||||
sa.sa_family = AF_UNSPEC;
|
||||
(*ifp->if_output) (ifp, m, &sa, NULL); /* XXX */
|
||||
out:
|
||||
ifa_release(ifa, &psref);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: at_control.c,v 1.38 2016/07/07 09:32:02 ozaki-r Exp $ */
|
||||
/* $NetBSD: at_control.c,v 1.39 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990,1994 Regents of The University of Michigan.
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: at_control.c,v 1.38 2016/07/07 09:32:02 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: at_control.c,v 1.39 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -194,6 +194,7 @@ at_control(u_long cmd, void *data, struct ifnet *ifp)
|
|||
TAILQ_INSERT_TAIL(&at_ifaddr, aa, aa_list);
|
||||
}
|
||||
ifaref(&aa->aa_ifa);
|
||||
ifa_psref_init(&aa->aa_ifa);
|
||||
|
||||
/*
|
||||
* Find the end of the interface's addresses
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_arp.c,v 1.220 2016/07/28 09:03:50 ozaki-r Exp $ */
|
||||
/* $NetBSD: if_arp.c,v 1.221 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -68,7 +68,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.220 2016/07/28 09:03:50 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.221 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ddb.h"
|
||||
|
@ -446,6 +446,8 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
struct in_ifaddr *ia;
|
||||
struct ifaddr *ifa;
|
||||
struct ifnet *ifp = rt->rt_ifp;
|
||||
int bound;
|
||||
int s;
|
||||
|
||||
if (req == RTM_LLINFO_UPD) {
|
||||
struct in_addr *in;
|
||||
|
@ -553,10 +555,13 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
if (rt->rt_flags & RTF_CONNECTED)
|
||||
break;
|
||||
}
|
||||
|
||||
bound = curlwp_bind();
|
||||
/* Announce a new entry if requested. */
|
||||
if (rt->rt_flags & RTF_ANNOUNCE) {
|
||||
ia = in_get_ia_on_iface(
|
||||
satocsin(rt_getkey(rt))->sin_addr, ifp);
|
||||
struct psref psref;
|
||||
ia = in_get_ia_on_iface_psref(
|
||||
satocsin(rt_getkey(rt))->sin_addr, ifp, &psref);
|
||||
if (ia == NULL ||
|
||||
ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED))
|
||||
;
|
||||
|
@ -565,12 +570,14 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
&satocsin(rt_getkey(rt))->sin_addr,
|
||||
&satocsin(rt_getkey(rt))->sin_addr,
|
||||
CLLADDR(satocsdl(gate)));
|
||||
if (ia != NULL)
|
||||
ia4_release(ia, &psref);
|
||||
}
|
||||
|
||||
if (gate->sa_family != AF_LINK ||
|
||||
gate->sa_len < sockaddr_dl_measure(0, ifp->if_addrlen)) {
|
||||
log(LOG_DEBUG, "%s: bad gateway value\n", __func__);
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
|
||||
satosdl(gate)->sdl_type = ifp->if_type;
|
||||
|
@ -586,7 +593,7 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
rt->rt_flags |= RTF_BROADCAST;
|
||||
/* There is little point in resolving the broadcast address */
|
||||
if (rt->rt_flags & RTF_BROADCAST)
|
||||
break;
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* When called from rt_ifa_addlocal, we cannot depend on that
|
||||
|
@ -599,12 +606,15 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
rt->rt_ifp = lo0ifp;
|
||||
rt->rt_rmx.rmx_mtu = 0;
|
||||
}
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia = in_get_ia_on_iface(satocsin(rt_getkey(rt))->sin_addr, ifp);
|
||||
if (ia == NULL)
|
||||
break;
|
||||
if (ia == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rt->rt_expire = 0;
|
||||
if (useloopback) {
|
||||
|
@ -619,7 +629,11 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
*/
|
||||
ifa = &ia->ia_ifa;
|
||||
if (ifa != rt->rt_ifa)
|
||||
/* Assume it doesn't sleep */
|
||||
rt_replace_ifa(rt, ifa);
|
||||
pserialize_read_exit(s);
|
||||
out:
|
||||
curlwp_bindx(bound);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -971,7 +985,7 @@ in_arpinput(struct mbuf *m)
|
|||
struct arphdr *ah;
|
||||
struct ifnet *ifp, *rcvif = NULL;
|
||||
struct llentry *la = NULL;
|
||||
struct in_ifaddr *ia;
|
||||
struct in_ifaddr *ia = NULL;
|
||||
#if NBRIDGE > 0
|
||||
struct in_ifaddr *bridge_ia = NULL;
|
||||
#endif
|
||||
|
@ -983,7 +997,8 @@ in_arpinput(struct mbuf *m)
|
|||
int op;
|
||||
void *tha;
|
||||
uint64_t *arps;
|
||||
struct psref psref;
|
||||
struct psref psref, psref_ia;
|
||||
int s;
|
||||
|
||||
if (__predict_false(m_makewritable(&m, 0, m->m_pkthdr.len, M_DONTWAIT)))
|
||||
goto out;
|
||||
|
@ -1024,6 +1039,7 @@ in_arpinput(struct mbuf *m)
|
|||
* or any address on the interface to use
|
||||
* as a dummy address in the rest of this function
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRHASH_READER_FOREACH(ia, itaddr.s_addr) {
|
||||
if (!in_hosteq(ia->ia_addr.sin_addr, itaddr))
|
||||
continue;
|
||||
|
@ -1064,11 +1080,14 @@ in_arpinput(struct mbuf *m)
|
|||
ifp = bridge_ia->ia_ifp;
|
||||
}
|
||||
#endif
|
||||
if (ia != NULL)
|
||||
ia4_acquire(ia, &psref_ia);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (ia == NULL) {
|
||||
ia = in_get_ia_on_iface(isaddr, rcvif);
|
||||
ia = in_get_ia_on_iface_psref(isaddr, rcvif, &psref_ia);
|
||||
if (ia == NULL) {
|
||||
ia = in_get_ia_from_ifp(ifp);
|
||||
ia = in_get_ia_from_ifp_psref(ifp, &psref_ia);
|
||||
if (ia == NULL) {
|
||||
ARP_STATINC(ARP_STAT_RCVNOINT);
|
||||
goto out;
|
||||
|
@ -1289,7 +1308,6 @@ reply:
|
|||
struct llentry *lle = NULL;
|
||||
struct sockaddr_in sin;
|
||||
#if NCARP > 0
|
||||
int s;
|
||||
struct ifnet *_rcvif = m_get_rcvif(m, &s);
|
||||
if (ifp->if_type == IFT_CARP && _rcvif->if_type != IFT_CARP)
|
||||
goto out;
|
||||
|
@ -1314,6 +1332,7 @@ reply:
|
|||
goto drop;
|
||||
}
|
||||
}
|
||||
ia4_release(ia, &psref_ia);
|
||||
|
||||
memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln);
|
||||
memcpy(ar_spa(ah), &itaddr, ah->ar_pln);
|
||||
|
@ -1350,6 +1369,8 @@ out:
|
|||
if (la != NULL)
|
||||
LLE_WUNLOCK(la);
|
||||
drop:
|
||||
if (ia != NULL)
|
||||
ia4_release(ia, &psref_ia);
|
||||
if (rcvif != NULL)
|
||||
m_put_rcvif_psref(rcvif, &psref);
|
||||
m_freem(m);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: igmp.c,v 1.61 2016/07/08 04:33:30 ozaki-r Exp $ */
|
||||
/* $NetBSD: igmp.c,v 1.62 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -40,7 +40,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: igmp.c,v 1.61 2016/07/08 04:33:30 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: igmp.c,v 1.62 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_mrouting.h"
|
||||
|
@ -361,9 +361,11 @@ igmp_input(struct mbuf *m, ...)
|
|||
* determine the arrival interface of an incoming packet.
|
||||
*/
|
||||
if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) {
|
||||
ia = in_get_ia_from_ifp(ifp); /* XXX */
|
||||
int s = pserialize_read_enter();
|
||||
ia = in_get_ia_from_ifp(ifp); /* XXX */
|
||||
if (ia)
|
||||
ip->ip_src.s_addr = ia->ia_subnet;
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -394,26 +396,32 @@ igmp_input(struct mbuf *m, ...)
|
|||
in_multi_unlock();
|
||||
break;
|
||||
|
||||
case IGMP_v2_HOST_MEMBERSHIP_REPORT:
|
||||
case IGMP_v2_HOST_MEMBERSHIP_REPORT: {
|
||||
int s = pserialize_read_enter();
|
||||
#ifdef MROUTING
|
||||
/*
|
||||
* Make sure we don't hear our own membership report. Fast
|
||||
* leave requires knowing that we are the only member of a
|
||||
* group.
|
||||
*/
|
||||
ia = in_get_ia_from_ifp(ifp); /* XXX */
|
||||
if (ia && in_hosteq(ip->ip_src, ia->ia_addr.sin_addr))
|
||||
ia = in_get_ia_from_ifp(ifp); /* XXX */
|
||||
if (ia && in_hosteq(ip->ip_src, ia->ia_addr.sin_addr)) {
|
||||
pserialize_read_exit(s);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
IGMP_STATINC(IGMP_STAT_RCV_REPORTS);
|
||||
|
||||
if (ifp->if_flags & IFF_LOOPBACK)
|
||||
if (ifp->if_flags & IFF_LOOPBACK) {
|
||||
pserialize_read_exit(s);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!IN_MULTICAST(igmp->igmp_group.s_addr) ||
|
||||
!in_hosteq(igmp->igmp_group, ip->ip_dst)) {
|
||||
IGMP_STATINC(IGMP_STAT_RCV_BADREPORTS);
|
||||
pserialize_read_exit(s);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
|
@ -428,11 +436,12 @@ igmp_input(struct mbuf *m, ...)
|
|||
*/
|
||||
if ((ip->ip_src.s_addr & IN_CLASSA_NET) == 0) {
|
||||
#ifndef MROUTING
|
||||
ia = in_get_ia_from_ifp(ifp); /* XXX */
|
||||
ia = in_get_ia_from_ifp(ifp); /* XXX */
|
||||
#endif
|
||||
if (ia)
|
||||
ip->ip_src.s_addr = ia->ia_subnet;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* If we belong to the group being reported, stop
|
||||
|
@ -457,7 +466,7 @@ igmp_input(struct mbuf *m, ...)
|
|||
}
|
||||
in_multi_unlock();
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
m_put_rcvif_psref(ifp, &psref);
|
||||
|
||||
|
|
258
sys/netinet/in.c
258
sys/netinet/in.c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in.c,v 1.177 2016/07/28 09:03:50 ozaki-r Exp $ */
|
||||
/* $NetBSD: in.c,v 1.178 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -91,7 +91,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.177 2016/07/28 09:03:50 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.178 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#include "arp.h"
|
||||
|
||||
|
@ -189,6 +189,7 @@ static krwlock_t in_multilock;
|
|||
struct in_ifaddrhashhead * in_ifaddrhashtbl;
|
||||
u_long in_ifaddrhash;
|
||||
struct in_ifaddrhead in_ifaddrhead;
|
||||
static kmutex_t in_ifaddr_lock;
|
||||
|
||||
struct pslist_head * in_ifaddrhashtbl_pslist;
|
||||
u_long in_ifaddrhash_pslist;
|
||||
|
@ -204,8 +205,11 @@ in_init(void)
|
|||
|
||||
in_ifaddrhashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, true,
|
||||
&in_ifaddrhash);
|
||||
|
||||
in_ifaddrhashtbl_pslist = hashinit(IN_IFADDR_HASH_SIZE, HASH_PSLIST,
|
||||
true, &in_ifaddrhash_pslist);
|
||||
mutex_init(&in_ifaddr_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
in_multihashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, true,
|
||||
&in_multihash);
|
||||
rw_init(&in_multilock);
|
||||
|
@ -223,19 +227,27 @@ int
|
|||
in_localaddr(struct in_addr in)
|
||||
{
|
||||
struct in_ifaddr *ia;
|
||||
int localaddr = 0;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
if (subnetsarelocal) {
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
|
||||
return (1);
|
||||
if ((in.s_addr & ia->ia_netmask) == ia->ia_net) {
|
||||
localaddr = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
|
||||
return (1);
|
||||
if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet) {
|
||||
localaddr = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return localaddr;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -307,6 +319,7 @@ in_setmaxmtu(void)
|
|||
struct in_ifaddr *ia;
|
||||
struct ifnet *ifp;
|
||||
unsigned long maxmtu = 0;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if ((ifp = ia->ia_ifp) == 0)
|
||||
|
@ -318,6 +331,7 @@ in_setmaxmtu(void)
|
|||
}
|
||||
if (maxmtu)
|
||||
in_maxmtu = maxmtu;
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
static u_int
|
||||
|
@ -371,6 +385,8 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
int newifaddr = 0;
|
||||
bool run_hook = false;
|
||||
bool need_reinsert = false;
|
||||
struct psref psref;
|
||||
int bound;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCALIFADDR:
|
||||
|
@ -386,11 +402,12 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
return ifaddrpref_ioctl(so, cmd, data, ifp);
|
||||
}
|
||||
|
||||
bound = curlwp_bind();
|
||||
/*
|
||||
* Find address for this interface, if it exists.
|
||||
*/
|
||||
if (ifp != NULL)
|
||||
ia = in_get_ia_from_ifp(ifp);
|
||||
ia = in_get_ia_from_ifp_psref(ifp, &psref);
|
||||
|
||||
hostIsNew = 1; /* moved here to appease gcc */
|
||||
switch (cmd) {
|
||||
|
@ -399,6 +416,11 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
case SIOCGIFALIAS:
|
||||
case SIOCGIFAFLAG_IN:
|
||||
if (ifra->ifra_addr.sin_family == AF_INET) {
|
||||
int s;
|
||||
|
||||
if (ia != NULL)
|
||||
ia4_release(ia, &psref);
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRHASH_READER_FOREACH(ia,
|
||||
ifra->ifra_addr.sin_addr.s_addr) {
|
||||
if (ia->ia_ifp == ifp &&
|
||||
|
@ -406,12 +428,17 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
ifra->ifra_addr.sin_addr))
|
||||
break;
|
||||
}
|
||||
if (ia != NULL)
|
||||
ia4_acquire(ia, &psref);
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
if ((cmd == SIOCDIFADDR ||
|
||||
cmd == SIOCGIFALIAS ||
|
||||
cmd == SIOCGIFAFLAG_IN) &&
|
||||
ia == NULL)
|
||||
return (EADDRNOTAVAIL);
|
||||
ia == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cmd == SIOCDIFADDR &&
|
||||
ifra->ifra_addr.sin_family == AF_UNSPEC) {
|
||||
|
@ -429,8 +456,10 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
hostIsNew = 0;
|
||||
/* FALLTHROUGH */
|
||||
case SIOCSIFDSTADDR:
|
||||
if (ifra->ifra_addr.sin_family != AF_INET)
|
||||
return (EAFNOSUPPORT);
|
||||
if (ifra->ifra_addr.sin_family != AF_INET) {
|
||||
error = EAFNOSUPPORT;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case SIOCSIFNETMASK:
|
||||
if (ifp == NULL)
|
||||
|
@ -440,18 +469,24 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
|
||||
if (ia == NULL &&
|
||||
(cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR))
|
||||
return (EADDRNOTAVAIL);
|
||||
(cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR)) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_INTERFACE,
|
||||
KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
|
||||
NULL) != 0)
|
||||
return (EPERM);
|
||||
NULL) != 0) {
|
||||
error = EPERM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ia == NULL) {
|
||||
ia = malloc(sizeof(*ia), M_IFADDR, M_WAITOK|M_ZERO);
|
||||
if (ia == NULL)
|
||||
return (ENOBUFS);
|
||||
if (ia == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
|
||||
ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
|
||||
ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
|
||||
|
@ -471,6 +506,7 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
LIST_INIT(&ia->ia_multiaddrs);
|
||||
IN_ADDRHASH_ENTRY_INIT(ia);
|
||||
IN_ADDRLIST_ENTRY_INIT(ia);
|
||||
ifa_psref_init(&ia->ia_ifa);
|
||||
|
||||
newifaddr = 1;
|
||||
}
|
||||
|
@ -479,16 +515,20 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
case SIOCSIFBRDADDR:
|
||||
if (kauth_authorize_network(curlwp->l_cred, KAUTH_NETWORK_INTERFACE,
|
||||
KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
|
||||
NULL) != 0)
|
||||
return (EPERM);
|
||||
NULL) != 0) {
|
||||
error = EPERM;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case SIOCGIFADDR:
|
||||
case SIOCGIFNETMASK:
|
||||
case SIOCGIFDSTADDR:
|
||||
case SIOCGIFBRDADDR:
|
||||
if (ia == NULL)
|
||||
return (EADDRNOTAVAIL);
|
||||
if (ia == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
error = 0;
|
||||
|
@ -499,14 +539,18 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
|
||||
case SIOCGIFBRDADDR:
|
||||
if ((ifp->if_flags & IFF_BROADCAST) == 0)
|
||||
return (EINVAL);
|
||||
if ((ifp->if_flags & IFF_BROADCAST) == 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ifreq_setdstaddr(cmd, ifr, sintocsa(&ia->ia_broadaddr));
|
||||
break;
|
||||
|
||||
case SIOCGIFDSTADDR:
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
|
||||
return (EINVAL);
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ifreq_setdstaddr(cmd, ifr, sintocsa(&ia->ia_dstaddr));
|
||||
break;
|
||||
|
||||
|
@ -522,13 +566,15 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
|
||||
case SIOCSIFDSTADDR:
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
|
||||
return (EINVAL);
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
oldaddr = ia->ia_dstaddr;
|
||||
ia->ia_dstaddr = *satocsin(ifreq_getdstaddr(cmd, ifr));
|
||||
if ((error = if_addr_init(ifp, &ia->ia_ifa, false)) != 0) {
|
||||
ia->ia_dstaddr = oldaddr;
|
||||
return error;
|
||||
goto out;
|
||||
}
|
||||
if (ia->ia_flags & IFA_ROUTE) {
|
||||
ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
|
||||
|
@ -539,15 +585,19 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
|
||||
case SIOCSIFBRDADDR:
|
||||
if ((ifp->if_flags & IFF_BROADCAST) == 0)
|
||||
return EINVAL;
|
||||
if ((ifp->if_flags & IFF_BROADCAST) == 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
ia->ia_broadaddr = *satocsin(ifreq_getbroadaddr(cmd, ifr));
|
||||
break;
|
||||
|
||||
case SIOCSIFADDR:
|
||||
if (!newifaddr) {
|
||||
mutex_enter(&in_ifaddr_lock);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
IN_ADDRHASH_WRITER_REMOVE(ia);
|
||||
mutex_exit(&in_ifaddr_lock);
|
||||
need_reinsert = true;
|
||||
}
|
||||
error = in_ifinit(ifp, ia, satocsin(ifreq_getaddr(cmd, ifr)),
|
||||
|
@ -561,8 +611,10 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
ia->ia_sockmask = *satocsin(ifreq_getaddr(cmd, ifr));
|
||||
ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
|
||||
if (!newifaddr) {
|
||||
mutex_enter(&in_ifaddr_lock);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
IN_ADDRHASH_WRITER_REMOVE(ia);
|
||||
mutex_exit(&in_ifaddr_lock);
|
||||
need_reinsert = true;
|
||||
}
|
||||
error = in_ifinit(ifp, ia, NULL, 0, 0);
|
||||
|
@ -591,8 +643,10 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
if (ifra->ifra_addr.sin_family == AF_INET &&
|
||||
(hostIsNew || maskIsNew)) {
|
||||
if (!newifaddr) {
|
||||
mutex_enter(&in_ifaddr_lock);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
IN_ADDRHASH_WRITER_REMOVE(ia);
|
||||
mutex_exit(&in_ifaddr_lock);
|
||||
need_reinsert = true;
|
||||
}
|
||||
error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0,
|
||||
|
@ -622,7 +676,9 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
|
||||
case SIOCDIFADDR:
|
||||
ia4_release(ia, &psref);
|
||||
in_purgeaddr(&ia->ia_ifa);
|
||||
ia = NULL;
|
||||
run_hook = true;
|
||||
break;
|
||||
|
||||
|
@ -634,7 +690,8 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
#endif /* MROUTING */
|
||||
|
||||
default:
|
||||
return ENOTTY;
|
||||
error = ENOTTY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -642,17 +699,22 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
* Need to improve.
|
||||
*/
|
||||
if (newifaddr) {
|
||||
TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_list);
|
||||
ifaref(&ia->ia_ifa);
|
||||
ifa_insert(ifp, &ia->ia_ifa);
|
||||
|
||||
mutex_enter(&in_ifaddr_lock);
|
||||
TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_list);
|
||||
IN_ADDRLIST_WRITER_INSERT_TAIL(ia);
|
||||
LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
|
||||
ia, ia_hash);
|
||||
IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
|
||||
mutex_exit(&in_ifaddr_lock);
|
||||
} else if (need_reinsert) {
|
||||
mutex_enter(&in_ifaddr_lock);
|
||||
LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
|
||||
ia, ia_hash);
|
||||
IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
|
||||
mutex_exit(&in_ifaddr_lock);
|
||||
}
|
||||
|
||||
if (error == 0) {
|
||||
|
@ -662,8 +724,13 @@ in_control0(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
} else if (newifaddr) {
|
||||
KASSERT(ia != NULL);
|
||||
in_purgeaddr(&ia->ia_ifa);
|
||||
ia = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!newifaddr && ia != NULL)
|
||||
ia4_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -704,10 +771,14 @@ in_ifremlocal(struct ifaddr *ifa)
|
|||
struct in_ifaddr *ia, *p;
|
||||
struct ifaddr *alt_ifa = NULL;
|
||||
int ia_count = 0;
|
||||
int s;
|
||||
struct psref psref;
|
||||
int bound = curlwp_bind();
|
||||
|
||||
ia = (struct in_ifaddr *)ifa;
|
||||
/* Delete the entry if exactly one ifaddr matches the
|
||||
* address, ifa->ifa_addr. */
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(p) {
|
||||
if (!in_hosteq(p->ia_addr.sin_addr, ia->ia_addr.sin_addr))
|
||||
continue;
|
||||
|
@ -716,35 +787,54 @@ in_ifremlocal(struct ifaddr *ifa)
|
|||
if (++ia_count > 1 && alt_ifa != NULL)
|
||||
break;
|
||||
}
|
||||
if (alt_ifa != NULL && ia_count > 1)
|
||||
ifa_acquire(alt_ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (ia_count == 0)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
rt_ifa_remlocal(ifa, ia_count == 1 ? NULL : alt_ifa);
|
||||
if (alt_ifa != NULL && ia_count > 1)
|
||||
ifa_release(alt_ifa, &psref);
|
||||
out:
|
||||
curlwp_bindx(bound);
|
||||
}
|
||||
|
||||
/*
|
||||
* Depends on it isn't called in concurrent. It should be guaranteed
|
||||
* by ifa->ifa_ifp's ioctl lock. The possible callers are in_control
|
||||
* and if_purgeaddrs; the former is called iva ifa->ifa_ifp's ioctl
|
||||
* and the latter is called via ifa->ifa_ifp's if_detach. The functions
|
||||
* never be executed in concurrent.
|
||||
*/
|
||||
void
|
||||
in_purgeaddr(struct ifaddr *ifa)
|
||||
{
|
||||
struct ifnet *ifp = ifa->ifa_ifp;
|
||||
struct in_ifaddr *ia = (void *) ifa;
|
||||
|
||||
KASSERT(!ifa_held(ifa));
|
||||
|
||||
/* stop DAD processing */
|
||||
if (ia->ia_dad_stop != NULL)
|
||||
ia->ia_dad_stop(ifa);
|
||||
|
||||
in_ifscrub(ifp, ia);
|
||||
in_ifremlocal(ifa);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
IN_ADDRHASH_WRITER_REMOVE(ia);
|
||||
IN_ADDRHASH_ENTRY_DESTROY(ia);
|
||||
ifa_remove(ifp, &ia->ia_ifa);
|
||||
TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
|
||||
IN_ADDRLIST_WRITER_REMOVE(ia);
|
||||
IN_ADDRLIST_ENTRY_DESTROY(ia);
|
||||
|
||||
if (ia->ia_allhosts != NULL)
|
||||
in_delmulti(ia->ia_allhosts);
|
||||
|
||||
mutex_enter(&in_ifaddr_lock);
|
||||
LIST_REMOVE(ia, ia_hash);
|
||||
IN_ADDRHASH_WRITER_REMOVE(ia);
|
||||
TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
|
||||
IN_ADDRLIST_WRITER_REMOVE(ia);
|
||||
ifa_remove(ifp, &ia->ia_ifa);
|
||||
mutex_exit(&in_ifaddr_lock);
|
||||
|
||||
IN_ADDRHASH_ENTRY_DESTROY(ia);
|
||||
IN_ADDRLIST_ENTRY_DESTROY(ia);
|
||||
ifafree(&ia->ia_ifa);
|
||||
in_setmaxmtu();
|
||||
}
|
||||
|
@ -1078,6 +1168,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
|
|||
struct in_ifaddr *ia;
|
||||
struct in_addr prefix, mask, p;
|
||||
int error;
|
||||
int s;
|
||||
|
||||
if ((flags & RTF_HOST) != 0)
|
||||
prefix = target->ia_dstaddr.sin_addr;
|
||||
|
@ -1087,6 +1178,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
|
|||
prefix.s_addr &= mask.s_addr;
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if (rtinitflags(ia))
|
||||
p = ia->ia_dstaddr.sin_addr;
|
||||
|
@ -1104,9 +1196,12 @@ in_addprefix(struct in_ifaddr *target, int flags)
|
|||
*
|
||||
* XXX RADIX_MPATH implications here? -dyoung
|
||||
*/
|
||||
if (ia->ia_flags & IFA_ROUTE)
|
||||
if (ia->ia_flags & IFA_ROUTE) {
|
||||
pserialize_read_exit(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* noone seem to have prefix route. insert it.
|
||||
|
@ -1134,6 +1229,7 @@ in_scrubprefix(struct in_ifaddr *target)
|
|||
struct in_ifaddr *ia;
|
||||
struct in_addr prefix, mask, p;
|
||||
int error;
|
||||
int s;
|
||||
|
||||
/* If we don't have IFA_ROUTE we should still inform userland */
|
||||
if ((target->ia_flags & IFA_ROUTE) == 0)
|
||||
|
@ -1147,6 +1243,7 @@ in_scrubprefix(struct in_ifaddr *target)
|
|||
prefix.s_addr &= mask.s_addr;
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if (rtinitflags(ia))
|
||||
p = ia->ia_dstaddr.sin_addr;
|
||||
|
@ -1162,6 +1259,12 @@ in_scrubprefix(struct in_ifaddr *target)
|
|||
* if we got a matching prefix route, move IFA_ROUTE to him
|
||||
*/
|
||||
if ((ia->ia_flags & IFA_ROUTE) == 0) {
|
||||
struct psref psref;
|
||||
int bound = curlwp_bind();
|
||||
|
||||
ia4_acquire(ia, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
rtinit(&target->ia_ifa, RTM_DELETE,
|
||||
rtinitflags(target));
|
||||
target->ia_flags &= ~IFA_ROUTE;
|
||||
|
@ -1170,9 +1273,14 @@ in_scrubprefix(struct in_ifaddr *target)
|
|||
rtinitflags(ia) | RTF_UP);
|
||||
if (error == 0)
|
||||
ia->ia_flags |= IFA_ROUTE;
|
||||
|
||||
ia4_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
return error;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* noone seem to have prefix route. remove it.
|
||||
|
@ -1191,6 +1299,9 @@ int
|
|||
in_broadcast(struct in_addr in, struct ifnet *ifp)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
KASSERT(ifp != NULL);
|
||||
|
||||
if (in.s_addr == INADDR_BROADCAST ||
|
||||
in_nullhost(in))
|
||||
|
@ -1202,7 +1313,8 @@ in_broadcast(struct in_addr in, struct ifnet *ifp)
|
|||
* with a broadcast address.
|
||||
*/
|
||||
#define ia (ifatoia(ifa))
|
||||
IFADDR_READER_FOREACH(ifa, ifp)
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family == AF_INET &&
|
||||
!in_hosteq(in, ia->ia_addr.sin_addr) &&
|
||||
(in_hosteq(in, ia->ia_broadaddr.sin_addr) ||
|
||||
|
@ -1212,8 +1324,12 @@ in_broadcast(struct in_addr in, struct ifnet *ifp)
|
|||
* Check for old-style (host 0) broadcast.
|
||||
*/
|
||||
(in.s_addr == ia->ia_subnet ||
|
||||
in.s_addr == ia->ia_net))))
|
||||
in.s_addr == ia->ia_net)))) {
|
||||
pserialize_read_exit(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
return (0);
|
||||
#undef ia
|
||||
}
|
||||
|
@ -1505,13 +1621,14 @@ in_multi_lock_held(void)
|
|||
return rw_lock_held(&in_multilock);
|
||||
}
|
||||
|
||||
struct sockaddr_in *
|
||||
struct in_ifaddr *
|
||||
in_selectsrc(struct sockaddr_in *sin, struct route *ro,
|
||||
int soopts, struct ip_moptions *mopts, int *errorp)
|
||||
int soopts, struct ip_moptions *mopts, int *errorp, struct psref *psref)
|
||||
{
|
||||
struct rtentry *rt = NULL;
|
||||
struct in_ifaddr *ia = NULL;
|
||||
|
||||
KASSERT(ISSET(curlwp->l_pflag, LP_BOUND));
|
||||
/*
|
||||
* If route is known or can be allocated now, take the
|
||||
* source address from the interface. Otherwise, punt.
|
||||
|
@ -1535,20 +1652,45 @@ in_selectsrc(struct sockaddr_in *sin, struct route *ro,
|
|||
*
|
||||
* XXX Is this still true? Do we care?
|
||||
*/
|
||||
if (rt != NULL && (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0)
|
||||
ia = ifatoia(rt->rt_ifa);
|
||||
if (rt != NULL && (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) {
|
||||
int s;
|
||||
struct ifaddr *ifa;
|
||||
/*
|
||||
* Just in case. May not need to do this workaround.
|
||||
* Revisit when working on rtentry MP-ification.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, rt->rt_ifp) {
|
||||
if (ifa == rt->rt_ifa)
|
||||
break;
|
||||
}
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
ia = ifatoia(ifa);
|
||||
}
|
||||
if (ia == NULL) {
|
||||
u_int16_t fport = sin->sin_port;
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
sin->sin_port = 0;
|
||||
ia = ifatoia(ifa_ifwithladdr(sintosa(sin)));
|
||||
ifa = ifa_ifwithladdr_psref(sintosa(sin), psref);
|
||||
sin->sin_port = fport;
|
||||
if (ia == NULL) {
|
||||
if (ifa == NULL) {
|
||||
/* Find 1st non-loopback AF_INET address */
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if (!(ia->ia_ifp->if_flags & IFF_LOOPBACK))
|
||||
break;
|
||||
}
|
||||
if (ia != NULL)
|
||||
ia4_acquire(ia, psref);
|
||||
pserialize_read_exit(s);
|
||||
} else {
|
||||
/* ia is already referenced by psref */
|
||||
ia = ifatoia(ifa);
|
||||
}
|
||||
if (ia == NULL) {
|
||||
*errorp = EADDRNOTAVAIL;
|
||||
|
@ -1566,15 +1708,21 @@ in_selectsrc(struct sockaddr_in *sin, struct route *ro,
|
|||
imo = mopts;
|
||||
if (imo->imo_multicast_if_index != 0) {
|
||||
struct ifnet *ifp;
|
||||
int s = pserialize_read_enter();
|
||||
int s;
|
||||
|
||||
if (ia != NULL)
|
||||
ia4_release(ia, psref);
|
||||
s = pserialize_read_enter();
|
||||
ifp = if_byindex(imo->imo_multicast_if_index);
|
||||
if (ifp != NULL) {
|
||||
ia = in_get_ia_from_ifp(ifp); /* XXX */
|
||||
/* XXX */
|
||||
ia = in_get_ia_from_ifp_psref(ifp, psref);
|
||||
} else
|
||||
ia = NULL;
|
||||
if (ia == NULL || ia->ia4_flags & IN_IFF_NOTREADY) {
|
||||
pserialize_read_exit(s);
|
||||
if (ia != NULL)
|
||||
ia4_release(ia, psref);
|
||||
*errorp = EADDRNOTAVAIL;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1588,12 +1736,14 @@ in_selectsrc(struct sockaddr_in *sin, struct route *ro,
|
|||
*errorp = EADDRNOTAVAIL;
|
||||
return NULL;
|
||||
}
|
||||
/* FIXME NOMPSAFE */
|
||||
ia4_acquire(ia, psref);
|
||||
}
|
||||
#ifdef GETIFA_DEBUG
|
||||
else
|
||||
printf("%s: missing ifa_getifa\n", __func__);
|
||||
#endif
|
||||
return &ia->ia_addr;
|
||||
return ia;
|
||||
}
|
||||
|
||||
#if NARP > 0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in.h,v 1.98 2015/10/13 21:28:35 rjs Exp $ */
|
||||
/* $NetBSD: in.h,v 1.99 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1990, 1993
|
||||
|
@ -507,6 +507,8 @@ struct ip_mreq {
|
|||
#undef __KAME_NETINET_IN_H_INCLUDED_
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/psref.h>
|
||||
|
||||
/*
|
||||
* in_cksum_phdr:
|
||||
*
|
||||
|
@ -576,8 +578,8 @@ void in_if_link_state_change(struct ifnet *, int);
|
|||
struct route;
|
||||
struct ip_moptions;
|
||||
|
||||
struct sockaddr_in *in_selectsrc(struct sockaddr_in *,
|
||||
struct route *, int, struct ip_moptions *, int *);
|
||||
struct in_ifaddr *in_selectsrc(struct sockaddr_in *,
|
||||
struct route *, int, struct ip_moptions *, int *, struct psref *);
|
||||
|
||||
#define in_hosteq(s,t) ((s).s_addr == (t).s_addr)
|
||||
#define in_nullhost(x) ((x).s_addr == INADDR_ANY)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in_gif.c,v 1.81 2016/07/06 08:42:34 ozaki-r Exp $ */
|
||||
/* $NetBSD: in_gif.c,v 1.82 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
/* $KAME: in_gif.c,v 1.66 2001/07/29 04:46:09 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.81 2016/07/06 08:42:34 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.82 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -289,6 +289,7 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)
|
|||
{
|
||||
struct sockaddr_in *src, *dst;
|
||||
struct in_ifaddr *ia4;
|
||||
int s;
|
||||
|
||||
src = satosin(sc->gif_psrc);
|
||||
dst = satosin(sc->gif_pdst);
|
||||
|
@ -306,12 +307,16 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)
|
|||
return 0;
|
||||
}
|
||||
/* reject packets with broadcast on source */
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(ia4) {
|
||||
if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
|
||||
continue;
|
||||
if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr)
|
||||
if (ip->ip_src.s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
|
||||
pserialize_read_exit(s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/* ingress filters on outer source */
|
||||
if ((sc->gif_if.if_flags & IFF_LINK2) == 0 && ifp) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in_pcb.c,v 1.167 2016/07/20 03:38:09 ozaki-r Exp $ */
|
||||
/* $NetBSD: in_pcb.c,v 1.168 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -93,7 +93,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.167 2016/07/20 03:38:09 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in_pcb.c,v 1.168 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -275,27 +275,39 @@ in_pcbsetport(struct sockaddr_in *sin, struct inpcb *inp, kauth_cred_t cred)
|
|||
static int
|
||||
in_pcbbind_addr(struct inpcb *inp, struct sockaddr_in *sin, kauth_cred_t cred)
|
||||
{
|
||||
int error = EADDRNOTAVAIL;
|
||||
struct ifaddr *ifa = NULL;
|
||||
int s;
|
||||
|
||||
if (sin->sin_family != AF_INET)
|
||||
return (EAFNOSUPPORT);
|
||||
|
||||
s = pserialize_read_enter();
|
||||
if (IN_MULTICAST(sin->sin_addr.s_addr)) {
|
||||
/* Always succeed; port reuse handled in in_pcbbind_port(). */
|
||||
} else if (!in_nullhost(sin->sin_addr)) {
|
||||
struct in_ifaddr *ia = NULL;
|
||||
struct in_ifaddr *ia;
|
||||
|
||||
ia = in_get_ia(sin->sin_addr);
|
||||
/* check for broadcast addresses */
|
||||
if (ia == NULL) {
|
||||
ifa = ifa_ifwithaddr(sintosa(sin));
|
||||
if (ifa != NULL)
|
||||
ia = ifatoia(ifa);
|
||||
}
|
||||
if (ia == NULL)
|
||||
ia = ifatoia(ifa_ifwithaddr(sintosa(sin)));
|
||||
if (ia == NULL)
|
||||
return (EADDRNOTAVAIL);
|
||||
goto error;
|
||||
if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED))
|
||||
return (EADDRNOTAVAIL);
|
||||
goto error;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
inp->inp_laddr = sin->sin_addr;
|
||||
|
||||
return (0);
|
||||
error:
|
||||
pserialize_read_exit(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -484,6 +496,7 @@ in_pcbconnect(void *v, struct sockaddr_in *sin, struct lwp *l)
|
|||
IN_ADDRLIST_READER_FIRST()->ia_addr.sin_addr;
|
||||
} else if (sin->sin_addr.s_addr == INADDR_BROADCAST) {
|
||||
struct in_ifaddr *ia;
|
||||
int s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
|
||||
sin->sin_addr =
|
||||
|
@ -491,6 +504,7 @@ in_pcbconnect(void *v, struct sockaddr_in *sin, struct lwp *l)
|
|||
break;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -507,26 +521,40 @@ in_pcbconnect(void *v, struct sockaddr_in *sin, struct lwp *l)
|
|||
*/
|
||||
if (in_nullhost(inp->inp_laddr)) {
|
||||
int xerror;
|
||||
struct sockaddr_in *ifaddr;
|
||||
struct in_ifaddr *ia;
|
||||
struct in_ifaddr *ia, *_ia;
|
||||
int s;
|
||||
struct psref psref;
|
||||
int bound;
|
||||
|
||||
ifaddr = in_selectsrc(sin, &inp->inp_route,
|
||||
inp->inp_socket->so_options, inp->inp_moptions, &xerror);
|
||||
if (ifaddr == NULL) {
|
||||
bound = curlwp_bind();
|
||||
ia = in_selectsrc(sin, &inp->inp_route,
|
||||
inp->inp_socket->so_options, inp->inp_moptions, &xerror,
|
||||
&psref);
|
||||
if (ia == NULL) {
|
||||
curlwp_bindx(bound);
|
||||
if (xerror == 0)
|
||||
xerror = EADDRNOTAVAIL;
|
||||
return xerror;
|
||||
}
|
||||
ia = in_get_ia(ifaddr->sin_addr);
|
||||
if (ia == NULL)
|
||||
s = pserialize_read_enter();
|
||||
_ia = in_get_ia(IA_SIN(ia)->sin_addr);
|
||||
if (_ia == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
ia4_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return (EADDRNOTAVAIL);
|
||||
laddr = ifaddr->sin_addr;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
laddr = IA_SIN(ia)->sin_addr;
|
||||
ia4_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
} else
|
||||
laddr = inp->inp_laddr;
|
||||
if (in_pcblookup_connect(inp->inp_table, sin->sin_addr, sin->sin_port,
|
||||
laddr, inp->inp_lport, &vestige) != 0
|
||||
|| vestige.valid)
|
||||
laddr, inp->inp_lport, &vestige) != NULL ||
|
||||
vestige.valid) {
|
||||
return (EADDRINUSE);
|
||||
}
|
||||
if (in_nullhost(inp->inp_laddr)) {
|
||||
if (inp->inp_lport == 0) {
|
||||
error = in_pcbbind(inp, NULL, l);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in_var.h,v 1.78 2016/07/08 04:33:30 ozaki-r Exp $ */
|
||||
/* $NetBSD: in_var.h,v 1.79 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -111,6 +111,25 @@ struct in_ifaddr {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
static inline void
|
||||
ia4_acquire(struct in_ifaddr *ia, struct psref *psref)
|
||||
{
|
||||
|
||||
KASSERT(ia != NULL);
|
||||
ifa_acquire(&ia->ia_ifa, psref);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ia4_release(struct in_ifaddr *ia, struct psref *psref)
|
||||
{
|
||||
|
||||
if (ia == NULL)
|
||||
return;
|
||||
ifa_release(&ia->ia_ifa, psref);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct in_aliasreq {
|
||||
char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */
|
||||
struct sockaddr_in ifra_addr;
|
||||
|
@ -125,6 +144,8 @@ struct in_aliasreq {
|
|||
*/
|
||||
#define IA_SIN(ia) (&(((struct in_ifaddr *)(ia))->ia_addr))
|
||||
|
||||
#define iatoifa(ia) (struct ifaddr *)(ia)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/* Note: 61, 127, 251, 509, 1021, 2039 are good. */
|
||||
|
@ -238,6 +259,21 @@ in_get_ia(struct in_addr addr)
|
|||
return ia;
|
||||
}
|
||||
|
||||
static inline struct in_ifaddr *
|
||||
in_get_ia_psref(struct in_addr addr, struct psref *psref)
|
||||
{
|
||||
struct in_ifaddr *ia;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia = in_get_ia(addr);
|
||||
if (ia != NULL)
|
||||
ia4_acquire(ia, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ia;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find whether an internet address (in_addr) belongs to a specified
|
||||
* interface. NULL if the address isn't ours.
|
||||
|
@ -256,6 +292,21 @@ in_get_ia_on_iface(struct in_addr addr, struct ifnet *ifp)
|
|||
return ia;
|
||||
}
|
||||
|
||||
static inline struct in_ifaddr *
|
||||
in_get_ia_on_iface_psref(struct in_addr addr, struct ifnet *ifp, struct psref *psref)
|
||||
{
|
||||
struct in_ifaddr *ia;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia = in_get_ia_on_iface(addr, ifp);
|
||||
if (ia != NULL)
|
||||
ia4_acquire(ia, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ia;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an internet address structure (in_ifaddr) corresponding
|
||||
* to a given interface (ifnet structure).
|
||||
|
@ -273,6 +324,21 @@ in_get_ia_from_ifp(struct ifnet *ifp)
|
|||
return ifatoia(ifa);
|
||||
}
|
||||
|
||||
static inline struct in_ifaddr *
|
||||
in_get_ia_from_ifp_psref(struct ifnet *ifp, struct psref *psref)
|
||||
{
|
||||
struct in_ifaddr *ia;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia = in_get_ia_from_ifp(ifp);
|
||||
if (ia != NULL)
|
||||
ia4_acquire(ia, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ia;
|
||||
}
|
||||
|
||||
#include <netinet/in_selsrc.h>
|
||||
/*
|
||||
* IPv4 per-interface state.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_carp.c,v 1.76 2016/07/23 13:37:10 is Exp $ */
|
||||
/* $NetBSD: ip_carp.c,v 1.77 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
/* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -33,7 +33,7 @@
|
|||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.76 2016/07/23 13:37:10 is Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.77 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
|
@ -635,15 +635,18 @@ carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
|
|||
if ((sc->sc_carpdev->if_flags & IFF_SIMPLEX) == 0) {
|
||||
struct sockaddr sa;
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_family = af;
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev);
|
||||
|
||||
if (ifa && af == AF_INET) {
|
||||
struct ip *ip = mtod(m, struct ip *);
|
||||
if (ip->ip_src.s_addr ==
|
||||
ifatoia(ifa)->ia_addr.sin_addr.s_addr) {
|
||||
pserialize_read_exit(s);
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
|
@ -660,11 +663,13 @@ carp_proto_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
|
|||
if (IN6_IS_ADDR_LINKLOCAL(&in6_found))
|
||||
in6_found.s6_addr16[1] = 0;
|
||||
if (IN6_ARE_ADDR_EQUAL(&in6_src, &in6_found)) {
|
||||
pserialize_read_exit(s);
|
||||
m_freem(m);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* INET6 */
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
nanotime(&sc->sc_if.if_lastchange);
|
||||
|
@ -989,7 +994,6 @@ carp_send_ad(void *v)
|
|||
struct carp_header *ch_ptr;
|
||||
struct mbuf *m;
|
||||
int error, len, advbase, advskew, s;
|
||||
struct ifaddr *ifa;
|
||||
struct sockaddr sa;
|
||||
|
||||
KERNEL_LOCK(1, NULL);
|
||||
|
@ -1029,6 +1033,8 @@ carp_send_ad(void *v)
|
|||
#ifdef INET
|
||||
if (sc->sc_naddrs) {
|
||||
struct ip *ip;
|
||||
struct ifaddr *ifa;
|
||||
int _s;
|
||||
|
||||
MGETHDR(m, M_DONTWAIT, MT_HEADER);
|
||||
if (m == NULL) {
|
||||
|
@ -1057,12 +1063,14 @@ carp_send_ad(void *v)
|
|||
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_family = AF_INET;
|
||||
_s = pserialize_read_enter();
|
||||
ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev);
|
||||
if (ifa == NULL)
|
||||
ip->ip_src.s_addr = 0;
|
||||
else
|
||||
ip->ip_src.s_addr =
|
||||
ifatoia(ifa)->ia_addr.sin_addr.s_addr;
|
||||
pserialize_read_exit(_s);
|
||||
ip->ip_dst.s_addr = INADDR_CARP_GROUP;
|
||||
|
||||
ch_ptr = (struct carp_header *)(&ip[1]);
|
||||
|
@ -1110,6 +1118,8 @@ carp_send_ad(void *v)
|
|||
#ifdef INET6_notyet
|
||||
if (sc->sc_naddrs6) {
|
||||
struct ip6_hdr *ip6;
|
||||
struct ifaddr *ifa;
|
||||
int _s;
|
||||
|
||||
MGETHDR(m, M_DONTWAIT, MT_HEADER);
|
||||
if (m == NULL) {
|
||||
|
@ -1134,12 +1144,14 @@ carp_send_ad(void *v)
|
|||
/* set the source address */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_family = AF_INET6;
|
||||
_s = pserialize_read_enter();
|
||||
ifa = ifaof_ifpforaddr(&sa, sc->sc_carpdev);
|
||||
if (ifa == NULL) /* This should never happen with IPv6 */
|
||||
memset(&ip6->ip6_src, 0, sizeof(struct in6_addr));
|
||||
else
|
||||
bcopy(ifatoia6(ifa)->ia_addr.sin6_addr.s6_addr,
|
||||
&ip6->ip6_src, sizeof(struct in6_addr));
|
||||
pserialize_read_exit(_s);
|
||||
/* set the multicast destination */
|
||||
|
||||
ip6->ip6_dst.s6_addr16[0] = htons(0xff02);
|
||||
|
@ -1746,6 +1758,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
|
|||
struct ifnet *ifp = sc->sc_carpdev;
|
||||
struct in_ifaddr *ia, *ia_if;
|
||||
int error = 0;
|
||||
int s;
|
||||
|
||||
if (sin->sin_addr.s_addr == 0) {
|
||||
if (!(sc->sc_if.if_flags & IFF_UP))
|
||||
|
@ -1758,6 +1771,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
|
|||
|
||||
/* we have to do this by hand to ensure we don't match on ourselves */
|
||||
ia_if = NULL;
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
/* and, yeah, we need a multicast-capable iface too */
|
||||
if (ia->ia_ifp != &sc->sc_if &&
|
||||
|
@ -1776,9 +1790,11 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin)
|
|||
if (ifp != ia->ia_ifp)
|
||||
return (EADDRNOTAVAIL);
|
||||
} else {
|
||||
/* FIXME NOMPSAFE */
|
||||
ifp = ia->ia_ifp;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if ((error = carp_set_ifp(sc, ifp)))
|
||||
return (error);
|
||||
|
@ -1836,6 +1852,7 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
|
|||
struct ifnet *ifp = sc->sc_carpdev;
|
||||
struct in6_ifaddr *ia, *ia_if;
|
||||
int error = 0;
|
||||
int s;
|
||||
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
if (!(sc->sc_if.if_flags & IFF_UP))
|
||||
|
@ -1848,6 +1865,7 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
|
|||
|
||||
/* we have to do this by hand to ensure we don't match on ourselves */
|
||||
ia_if = NULL;
|
||||
s = pserialize_read_enter();
|
||||
IN6_ADDRLIST_READER_FOREACH(ia) {
|
||||
int i;
|
||||
|
||||
|
@ -1867,6 +1885,7 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6)
|
|||
ia_if = ia;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (ia_if) {
|
||||
ia = ia_if;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_icmp.c,v 1.150 2016/07/08 04:33:30 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip_icmp.c,v 1.151 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -94,7 +94,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.150 2016/07/08 04:33:30 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_icmp.c,v 1.151 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -562,7 +562,8 @@ icmp_input(struct mbuf *m, ...)
|
|||
|
||||
case ICMP_MASKREQ: {
|
||||
struct ifnet *rcvif;
|
||||
int s;
|
||||
int s, ss;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
if (icmpmaskrepl == 0)
|
||||
break;
|
||||
|
@ -579,12 +580,15 @@ icmp_input(struct mbuf *m, ...)
|
|||
icmpdst.sin_addr = ip->ip_src;
|
||||
else
|
||||
icmpdst.sin_addr = ip->ip_dst;
|
||||
ss = pserialize_read_enter();
|
||||
rcvif = m_get_rcvif(m, &s);
|
||||
ia = ifatoia(ifaof_ifpforaddr(sintosa(&icmpdst),
|
||||
rcvif));
|
||||
ifa = ifaof_ifpforaddr(sintosa(&icmpdst), rcvif);
|
||||
m_put_rcvif(rcvif, &s);
|
||||
if (ia == 0)
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(ss);
|
||||
break;
|
||||
}
|
||||
ia = ifatoia(ifa);
|
||||
icp->icmp_type = ICMP_MASKREPLY;
|
||||
icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
|
||||
if (in_nullhost(ip->ip_src)) {
|
||||
|
@ -593,6 +597,7 @@ icmp_input(struct mbuf *m, ...)
|
|||
else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
|
||||
ip->ip_src = ia->ia_dstaddr.sin_addr;
|
||||
}
|
||||
pserialize_read_exit(ss);
|
||||
reflect:
|
||||
{
|
||||
uint64_t *icps = percpu_getref(icmpstat_percpu);
|
||||
|
@ -693,7 +698,11 @@ icmp_reflect(struct mbuf *m)
|
|||
struct mbuf *opts = NULL;
|
||||
int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
|
||||
struct ifnet *rcvif;
|
||||
struct psref psref;
|
||||
struct psref psref, psref_ia;
|
||||
int s;
|
||||
int bound;
|
||||
|
||||
bound = curlwp_bind();
|
||||
|
||||
if (!in_canforward(ip->ip_src) &&
|
||||
((ip->ip_src.s_addr & IN_CLASSA_NET) !=
|
||||
|
@ -712,15 +721,18 @@ icmp_reflect(struct mbuf *m)
|
|||
*/
|
||||
|
||||
/* Look for packet addressed to us */
|
||||
ia = in_get_ia(t);
|
||||
if (ia && (ia->ia4_flags & IN_IFF_NOTREADY))
|
||||
ia = in_get_ia_psref(t, &psref_ia);
|
||||
if (ia && (ia->ia4_flags & IN_IFF_NOTREADY)) {
|
||||
ia4_release(ia, &psref_ia);
|
||||
ia = NULL;
|
||||
}
|
||||
|
||||
rcvif = m_get_rcvif_psref(m, &psref);
|
||||
|
||||
/* look for packet sent to broadcast address */
|
||||
if (ia == NULL && rcvif &&
|
||||
(rcvif->if_flags & IFF_BROADCAST)) {
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, rcvif) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
|
@ -731,6 +743,9 @@ icmp_reflect(struct mbuf *m)
|
|||
ia = NULL;
|
||||
}
|
||||
}
|
||||
if (ia != NULL)
|
||||
ia4_acquire(ia, &psref_ia);
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
sin = ia ? &ia->ia_addr : NULL;
|
||||
|
@ -751,14 +766,17 @@ icmp_reflect(struct mbuf *m)
|
|||
sockaddr_in_init(&sin_dst, &ip->ip_dst, 0);
|
||||
memset(&icmproute, 0, sizeof(icmproute));
|
||||
errornum = 0;
|
||||
sin = in_selectsrc(&sin_dst, &icmproute, 0, NULL, &errornum);
|
||||
ia = in_selectsrc(&sin_dst, &icmproute, 0, NULL, &errornum,
|
||||
&psref_ia);
|
||||
/* errornum is never used */
|
||||
rtcache_free(&icmproute);
|
||||
/* check to make sure sin is a source address on rcvif */
|
||||
if (sin) {
|
||||
if (ia != NULL) {
|
||||
sin = &ia->ia_addr;
|
||||
t = sin->sin_addr;
|
||||
sin = NULL;
|
||||
ia = in_get_ia_on_iface(t, rcvif);
|
||||
ia4_release(ia, &psref_ia);
|
||||
ia = in_get_ia_on_iface_psref(t, rcvif, &psref_ia);
|
||||
if (ia != NULL)
|
||||
sin = &ia->ia_addr;
|
||||
}
|
||||
|
@ -771,12 +789,16 @@ icmp_reflect(struct mbuf *m)
|
|||
* when the incoming packet was encapsulated
|
||||
*/
|
||||
if (sin == NULL && rcvif) {
|
||||
KASSERT(ia == NULL);
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, rcvif) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET)
|
||||
continue;
|
||||
sin = &(ifatoia(ifa)->ia_addr);
|
||||
ia4_acquire(ifatoia(ifa), &psref_ia);
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
m_put_rcvif_psref(rcvif, &psref);
|
||||
|
@ -787,19 +809,25 @@ icmp_reflect(struct mbuf *m)
|
|||
* We find the first AF_INET address on the first non-loopback
|
||||
* interface.
|
||||
*/
|
||||
if (sin == NULL)
|
||||
if (sin == NULL) {
|
||||
KASSERT(ia == NULL);
|
||||
s = pserialize_read_enter();
|
||||
IN_ADDRLIST_READER_FOREACH(ia) {
|
||||
if (ia->ia_ifp->if_flags & IFF_LOOPBACK)
|
||||
continue;
|
||||
sin = &ia->ia_addr;
|
||||
ia4_acquire(ia, &psref_ia);
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we still didn't find an address, punt. We could have an
|
||||
* interface up (and receiving packets) with no address.
|
||||
*/
|
||||
if (sin == NULL) {
|
||||
KASSERT(ia == NULL);
|
||||
m_freem(m);
|
||||
goto done;
|
||||
}
|
||||
|
@ -807,6 +835,9 @@ icmp_reflect(struct mbuf *m)
|
|||
ip->ip_src = sin->sin_addr;
|
||||
ip->ip_ttl = MAXTTL;
|
||||
|
||||
if (ia != NULL)
|
||||
ia4_release(ia, &psref_ia);
|
||||
|
||||
if (optlen > 0) {
|
||||
u_char *cp;
|
||||
int opt, cnt;
|
||||
|
@ -890,6 +921,7 @@ icmp_reflect(struct mbuf *m)
|
|||
|
||||
icmp_send(m, opts);
|
||||
done:
|
||||
curlwp_bindx(bound);
|
||||
if (opts)
|
||||
(void)m_free(opts);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_input.c,v 1.338 2016/07/26 08:34:55 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip_input.c,v 1.339 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -91,7 +91,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.338 2016/07/26 08:34:55 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.339 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -447,12 +447,13 @@ static void
|
|||
ip_input(struct mbuf *m)
|
||||
{
|
||||
struct ip *ip = NULL;
|
||||
struct in_ifaddr *ia;
|
||||
struct in_ifaddr *ia = NULL;
|
||||
int hlen = 0, len;
|
||||
int downmatch;
|
||||
int srcrt = 0;
|
||||
ifnet_t *ifp;
|
||||
struct psref psref;
|
||||
int s;
|
||||
|
||||
KASSERTMSG(cpu_softintr_p(), "ip_input: not in the software "
|
||||
"interrupt handler; synchronization assumptions violated");
|
||||
|
@ -665,15 +666,21 @@ ip_input(struct mbuf *m)
|
|||
* or IN_IFF_NOTREADY addresses as not mine.
|
||||
*/
|
||||
downmatch = 0;
|
||||
s = pserialize_read_enter();
|
||||
ia = ip_match_our_address(ifp, ip, &downmatch);
|
||||
if (ia != NULL)
|
||||
if (ia != NULL) {
|
||||
pserialize_read_exit(s);
|
||||
goto ours;
|
||||
}
|
||||
|
||||
if (ifp->if_flags & IFF_BROADCAST) {
|
||||
ia = ip_match_our_address_broadcast(ifp, ip);
|
||||
if (ia != NULL)
|
||||
if (ia != NULL) {
|
||||
pserialize_read_exit(s);
|
||||
goto ours;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (IN_MULTICAST(ip->ip_dst.s_addr)) {
|
||||
#ifdef MROUTING
|
||||
|
@ -810,8 +817,17 @@ ours:
|
|||
* Switch out to protocol's input routine.
|
||||
*/
|
||||
#if IFA_STATS
|
||||
if (ia && ip)
|
||||
ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len);
|
||||
if (ia && ip) {
|
||||
struct in_ifaddr *_ia;
|
||||
/*
|
||||
* Keep a reference from ip_match_our_address with psref
|
||||
* is expensive, so explore ia here again.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
_ia = in_get_ia(ip->ip_dst.s_addr);
|
||||
_ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len);
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
#endif
|
||||
IP_STATINC(IP_STAT_DELIVERED);
|
||||
|
||||
|
@ -873,6 +889,8 @@ ip_dooptions(struct mbuf *m)
|
|||
int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
|
||||
struct in_addr dst;
|
||||
n_time ntime;
|
||||
struct ifaddr *ifa;
|
||||
int s;
|
||||
|
||||
dst = ip->ip_dst;
|
||||
cp = (u_char *)(ip + 1);
|
||||
|
@ -924,8 +942,11 @@ ip_dooptions(struct mbuf *m)
|
|||
goto bad;
|
||||
}
|
||||
ipaddr.sin_addr = ip->ip_dst;
|
||||
ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)));
|
||||
if (ia == 0) {
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(sintosa(&ipaddr));
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
if (opt == IPOPT_SSRR) {
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_SRCFAIL;
|
||||
|
@ -937,6 +958,8 @@ ip_dooptions(struct mbuf *m)
|
|||
*/
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
off--; /* 0 origin */
|
||||
if ((off + sizeof(struct in_addr)) > optlen) {
|
||||
/*
|
||||
|
@ -950,18 +973,26 @@ ip_dooptions(struct mbuf *m)
|
|||
*/
|
||||
memcpy((void *)&ipaddr.sin_addr, (void *)(cp + off),
|
||||
sizeof(ipaddr.sin_addr));
|
||||
if (opt == IPOPT_SSRR)
|
||||
ia = ifatoia(ifa_ifwithladdr(sintosa(&ipaddr)));
|
||||
else
|
||||
s = pserialize_read_enter();
|
||||
if (opt == IPOPT_SSRR) {
|
||||
ifa = ifa_ifwithladdr(sintosa(&ipaddr));
|
||||
if (ifa != NULL)
|
||||
ia = ifatoia(ifa);
|
||||
else
|
||||
ia = NULL;
|
||||
} else {
|
||||
ia = ip_rtaddr(ipaddr.sin_addr);
|
||||
if (ia == 0) {
|
||||
}
|
||||
if (ia == NULL) {
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_SRCFAIL;
|
||||
pserialize_read_exit(s);
|
||||
goto bad;
|
||||
}
|
||||
ip->ip_dst = ipaddr.sin_addr;
|
||||
bcopy((void *)&ia->ia_addr.sin_addr,
|
||||
(void *)(cp + off), sizeof(struct in_addr));
|
||||
pserialize_read_exit(s);
|
||||
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
|
||||
/*
|
||||
* Let ip_intr's mcast routing check handle mcast pkts
|
||||
|
@ -990,15 +1021,22 @@ ip_dooptions(struct mbuf *m)
|
|||
* locate outgoing interface; if we're the destination,
|
||||
* use the incoming interface (should be same).
|
||||
*/
|
||||
if ((ia = ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))))
|
||||
== NULL &&
|
||||
(ia = ip_rtaddr(ipaddr.sin_addr)) == NULL) {
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_HOST;
|
||||
goto bad;
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(sintosa(&ipaddr));
|
||||
if (ifa == NULL) {
|
||||
ia = ip_rtaddr(ipaddr.sin_addr);
|
||||
if (ia == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_HOST;
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
ia = ifatoia(ifa);
|
||||
}
|
||||
bcopy((void *)&ia->ia_addr.sin_addr,
|
||||
(void *)(cp + off), sizeof(struct in_addr));
|
||||
pserialize_read_exit(s);
|
||||
cp[IPOPT_OFFSET] += sizeof(struct in_addr);
|
||||
break;
|
||||
|
||||
|
@ -1029,7 +1067,7 @@ ip_dooptions(struct mbuf *m)
|
|||
|
||||
case IPOPT_TS_TSANDADDR: {
|
||||
struct ifnet *rcvif;
|
||||
int s;
|
||||
int _s, _ss;
|
||||
|
||||
if (ipt->ipt_ptr - 1 + sizeof(n_time) +
|
||||
sizeof(struct in_addr) > ipt->ipt_len) {
|
||||
|
@ -1038,14 +1076,18 @@ ip_dooptions(struct mbuf *m)
|
|||
goto bad;
|
||||
}
|
||||
ipaddr.sin_addr = dst;
|
||||
rcvif = m_get_rcvif(m, &s);
|
||||
ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr),
|
||||
rcvif));
|
||||
m_put_rcvif(rcvif, &s);
|
||||
if (ia == 0)
|
||||
continue;
|
||||
_ss = pserialize_read_enter();
|
||||
rcvif = m_get_rcvif(m, &_s);
|
||||
ifa = ifaof_ifpforaddr(sintosa(&ipaddr), rcvif);
|
||||
m_put_rcvif(rcvif, &_s);
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(_ss);
|
||||
break;
|
||||
}
|
||||
ia = ifatoia(ifa);
|
||||
bcopy(&ia->ia_addr.sin_addr,
|
||||
cp0, sizeof(struct in_addr));
|
||||
pserialize_read_exit(_ss);
|
||||
ipt->ipt_ptr += sizeof(struct in_addr);
|
||||
break;
|
||||
}
|
||||
|
@ -1059,9 +1101,13 @@ ip_dooptions(struct mbuf *m)
|
|||
}
|
||||
memcpy(&ipaddr.sin_addr, cp0,
|
||||
sizeof(struct in_addr));
|
||||
if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)))
|
||||
== NULL)
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(sintosa(&ipaddr));
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
continue;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
ipt->ipt_ptr += sizeof(struct in_addr);
|
||||
break;
|
||||
|
||||
|
@ -1080,7 +1126,7 @@ ip_dooptions(struct mbuf *m)
|
|||
}
|
||||
if (forward) {
|
||||
struct ifnet *rcvif;
|
||||
struct psref psref;
|
||||
struct psref _psref;
|
||||
|
||||
if (ip_forwsrcrt == 0) {
|
||||
type = ICMP_UNREACH;
|
||||
|
@ -1088,14 +1134,14 @@ ip_dooptions(struct mbuf *m)
|
|||
goto bad;
|
||||
}
|
||||
|
||||
rcvif = m_get_rcvif_psref(m, &psref);
|
||||
rcvif = m_get_rcvif_psref(m, &_psref);
|
||||
if (__predict_false(rcvif == NULL)) {
|
||||
type = ICMP_UNREACH;
|
||||
code = ICMP_UNREACH_HOST;
|
||||
goto bad;
|
||||
}
|
||||
ip_forward(m, 1, rcvif);
|
||||
m_put_rcvif_psref(rcvif, &psref);
|
||||
m_put_rcvif_psref(rcvif, &_psref);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_mroute.c,v 1.143 2016/07/04 04:35:09 knakahara Exp $ */
|
||||
/* $NetBSD: ip_mroute.c,v 1.144 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -93,7 +93,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_mroute.c,v 1.143 2016/07/04 04:35:09 knakahara Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_mroute.c,v 1.144 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -785,7 +785,6 @@ static int
|
|||
add_vif(struct vifctl *vifcp)
|
||||
{
|
||||
struct vif *vifp;
|
||||
struct ifaddr *ifa;
|
||||
struct ifnet *ifp;
|
||||
int error, s;
|
||||
struct sockaddr_in sin;
|
||||
|
@ -811,11 +810,18 @@ add_vif(struct vifctl *vifcp)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
|
||||
sockaddr_in_init(&sin, &vifcp->vifc_lcl_addr, 0);
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(sintosa(&sin));
|
||||
if (ifa == NULL)
|
||||
return (EADDRNOTAVAIL);
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
ifp = ifa->ifa_ifp;
|
||||
/* FIXME NOMPSAFE */
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
if (vifcp->vifc_flags & VIFF_TUNNEL) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip_output.c,v 1.259 2016/07/08 04:33:30 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip_output.c,v 1.260 2016/08/01 03:15:30 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -91,7 +91,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.259 2016/07/08 04:33:30 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.260 2016/08/01 03:15:30 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -112,6 +112,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.259 2016/07/08 04:33:30 ozaki-r Exp
|
|||
#include <sys/domain.h>
|
||||
#endif
|
||||
#include <sys/systm.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
|
@ -235,7 +236,7 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
int len, error = 0;
|
||||
struct route iproute;
|
||||
const struct sockaddr_in *dst;
|
||||
struct in_ifaddr *ia;
|
||||
struct in_ifaddr *ia = NULL;
|
||||
int isbroadcast;
|
||||
int sw_csum;
|
||||
u_long mtu;
|
||||
|
@ -251,8 +252,9 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
struct sockaddr *rdst = &u.dst; /* real IP destination, as opposed
|
||||
* to the nexthop
|
||||
*/
|
||||
struct psref psref;
|
||||
struct psref psref, psref_ia;
|
||||
int bound;
|
||||
bool bind_need_restore = false;
|
||||
|
||||
len = 0;
|
||||
|
||||
|
@ -311,15 +313,23 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
goto bad;
|
||||
}
|
||||
|
||||
bound = curlwp_bind();
|
||||
bind_need_restore = true;
|
||||
/*
|
||||
* If routing to interface only, short circuit routing lookup.
|
||||
*/
|
||||
if (flags & IP_ROUTETOIF) {
|
||||
if ((ia = ifatoia(ifa_ifwithladdr(sintocsa(dst)))) == NULL) {
|
||||
struct ifaddr *ifa;
|
||||
|
||||
ifa = ifa_ifwithladdr_psref(sintocsa(dst), &psref_ia);
|
||||
if (ifa == NULL) {
|
||||
IP_STATINC(IP_STAT_NOROUTE);
|
||||
error = ENETUNREACH;
|
||||
goto bad;
|
||||
}
|
||||
/* ia is already referenced by psref_ia */
|
||||
ia = ifatoia(ifa);
|
||||
|
||||
ifp = ia->ia_ifp;
|
||||
mtu = ifp->if_mtu;
|
||||
ip->ip_ttl = 1;
|
||||
|
@ -327,16 +337,18 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
} else if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
|
||||
ip->ip_dst.s_addr == INADDR_BROADCAST) &&
|
||||
imo != NULL && imo->imo_multicast_if_index != 0) {
|
||||
bound = curlwp_bind();
|
||||
ifp = mifp = if_get_byindex(imo->imo_multicast_if_index, &psref);
|
||||
if (ifp == NULL) {
|
||||
curlwp_bindx(bound);
|
||||
IP_STATINC(IP_STAT_NOROUTE);
|
||||
error = ENETUNREACH;
|
||||
goto bad;
|
||||
}
|
||||
mtu = ifp->if_mtu;
|
||||
ia = in_get_ia_from_ifp(ifp);
|
||||
ia = in_get_ia_from_ifp_psref(ifp, &psref_ia);
|
||||
if (ia == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
isbroadcast = 0;
|
||||
} else {
|
||||
if (rt == NULL)
|
||||
|
@ -346,6 +358,11 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
error = EHOSTUNREACH;
|
||||
goto bad;
|
||||
}
|
||||
/*
|
||||
* XXX NOMPSAFE: depends on accessing rt->rt_ifa isn't racy.
|
||||
* Revisit when working on rtentry MP-ification.
|
||||
*/
|
||||
ifa_acquire(rt->rt_ifa, &psref_ia);
|
||||
ia = ifatoia(rt->rt_ifa);
|
||||
ifp = rt->rt_ifp;
|
||||
if ((mtu = rt->rt_rmx.rmx_mtu) == 0)
|
||||
|
@ -403,21 +420,26 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
if (in_nullhost(ip->ip_src)) {
|
||||
struct in_ifaddr *xia;
|
||||
struct ifaddr *xifa;
|
||||
struct psref _psref;
|
||||
|
||||
xia = in_get_ia_from_ifp(ifp);
|
||||
xia = in_get_ia_from_ifp_psref(ifp, &_psref);
|
||||
if (!xia) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
xifa = &xia->ia_ifa;
|
||||
if (xifa->ifa_getifa != NULL) {
|
||||
ia4_release(xia, &_psref);
|
||||
/* FIXME NOMPSAFE */
|
||||
xia = ifatoia((*xifa->ifa_getifa)(xifa, rdst));
|
||||
if (xia == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
ia4_acquire(xia, &_psref);
|
||||
}
|
||||
ip->ip_src = xia->ia_addr.sin_addr;
|
||||
ia4_release(xia, &_psref);
|
||||
}
|
||||
|
||||
inmgroup = in_multi_group(ip->ip_dst, ifp, flags);
|
||||
|
@ -477,11 +499,14 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags,
|
|||
|
||||
xifa = &ia->ia_ifa;
|
||||
if (xifa->ifa_getifa != NULL) {
|
||||
ia4_release(ia, &psref_ia);
|
||||
/* FIXME NOMPSAFE */
|
||||
ia = ifatoia((*xifa->ifa_getifa)(xifa, rdst));
|
||||
if (ia == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto bad;
|
||||
}
|
||||
ia4_acquire(ia, &psref_ia);
|
||||
}
|
||||
ip->ip_src = ia->ia_addr.sin_addr;
|
||||
}
|
||||
|
@ -543,6 +568,10 @@ sendit:
|
|||
ip->ip_id = ip_newid_range(ia, num);
|
||||
}
|
||||
}
|
||||
if (ia != NULL) {
|
||||
ia4_release(ia, &psref_ia);
|
||||
ia = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're doing Path MTU Discovery, we need to set DF unless
|
||||
|
@ -583,7 +612,8 @@ sendit:
|
|||
* search for the source address structure to
|
||||
* maintain output statistics.
|
||||
*/
|
||||
ia = in_get_ia(ip->ip_src);
|
||||
KASSERT(ia == NULL);
|
||||
ia = in_get_ia_psref(ip->ip_src, &psref_ia);
|
||||
#endif
|
||||
|
||||
/* Maybe skip checksums on loopback interfaces. */
|
||||
|
@ -713,6 +743,7 @@ sendit:
|
|||
IP_STATINC(IP_STAT_FRAGMENTED);
|
||||
}
|
||||
done:
|
||||
ia4_release(ia, &psref_ia);
|
||||
if (ro == &iproute) {
|
||||
rtcache_free(&iproute);
|
||||
}
|
||||
|
@ -723,8 +754,9 @@ done:
|
|||
#endif
|
||||
if (mifp != NULL) {
|
||||
if_put(mifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
}
|
||||
if (bind_need_restore)
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
bad:
|
||||
m_freem(m);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: raw_ip.c,v 1.158 2016/05/12 02:24:17 ozaki-r Exp $ */
|
||||
/* $NetBSD: raw_ip.c,v 1.159 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -65,7 +65,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.158 2016/05/12 02:24:17 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.159 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -554,8 +554,8 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
|
|||
struct inpcb *inp = sotoinpcb(so);
|
||||
struct sockaddr_in *addr = (struct sockaddr_in *)nam;
|
||||
int error = 0;
|
||||
int s;
|
||||
struct ifaddr *ia;
|
||||
int s, ss;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
KASSERT(solocked(so));
|
||||
KASSERT(inp != NULL);
|
||||
|
@ -573,18 +573,22 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
|
|||
error = EAFNOSUPPORT;
|
||||
goto release;
|
||||
}
|
||||
if ((ia = ifa_ifwithaddr(sintosa(addr))) == 0 &&
|
||||
ss = pserialize_read_enter();
|
||||
if ((ifa = ifa_ifwithaddr(sintosa(addr))) == NULL &&
|
||||
!in_nullhost(addr->sin_addr))
|
||||
{
|
||||
pserialize_read_exit(ss);
|
||||
error = EADDRNOTAVAIL;
|
||||
goto release;
|
||||
}
|
||||
if (ia && ((struct in_ifaddr *)ia)->ia4_flags &
|
||||
if (ifa && (ifatoia(ifa))->ia4_flags &
|
||||
(IN6_IFF_NOTREADY | IN_IFF_DETACHED))
|
||||
{
|
||||
pserialize_read_exit(ss);
|
||||
error = EADDRNOTAVAIL;
|
||||
goto release;
|
||||
}
|
||||
pserialize_read_exit(ss);
|
||||
|
||||
inp->inp_laddr = addr->sin_addr;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: icmp6.c,v 1.194 2016/07/15 07:40:09 ozaki-r Exp $ */
|
||||
/* $NetBSD: icmp6.c,v 1.195 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.194 2016/07/15 07:40:09 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: icmp6.c,v 1.195 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -160,7 +160,7 @@ static struct mbuf *ni6_input(struct mbuf *, int);
|
|||
static struct mbuf *ni6_nametodns(const char *, int, int);
|
||||
static int ni6_dnsmatch(const char *, int, const char *, int);
|
||||
static int ni6_addrs(struct icmp6_nodeinfo *, struct mbuf *,
|
||||
struct ifnet **, char *);
|
||||
struct ifnet **, char *, struct psref *);
|
||||
static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *,
|
||||
struct ifnet *, int);
|
||||
static int icmp6_notify_error(struct mbuf *, int, int, int);
|
||||
|
@ -1200,8 +1200,10 @@ ni6_input(struct mbuf *m, int off)
|
|||
struct ip6_hdr *ip6;
|
||||
int oldfqdn = 0; /* if 1, return pascal string (03 draft) */
|
||||
char *subj = NULL;
|
||||
int s;
|
||||
struct ifnet *rcvif;
|
||||
int s, ss;
|
||||
struct ifaddr *ifa;
|
||||
struct psref psref;
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
IP6_EXTHDR_GET(ni6, struct icmp6_nodeinfo *, m, off, sizeof(*ni6));
|
||||
|
@ -1220,12 +1222,17 @@ ni6_input(struct mbuf *m, int off)
|
|||
*/
|
||||
sockaddr_in6_init(&sin6, &ip6->ip6_dst, 0, 0, 0);
|
||||
/* XXX scopeid */
|
||||
if (ifa_ifwithaddr(sin6tosa(&sin6)))
|
||||
ss = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(sin6tosa(&sin6));
|
||||
if (ifa != NULL)
|
||||
; /* unicast/anycast, fine */
|
||||
else if (IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr))
|
||||
; /* link-local multicast, fine */
|
||||
else
|
||||
else {
|
||||
pserialize_read_exit(ss);
|
||||
goto bad;
|
||||
}
|
||||
pserialize_read_exit(ss);
|
||||
|
||||
/* validate query Subject field. */
|
||||
qtype = ntohs(ni6->ni_qtype);
|
||||
|
@ -1359,7 +1366,7 @@ ni6_input(struct mbuf *m, int off)
|
|||
replylen += offsetof(struct ni_reply_fqdn, ni_fqdn_namelen);
|
||||
break;
|
||||
case NI_QTYPE_NODEADDR:
|
||||
addrs = ni6_addrs(ni6, m, &ifp, subj);
|
||||
addrs = ni6_addrs(ni6, m, &ifp, subj, &psref);
|
||||
if ((replylen += addrs * (sizeof(struct in6_addr) +
|
||||
sizeof(u_int32_t))) > MCLBYTES)
|
||||
replylen = MCLBYTES; /* XXX: will truncate pkt later */
|
||||
|
@ -1387,6 +1394,7 @@ ni6_input(struct mbuf *m, int off)
|
|||
/* allocate an mbuf to reply. */
|
||||
MGETHDR(n, M_DONTWAIT, m->m_type);
|
||||
if (n == NULL) {
|
||||
if_put(ifp, &psref);
|
||||
m_freem(m);
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -1454,6 +1462,8 @@ ni6_input(struct mbuf *m, int off)
|
|||
sizeof(struct ip6_hdr) + sizeof(struct icmp6_nodeinfo);
|
||||
lenlim = M_TRAILINGSPACE(n);
|
||||
copied = ni6_store_addrs(ni6, nni6, ifp, lenlim);
|
||||
if_put(ifp, &psref);
|
||||
ifp = NULL;
|
||||
/* XXX: reset mbuf length */
|
||||
n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) +
|
||||
sizeof(struct icmp6_nodeinfo) + copied;
|
||||
|
@ -1468,6 +1478,7 @@ ni6_input(struct mbuf *m, int off)
|
|||
return (n);
|
||||
|
||||
bad:
|
||||
if_put(ifp, &psref);
|
||||
m_freem(m);
|
||||
if (n)
|
||||
m_freem(n);
|
||||
|
@ -1657,7 +1668,7 @@ ni6_dnsmatch(const char *a, int alen, const char *b, int blen)
|
|||
*/
|
||||
static int
|
||||
ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m,
|
||||
struct ifnet **ifpp, char *subj)
|
||||
struct ifnet **ifpp, char *subj, struct psref *psref)
|
||||
{
|
||||
struct ifnet *ifp;
|
||||
struct in6_ifaddr *ia6;
|
||||
|
@ -1665,6 +1676,7 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m,
|
|||
struct sockaddr_in6 *subj_ip6 = NULL; /* XXX pedant */
|
||||
int addrs = 0, addrsofif, iffound = 0;
|
||||
int niflags = ni6->ni_flags;
|
||||
int s;
|
||||
|
||||
if ((niflags & NI_NODEADDR_FLAG_ALL) == 0) {
|
||||
switch (ni6->ni_code) {
|
||||
|
@ -1682,6 +1694,7 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m,
|
|||
}
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IFNET_READER_FOREACH(ifp) {
|
||||
addrsofif = 0;
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
|
@ -1733,12 +1746,15 @@ ni6_addrs(struct icmp6_nodeinfo *ni6, struct mbuf *m,
|
|||
addrsofif++; /* count the address */
|
||||
}
|
||||
if (iffound) {
|
||||
if_acquire_NOMPSAFE(ifp, psref);
|
||||
pserialize_read_exit(s);
|
||||
*ifpp = ifp;
|
||||
return (addrsofif);
|
||||
}
|
||||
|
||||
addrs += addrsofif;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return (addrs);
|
||||
}
|
||||
|
@ -1748,7 +1764,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6,
|
|||
struct icmp6_nodeinfo *nni6, struct ifnet *ifp0,
|
||||
int resid)
|
||||
{
|
||||
struct ifnet *ifp = ifp0 ? ifp0 : IFNET_READER_FIRST();
|
||||
struct ifnet *ifp;
|
||||
struct in6_ifaddr *ia6;
|
||||
struct ifaddr *ifa;
|
||||
struct ifnet *ifp_dep = NULL;
|
||||
|
@ -1756,10 +1772,13 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6,
|
|||
u_char *cp = (u_char *)(nni6 + 1);
|
||||
int niflags = ni6->ni_flags;
|
||||
u_int32_t ltime;
|
||||
int s;
|
||||
|
||||
if (ifp0 == NULL && !(niflags & NI_NODEADDR_FLAG_ALL))
|
||||
return (0); /* needless to copy */
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifp = ifp0 ? ifp0 : IFNET_READER_FIRST();
|
||||
again:
|
||||
|
||||
for (; ifp; ifp = IFNET_READER_NEXT(ifp))
|
||||
|
@ -1820,7 +1839,7 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6,
|
|||
* Set the truncate flag and return.
|
||||
*/
|
||||
nni6->ni_flags |= NI_NODEADDR_FLAG_TRUNCATE;
|
||||
return (copied);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1876,7 +1895,8 @@ ni6_store_addrs(struct icmp6_nodeinfo *ni6,
|
|||
|
||||
goto again;
|
||||
}
|
||||
|
||||
out:
|
||||
pserialize_read_exit(s);
|
||||
return (copied);
|
||||
}
|
||||
|
||||
|
@ -2067,16 +2087,21 @@ icmp6_reflect(struct mbuf *m, size_t off)
|
|||
struct sockaddr_in6 sin6;
|
||||
struct sockaddr sa;
|
||||
} u;
|
||||
int _s;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
sockaddr_in6_init(&u.sin6, &origdst, 0, 0, 0);
|
||||
|
||||
ia = ifatoia6(ifa_ifwithaddr(&u.sa));
|
||||
_s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(&u.sa);
|
||||
|
||||
if (ia == NULL)
|
||||
;
|
||||
else if ((ia->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0)
|
||||
src = &ia->ia_addr.sin6_addr;
|
||||
if (ifa != NULL) {
|
||||
ia = ifatoia6(ifa);
|
||||
if ((ia->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) == 0)
|
||||
src = &ia->ia_addr.sin6_addr;
|
||||
}
|
||||
pserialize_read_exit(_s);
|
||||
}
|
||||
|
||||
if (src == NULL) {
|
||||
|
@ -2438,11 +2463,15 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
|
|||
{
|
||||
/* get ip6 linklocal address for ifp(my outgoing interface). */
|
||||
struct in6_ifaddr *ia;
|
||||
int s = pserialize_read_enter();
|
||||
if ((ia = in6ifa_ifpforlinklocal(ifp,
|
||||
IN6_IFF_NOTREADY|
|
||||
IN6_IFF_ANYCAST)) == NULL)
|
||||
IN6_IFF_ANYCAST)) == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
goto fail;
|
||||
}
|
||||
ifp_ll6 = &ia->ia_addr.sin6_addr;
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/* get ip6 linklocal address for the router. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6.c,v 1.212 2016/07/28 09:03:50 ozaki-r Exp $ */
|
||||
/* $NetBSD: in6.c,v 1.213 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.212 2016/07/28 09:03:50 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.213 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -143,6 +143,7 @@ const struct sockaddr_in6 sa6_any = {sizeof(sa6_any), AF_INET6,
|
|||
0, 0, IN6ADDR_ANY_INIT, 0};
|
||||
|
||||
struct pslist_head in6_ifaddr_list;
|
||||
kmutex_t in6_ifaddr_lock;
|
||||
|
||||
static int in6_lifaddr_ioctl(struct socket *, u_long, void *,
|
||||
struct ifnet *);
|
||||
|
@ -155,6 +156,7 @@ in6_init(void)
|
|||
{
|
||||
|
||||
PSLIST_INIT(&in6_ifaddr_list);
|
||||
mutex_init(&in6_ifaddr_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -189,6 +191,8 @@ in6_ifremlocal(struct ifaddr *ifa)
|
|||
struct in6_ifaddr *ia;
|
||||
struct ifaddr *alt_ifa = NULL;
|
||||
int ia_count = 0;
|
||||
struct psref psref;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* Some of BSD variants do not remove cloned routes
|
||||
|
@ -218,6 +222,7 @@ in6_ifremlocal(struct ifaddr *ifa)
|
|||
* XXX agree, especially now that I have fixed the dangling
|
||||
* XXX ifp-pointers bug.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
IN6_ADDRLIST_READER_FOREACH(ia) {
|
||||
if (!IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr))
|
||||
continue;
|
||||
|
@ -226,11 +231,17 @@ in6_ifremlocal(struct ifaddr *ifa)
|
|||
if (++ia_count > 1 && alt_ifa != NULL)
|
||||
break;
|
||||
}
|
||||
if (ia_count > 1 && alt_ifa != NULL)
|
||||
ifa_acquire(alt_ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (ia_count == 0)
|
||||
return;
|
||||
|
||||
rt_ifa_remlocal(ifa, ia_count == 1 ? NULL : alt_ifa);
|
||||
|
||||
if (ia_count > 1 && alt_ifa != NULL)
|
||||
ifa_release(alt_ifa, &psref);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -279,7 +290,9 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
struct in6_ifaddr *ia = NULL;
|
||||
struct in6_aliasreq *ifra = (struct in6_aliasreq *)data;
|
||||
struct sockaddr_in6 *sa6;
|
||||
int error;
|
||||
int error, bound;
|
||||
struct psref psref;
|
||||
bool run_hooks = false;
|
||||
|
||||
switch (cmd) {
|
||||
case SIOCAADDRCTL_POLICY:
|
||||
|
@ -395,14 +408,17 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
sa6 = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
bound = curlwp_bind();
|
||||
if (sa6 && sa6->sin6_family == AF_INET6) {
|
||||
if (sa6->sin6_scope_id != 0)
|
||||
error = sa6_embedscope(sa6, 0);
|
||||
else
|
||||
error = in6_setscope(&sa6->sin6_addr, ifp, NULL);
|
||||
if (error != 0)
|
||||
return error;
|
||||
ia = in6ifa_ifpwithaddr(ifp, &sa6->sin6_addr);
|
||||
goto out;
|
||||
ia = in6ifa_ifpwithaddr_psref(ifp, &sa6->sin6_addr, &psref);
|
||||
} else
|
||||
ia = NULL;
|
||||
|
||||
|
@ -414,7 +430,8 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
* Since IPv6 allows a node to assign multiple addresses
|
||||
* on a single interface, SIOCSIFxxx ioctls are deprecated.
|
||||
*/
|
||||
return EINVAL;
|
||||
error = EINVAL;
|
||||
goto release;
|
||||
|
||||
case SIOCDIFADDR_IN6:
|
||||
/*
|
||||
|
@ -424,8 +441,10 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
* interface address from the day one, we consider "remove the
|
||||
* first one" semantics to be not preferable.
|
||||
*/
|
||||
if (ia == NULL)
|
||||
return EADDRNOTAVAIL;
|
||||
if (ia == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
#ifdef OSIOCAIFADDR_IN6
|
||||
case OSIOCAIFADDR_IN6:
|
||||
|
@ -436,8 +455,10 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
* the corresponding operation.
|
||||
*/
|
||||
if (ifra->ifra_addr.sin6_family != AF_INET6 ||
|
||||
ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6))
|
||||
return EAFNOSUPPORT;
|
||||
ifra->ifra_addr.sin6_len != sizeof(struct sockaddr_in6)) {
|
||||
error = EAFNOSUPPORT;
|
||||
goto release;
|
||||
}
|
||||
/* Privileged. */
|
||||
|
||||
break;
|
||||
|
@ -453,8 +474,10 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
case OSIOCGIFALIFETIME_IN6:
|
||||
#endif
|
||||
/* must think again about its semantics */
|
||||
if (ia == NULL)
|
||||
return EADDRNOTAVAIL;
|
||||
if (ia == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -463,19 +486,21 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
case SIOCGIFADDR_IN6:
|
||||
ifr->ifr_addr = ia->ia_addr;
|
||||
if ((error = sa6_recoverscope(&ifr->ifr_addr)) != 0)
|
||||
return error;
|
||||
break;
|
||||
break;
|
||||
|
||||
case SIOCGIFDSTADDR_IN6:
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
|
||||
return EINVAL;
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* XXX: should we check if ifa_dstaddr is NULL and return
|
||||
* an error?
|
||||
*/
|
||||
ifr->ifr_dstaddr = ia->ia_dstaddr;
|
||||
if ((error = sa6_recoverscope(&ifr->ifr_dstaddr)) != 0)
|
||||
return error;
|
||||
break;
|
||||
break;
|
||||
|
||||
case SIOCGIFNETMASK_IN6:
|
||||
|
@ -487,8 +512,10 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
|
||||
case SIOCGIFSTAT_IN6:
|
||||
if (ifp == NULL)
|
||||
return EINVAL;
|
||||
if (ifp == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
memset(&ifr->ifr_ifru.ifru_stat, 0,
|
||||
sizeof(ifr->ifr_ifru.ifru_stat));
|
||||
ifr->ifr_ifru.ifru_stat =
|
||||
|
@ -496,8 +523,10 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
|
||||
case SIOCGIFSTAT_ICMP6:
|
||||
if (ifp == NULL)
|
||||
return EINVAL;
|
||||
if (ifp == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
memset(&ifr->ifr_ifru.ifru_icmp6stat, 0,
|
||||
sizeof(ifr->ifr_ifru.ifru_icmp6stat));
|
||||
ifr->ifr_ifru.ifru_icmp6stat =
|
||||
|
@ -569,6 +598,8 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
struct nd_prefixctl prc0;
|
||||
struct nd_prefix *pr;
|
||||
struct in6_addrlifetime *lt;
|
||||
struct in6_ifaddr *_ia;
|
||||
int s;
|
||||
|
||||
/* reject read-only flags */
|
||||
if ((ifra->ifra_flags & IN6_IFF_DUPLICATED) != 0 ||
|
||||
|
@ -576,7 +607,8 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
(ifra->ifra_flags & IN6_IFF_TENTATIVE) != 0 ||
|
||||
(ifra->ifra_flags & IN6_IFF_NODAD) != 0 ||
|
||||
(ifra->ifra_flags & IN6_IFF_AUTOCONF) != 0) {
|
||||
return EINVAL;
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* ia6t_expire and ia6t_preferred won't be used for now,
|
||||
|
@ -589,19 +621,31 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
lt->ia6t_preferred =
|
||||
time_wall_to_mono(lt->ia6t_preferred);
|
||||
/*
|
||||
* first, make or update the interface address structure,
|
||||
* and link it to the list.
|
||||
* first, make (ia == NULL) or update (ia != NULL) the interface
|
||||
* address structure, and link it to the list.
|
||||
*/
|
||||
if ((error = in6_update_ifa(ifp, ifra, ia, 0)) != 0)
|
||||
return error;
|
||||
if ((ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr))
|
||||
== NULL) {
|
||||
break;
|
||||
s = pserialize_read_enter();
|
||||
_ia = in6ifa_ifpwithaddr(ifp, &ifra->ifra_addr.sin6_addr);
|
||||
if (_ia == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
/*
|
||||
* this can happen when the user specify the 0 valid
|
||||
* lifetime.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If ia == NULL, _ia has been created and we need to acquire
|
||||
* a reference. Otherwise, a reference is already taken.
|
||||
*/
|
||||
if (ia == NULL) {
|
||||
ia6_acquire(_ia, &psref);
|
||||
ia = _ia;
|
||||
} else
|
||||
KASSERT(_ia == ia);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* then, make the prefix on-link on the interface.
|
||||
|
@ -647,11 +691,12 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
* interface route.
|
||||
*/
|
||||
if ((error = nd6_prelist_add(&prc0, NULL, &pr)) != 0)
|
||||
return error;
|
||||
break;
|
||||
if (pr == NULL) {
|
||||
log(LOG_ERR, "nd6_prelist_add succeeded but "
|
||||
"no prefix\n");
|
||||
return EINVAL; /* XXX panic here? */
|
||||
error = EINVAL; /* XXX panic here? */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,8 +727,7 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
*/
|
||||
pfxlist_onlink_check();
|
||||
|
||||
(void)pfil_run_hooks(if_pfil, (struct mbuf **)SIOCAIFADDR_IN6,
|
||||
ifp, PFIL_IFADDR);
|
||||
run_hooks = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -702,19 +746,26 @@ in6_control1(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
|
|||
* Note that in6_purgeaddr() will decrement ndpr_refcnt.
|
||||
*/
|
||||
pr = ia->ia6_ndpr;
|
||||
ia6_release(ia, &psref);
|
||||
in6_purgeaddr(&ia->ia_ifa);
|
||||
ia = NULL;
|
||||
if (pr && pr->ndpr_refcnt == 0)
|
||||
prelist_remove(pr);
|
||||
(void)pfil_run_hooks(if_pfil, (struct mbuf **)SIOCDIFADDR_IN6,
|
||||
ifp, PFIL_IFADDR);
|
||||
run_hooks = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return ENOTTY;
|
||||
error = ENOTTY;
|
||||
}
|
||||
release:
|
||||
ia6_release(ia, &psref);
|
||||
|
||||
return 0;
|
||||
if (run_hooks)
|
||||
pfil_run_hooks(if_pfil, (struct mbuf **)cmd, ifp, PFIL_IFADDR);
|
||||
out:
|
||||
curlwp_bindx(bound);
|
||||
return error;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -930,6 +981,7 @@ in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra,
|
|||
|
||||
ia->ia_ifp = ifp;
|
||||
IN6_ADDRLIST_ENTRY_INIT(ia);
|
||||
ifa_psref_init(&ia->ia_ifa);
|
||||
}
|
||||
|
||||
/* update timestamp */
|
||||
|
@ -1036,7 +1088,9 @@ in6_update_ifa1(struct ifnet *ifp, struct in6_aliasreq *ifra,
|
|||
/*
|
||||
* Insert ia to the global list and ifa to the interface's list.
|
||||
*/
|
||||
mutex_enter(&in6_ifaddr_lock);
|
||||
IN6_ADDRLIST_WRITER_INSERT_TAIL(ia);
|
||||
mutex_exit(&in6_ifaddr_lock);
|
||||
|
||||
/* gain a refcnt for the link from in6_ifaddr */
|
||||
ifaref(&ia->ia_ifa);
|
||||
|
@ -1345,11 +1399,10 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
|
|||
{
|
||||
int s = splnet();
|
||||
|
||||
ifa_remove(ifp, &ia->ia_ifa);
|
||||
|
||||
mutex_enter(&in6_ifaddr_lock);
|
||||
IN6_ADDRLIST_WRITER_REMOVE(ia);
|
||||
/* TODO psref_target_destroy */
|
||||
IN6_ADDRLIST_ENTRY_DESTROY(ia);
|
||||
ifa_remove(ifp, &ia->ia_ifa);
|
||||
mutex_exit(&in6_ifaddr_lock);
|
||||
|
||||
/*
|
||||
* XXX thorpej@NetBSD.org -- if the interface is going
|
||||
|
@ -1388,6 +1441,8 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
|
|||
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0)
|
||||
pfxlist_onlink_check();
|
||||
|
||||
IN6_ADDRLIST_ENTRY_DESTROY(ia);
|
||||
|
||||
/*
|
||||
* release another refcnt for the link from in6_ifaddr.
|
||||
* Note that we should decrement the refcnt at least once for all *BSD.
|
||||
|
@ -1480,6 +1535,8 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
struct in6_aliasreq ifra;
|
||||
struct in6_addr *xhostid = NULL;
|
||||
int prefixlen;
|
||||
int bound = curlwp_bind();
|
||||
struct psref psref;
|
||||
|
||||
if ((iflr->flags & IFLR_PREFIX) != 0) {
|
||||
struct sockaddr_in6 *sin6;
|
||||
|
@ -1489,20 +1546,27 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
* address. xhostid points to the first link-local
|
||||
* address attached to the interface.
|
||||
*/
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0);
|
||||
if (ia == NULL)
|
||||
ia = in6ifa_ifpforlinklocal_psref(ifp, 0, &psref);
|
||||
if (ia == NULL) {
|
||||
curlwp_bindx(bound);
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
xhostid = IFA_IN6(&ia->ia_ifa);
|
||||
|
||||
/* prefixlen must be <= 64. */
|
||||
if (64 < iflr->prefixlen)
|
||||
if (64 < iflr->prefixlen) {
|
||||
ia6_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return EINVAL;
|
||||
}
|
||||
prefixlen = iflr->prefixlen;
|
||||
|
||||
/* hostid part must be zero. */
|
||||
sin6 = (struct sockaddr_in6 *)&iflr->addr;
|
||||
if (sin6->sin6_addr.s6_addr32[2] != 0
|
||||
|| sin6->sin6_addr.s6_addr32[3] != 0) {
|
||||
ia6_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return EINVAL;
|
||||
}
|
||||
} else
|
||||
|
@ -1532,6 +1596,11 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
xhostid->s6_addr32[3];
|
||||
}
|
||||
}
|
||||
if (xhostid) {
|
||||
ia6_release(ia, &psref);
|
||||
ia = NULL;
|
||||
}
|
||||
curlwp_bindx(bound);
|
||||
|
||||
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
|
||||
in6_prefixlen2mask(&ifra.ifra_prefixmask.sin6_addr, prefixlen);
|
||||
|
@ -1547,6 +1616,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
struct in6_addr mask, candidate, match;
|
||||
struct sockaddr_in6 *sin6;
|
||||
int cmp;
|
||||
int error, s;
|
||||
|
||||
memset(&mask, 0, sizeof(mask));
|
||||
if (iflr->flags & IFLR_PREFIX) {
|
||||
|
@ -1579,6 +1649,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
}
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
@ -1599,19 +1670,19 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
if (IN6_ARE_ADDR_EQUAL(&candidate, &match))
|
||||
break;
|
||||
}
|
||||
if (!ifa)
|
||||
return EADDRNOTAVAIL;
|
||||
if (!ifa) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto error;
|
||||
}
|
||||
ia = ifa2ia6(ifa);
|
||||
|
||||
if (cmd == SIOCGLIFADDR) {
|
||||
int error;
|
||||
|
||||
/* fill in the if_laddrreq structure */
|
||||
memcpy(&iflr->addr, &ia->ia_addr, ia->ia_addr.sin6_len);
|
||||
error = sa6_recoverscope(
|
||||
(struct sockaddr_in6 *)&iflr->addr);
|
||||
if (error != 0)
|
||||
return error;
|
||||
goto error;
|
||||
|
||||
if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
|
||||
memcpy(&iflr->dstaddr, &ia->ia_dstaddr,
|
||||
|
@ -1619,7 +1690,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
error = sa6_recoverscope(
|
||||
(struct sockaddr_in6 *)&iflr->dstaddr);
|
||||
if (error != 0)
|
||||
return error;
|
||||
goto error;
|
||||
} else
|
||||
memset(&iflr->dstaddr, 0, sizeof(iflr->dstaddr));
|
||||
|
||||
|
@ -1628,7 +1699,7 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
|
||||
iflr->flags = ia->ia6_flags; /* XXX */
|
||||
|
||||
return 0;
|
||||
error = 0;
|
||||
} else {
|
||||
struct in6_aliasreq ifra;
|
||||
|
||||
|
@ -1650,8 +1721,13 @@ in6_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
|
|||
ia->ia_prefixmask.sin6_len);
|
||||
|
||||
ifra.ifra_flags = ia->ia6_flags;
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return in6_control(so, SIOCDIFADDR_IN6, &ifra, ifp);
|
||||
}
|
||||
error:
|
||||
pserialize_read_exit(s);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1756,6 +1832,21 @@ in6ifa_ifpforlinklocal(const struct ifnet *ifp, const int ignoreflags)
|
|||
return (struct in6_ifaddr *)best_ifa;
|
||||
}
|
||||
|
||||
struct in6_ifaddr *
|
||||
in6ifa_ifpforlinklocal_psref(const struct ifnet *ifp, const int ignoreflags,
|
||||
struct psref *psref)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
ia = in6ifa_ifpforlinklocal(ifp, ignoreflags);
|
||||
if (ia != NULL)
|
||||
ia6_acquire(ia, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ia;
|
||||
}
|
||||
|
||||
/*
|
||||
* find the internet address corresponding to a given address.
|
||||
* ifaddr is returned referenced.
|
||||
|
@ -1764,13 +1855,10 @@ struct in6_ifaddr *
|
|||
in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
int s;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
IN6_IFADDR_RLOCK();
|
||||
LIST_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) {
|
||||
#else
|
||||
s = pserialize_read_enter();
|
||||
IN6_ADDRLIST_READER_FOREACH(ia) {
|
||||
#endif
|
||||
if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), addr)) {
|
||||
if (zoneid != 0 &&
|
||||
zoneid != ia->ia_addr.sin6_scope_id)
|
||||
|
@ -1779,9 +1867,8 @@ in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid)
|
|||
break;
|
||||
}
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
IN6_IFADDR_RUNLOCK();
|
||||
#endif
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ia;
|
||||
}
|
||||
|
||||
|
@ -1804,6 +1891,21 @@ in6ifa_ifpwithaddr(const struct ifnet *ifp, const struct in6_addr *addr)
|
|||
return (struct in6_ifaddr *)best_ifa;
|
||||
}
|
||||
|
||||
struct in6_ifaddr *
|
||||
in6ifa_ifpwithaddr_psref(const struct ifnet *ifp, const struct in6_addr *addr,
|
||||
struct psref *psref)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
ia = in6ifa_ifpwithaddr(ifp, addr);
|
||||
if (ia != NULL)
|
||||
ia6_acquire(ia, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ia;
|
||||
}
|
||||
|
||||
static struct in6_ifaddr *
|
||||
bestia(struct in6_ifaddr *best_ia, struct in6_ifaddr *ia)
|
||||
{
|
||||
|
@ -2043,6 +2145,7 @@ in6_if_link_up(struct ifnet *ifp)
|
|||
{
|
||||
struct ifaddr *ifa;
|
||||
struct in6_ifaddr *ia;
|
||||
int s, bound;
|
||||
|
||||
/* Ensure it's sane to run DAD */
|
||||
if (ifp->if_link_state == LINK_STATE_DOWN)
|
||||
|
@ -2050,9 +2153,16 @@ in6_if_link_up(struct ifnet *ifp)
|
|||
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
|
||||
return;
|
||||
|
||||
bound = curlwp_bind();
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct psref psref;
|
||||
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
ifa_acquire(ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
|
||||
/* If detached then mark as tentative */
|
||||
|
@ -2083,7 +2193,12 @@ in6_if_link_up(struct ifnet *ifp)
|
|||
/* +1 ensures callout is always used */
|
||||
nd6_dad_start(ifa, rand_delay + 1);
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
/* Restore any detached prefixes */
|
||||
pfxlist_onlink_check();
|
||||
|
@ -2110,13 +2225,21 @@ in6_if_link_down(struct ifnet *ifp)
|
|||
{
|
||||
struct ifaddr *ifa;
|
||||
struct in6_ifaddr *ia;
|
||||
int s, bound;
|
||||
|
||||
/* Any prefixes on this interface should be detached as well */
|
||||
pfxlist_onlink_check();
|
||||
|
||||
bound = curlwp_bind();
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct psref psref;
|
||||
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
ifa_acquire(ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
|
||||
/* Stop DAD processing */
|
||||
|
@ -2138,7 +2261,12 @@ in6_if_link_down(struct ifnet *ifp)
|
|||
~(IN6_IFF_TENTATIVE | IN6_IFF_DUPLICATED);
|
||||
rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL);
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
curlwp_bindx(bound);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2319,18 +2447,22 @@ in6_lltable_rtcheck(struct ifnet *ifp,
|
|||
|
||||
rt = rtalloc1(l3addr, 0);
|
||||
if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
|
||||
int s;
|
||||
struct ifaddr *ifa;
|
||||
/*
|
||||
* Create an ND6 cache for an IPv6 neighbor
|
||||
* that is not covered by our own prefix.
|
||||
*/
|
||||
/* XXX ifaof_ifpforaddr should take a const param */
|
||||
s = pserialize_read_enter();
|
||||
ifa = ifaof_ifpforaddr(l3addr, ifp);
|
||||
if (ifa != NULL) {
|
||||
pserialize_read_exit(s);
|
||||
if (rt != NULL)
|
||||
rtfree(rt);
|
||||
return 0;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
|
||||
ip6_sprintf(&((const struct sockaddr_in6 *)l3addr)->sin6_addr));
|
||||
if (rt != NULL)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_ifattach.c,v 1.102 2016/07/20 07:37:51 ozaki-r Exp $ */
|
||||
/* $NetBSD: in6_ifattach.c,v 1.103 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: in6_ifattach.c,v 1.124 2001/07/18 08:32:51 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.102 2016/07/20 07:37:51 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.103 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -320,31 +320,35 @@ int
|
|||
in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
const struct sockaddr_dl *sdl = NULL, *tsdl;
|
||||
const struct sockaddr_dl *sdl = NULL;
|
||||
const char *addr;
|
||||
size_t addrlen;
|
||||
static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
static u_int8_t allone[8] =
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
const struct sockaddr_dl *tsdl;
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
tsdl = satocsdl(ifa->ifa_addr);
|
||||
if (tsdl == NULL || tsdl->sdl_alen == 0)
|
||||
continue;
|
||||
if (sdl == NULL || ifa == ifp->if_dl || ifa == ifp->if_hwdl)
|
||||
if (sdl == NULL || ifa == ifp->if_dl || ifa == ifp->if_hwdl) {
|
||||
sdl = tsdl;
|
||||
addr = CLLADDR(sdl);
|
||||
addrlen = sdl->sdl_alen;
|
||||
}
|
||||
if (ifa == ifp->if_hwdl)
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (sdl == NULL)
|
||||
return -1;
|
||||
|
||||
addr = CLLADDR(sdl);
|
||||
addrlen = sdl->sdl_alen;
|
||||
|
||||
switch (ifp->if_type) {
|
||||
case IFT_IEEE1394:
|
||||
case IFT_IEEE80211:
|
||||
|
@ -532,7 +536,7 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
|
|||
struct in6_ifaddr *ia __diagused;
|
||||
struct in6_aliasreq ifra;
|
||||
struct nd_prefixctl prc0;
|
||||
int i, error;
|
||||
int i, error, s;
|
||||
|
||||
/*
|
||||
* configure link-local address.
|
||||
|
@ -589,8 +593,10 @@ in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
|
|||
return -1;
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
|
||||
KASSERTMSG(ia, "ia == NULL in in6_ifattach_linklocal");
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* Make the link-local prefix (fe80::/64%link) as on-link.
|
||||
|
@ -811,24 +817,29 @@ in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
|
|||
* XXX multiple loopback interface case.
|
||||
*/
|
||||
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
|
||||
int s = pserialize_read_enter();
|
||||
in6 = in6addr_loopback;
|
||||
if (in6ifa_ifpwithaddr(ifp, &in6) == NULL) {
|
||||
if (in6_ifattach_loopback(ifp) != 0)
|
||||
if (in6_ifattach_loopback(ifp) != 0) {
|
||||
pserialize_read_exit(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* assign a link-local address, if there's none.
|
||||
*/
|
||||
if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
|
||||
ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL)
|
||||
{
|
||||
ND_IFINFO(ifp)->flags & ND6_IFF_AUTO_LINKLOCAL) {
|
||||
int s = pserialize_read_enter();
|
||||
ia = in6ifa_ifpforlinklocal(ifp, 0);
|
||||
if (ia == NULL && in6_ifattach_linklocal(ifp, altifp) != 0) {
|
||||
printf("%s: cannot assign link-local address\n",
|
||||
ifp->if_xname);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_pcb.c,v 1.147 2016/07/15 07:40:09 ozaki-r Exp $ */
|
||||
/* $NetBSD: in6_pcb.c,v 1.148 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: in6_pcb.c,v 1.84 2001/02/08 18:02:08 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.147 2016/07/15 07:40:09 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_pcb.c,v 1.148 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -203,6 +203,7 @@ static int
|
|||
in6_pcbbind_addr(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
||||
{
|
||||
int error;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* We should check the family, but old programs
|
||||
|
@ -219,9 +220,12 @@ in6_pcbbind_addr(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
|||
if ((error = sa6_embedscope(sin6, ip6_use_defzone)) != 0)
|
||||
return (error);
|
||||
|
||||
s = pserialize_read_enter();
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
|
||||
if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0)
|
||||
return (EINVAL);
|
||||
if ((in6p->in6p_flags & IN6P_IPV6_V6ONLY) != 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (sin6->sin6_addr.s6_addr32[3]) {
|
||||
struct sockaddr_in sin;
|
||||
|
||||
|
@ -230,18 +234,27 @@ in6_pcbbind_addr(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
|||
sin.sin_family = AF_INET;
|
||||
bcopy(&sin6->sin6_addr.s6_addr32[3],
|
||||
&sin.sin_addr, sizeof(sin.sin_addr));
|
||||
if (!IN_MULTICAST(sin.sin_addr.s_addr) &&
|
||||
ifa_ifwithaddr((struct sockaddr *)&sin) == NULL)
|
||||
return EADDRNOTAVAIL;
|
||||
if (!IN_MULTICAST(sin.sin_addr.s_addr)) {
|
||||
struct ifaddr *ifa;
|
||||
ifa = ifa_ifwithaddr((struct sockaddr *)&sin);
|
||||
if (ifa == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
|
||||
// succeed
|
||||
} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
|
||||
struct ifaddr *ia = NULL;
|
||||
struct ifaddr *ifa = NULL;
|
||||
|
||||
if ((in6p->in6p_flags & IN6P_FAITH) == 0 &&
|
||||
(ia = ifa_ifwithaddr(sin6tosa(sin6))) == NULL)
|
||||
return (EADDRNOTAVAIL);
|
||||
if ((in6p->in6p_flags & IN6P_FAITH) == 0) {
|
||||
ifa = ifa_ifwithaddr(sin6tosa(sin6));
|
||||
if (ifa == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* bind to an anycast address might accidentally
|
||||
|
@ -256,17 +269,18 @@ in6_pcbbind_addr(struct in6pcb *in6p, struct sockaddr_in6 *sin6, struct lwp *l)
|
|||
* flag to control the bind(2) behavior against
|
||||
* deprecated addresses (default: forbid bind(2)).
|
||||
*/
|
||||
if (ia &&
|
||||
ifatoia6(ia)->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED))
|
||||
return (EADDRNOTAVAIL);
|
||||
if (ifa &&
|
||||
ifatoia6(ifa)->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
in6p->in6p_laddr = sin6->sin6_addr;
|
||||
|
||||
|
||||
return (0);
|
||||
error = 0;
|
||||
out:
|
||||
pserialize_read_exit(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -485,23 +499,27 @@ in6_pcbconnect(void *v, struct sockaddr_in6 *sin6, struct lwp *l)
|
|||
if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr) &&
|
||||
in6p->in6p_laddr.s6_addr32[3] == 0) {
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin, *sinp;
|
||||
struct sockaddr_in sin;
|
||||
struct in_ifaddr *ia4;
|
||||
struct psref _psref;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_len = sizeof(sin);
|
||||
sin.sin_family = AF_INET;
|
||||
memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr32[3],
|
||||
sizeof(sin.sin_addr));
|
||||
sinp = in_selectsrc(&sin, &in6p->in6p_route,
|
||||
in6p->in6p_socket->so_options, NULL, &error);
|
||||
if (sinp == NULL) {
|
||||
ia4 = in_selectsrc(&sin, &in6p->in6p_route,
|
||||
in6p->in6p_socket->so_options, NULL, &error, &_psref);
|
||||
if (ia4 == NULL) {
|
||||
if (error == 0)
|
||||
error = EADDRNOTAVAIL;
|
||||
return (error);
|
||||
}
|
||||
memset(&mapped, 0, sizeof(mapped));
|
||||
mapped.s6_addr16[5] = htons(0xffff);
|
||||
memcpy(&mapped.s6_addr32[3], &sinp->sin_addr, sizeof(sinp->sin_addr));
|
||||
memcpy(&mapped.s6_addr32[3], &IA_SIN(ia4)->sin_addr,
|
||||
sizeof(IA_SIN(ia4)->sin_addr));
|
||||
ia4_release(ia4, &_psref);
|
||||
in6a = &mapped;
|
||||
#else
|
||||
return EADDRNOTAVAIL;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_src.c,v 1.65 2016/07/15 07:40:09 ozaki-r Exp $ */
|
||||
/* $NetBSD: in6_src.c,v 1.66 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: in6_src.c,v 1.159 2005/10/19 01:40:32 t-momose Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -66,7 +66,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.65 2016/07/15 07:40:09 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.66 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -192,6 +192,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
struct in6_addr *ret_ia = NULL;
|
||||
int bound = curlwp_bind();
|
||||
#define PSREF (psref == NULL) ? &local_psref : psref
|
||||
int s;
|
||||
|
||||
KASSERT((ifpp != NULL && psref != NULL) ||
|
||||
(ifpp == NULL && psref == NULL));
|
||||
|
@ -222,6 +223,8 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
!IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
|
||||
struct sockaddr_in6 srcsock;
|
||||
struct in6_ifaddr *ia6;
|
||||
int _s;
|
||||
struct ifaddr *ifa;
|
||||
|
||||
/*
|
||||
* Determine the appropriate zone id of the source based on
|
||||
|
@ -240,9 +243,16 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
ia6 = ifatoia6(ifa_ifwithaddr(sin6tosa(&srcsock)));
|
||||
if (ia6 == NULL ||
|
||||
(ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
|
||||
_s = pserialize_read_enter();
|
||||
ifa = ifa_ifwithaddr(sin6tosa(&srcsock));
|
||||
if (ifa == NULL) {
|
||||
pserialize_read_exit(_s);
|
||||
*errorp = EADDRNOTAVAIL;
|
||||
goto exit;
|
||||
}
|
||||
ia6 = ifatoia6(ifa);
|
||||
if (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY)) {
|
||||
pserialize_read_exit(_s);
|
||||
*errorp = EADDRNOTAVAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -250,6 +260,8 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
if (ifpp)
|
||||
*ifpp = ifp;
|
||||
ret_ia = &ia6->ia_addr.sin6_addr;
|
||||
pserialize_read_exit(_s);
|
||||
/* XXX don't return pointer */
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -293,6 +305,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
if (*errorp != 0)
|
||||
goto exit;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IN6_ADDRLIST_READER_FOREACH(ia) {
|
||||
int new_scope = -1, new_matchlen = -1;
|
||||
struct in6_addrpolicy *new_policy = NULL;
|
||||
|
@ -551,6 +564,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
out:
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if ((ia = ia_best) == NULL) {
|
||||
*errorp = EADDRNOTAVAIL;
|
||||
|
@ -659,8 +673,12 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
goto done;
|
||||
}
|
||||
ifp = rt->rt_ifp;
|
||||
if (ifp != NULL)
|
||||
if_acquire_NOMPSAFE(ifp, PSREF);
|
||||
if (ifp != NULL) {
|
||||
if (!if_is_deactivated(ifp))
|
||||
if_acquire_NOMPSAFE(ifp, PSREF);
|
||||
else
|
||||
ifp = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* When cloning is required, try to allocate a route to the
|
||||
|
@ -699,8 +717,12 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
else {
|
||||
if_put(ifp, PSREF);
|
||||
ifp = rt->rt_ifp;
|
||||
if (ifp != NULL)
|
||||
if_acquire_NOMPSAFE(ifp, PSREF);
|
||||
if (ifp != NULL) {
|
||||
if (!if_is_deactivated(ifp))
|
||||
if_acquire_NOMPSAFE(ifp, PSREF);
|
||||
else
|
||||
ifp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -788,7 +810,8 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
|
|||
* addresses.)
|
||||
*/
|
||||
if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp &&
|
||||
rt->rt_ifa->ifa_ifp != *retifp) {
|
||||
rt->rt_ifa->ifa_ifp != *retifp &&
|
||||
!if_is_deactivated(rt->rt_ifa->ifa_ifp)) {
|
||||
if_put(*retifp, psref);
|
||||
*retifp = rt->rt_ifa->ifa_ifp;
|
||||
if_acquire_NOMPSAFE(*retifp, psref);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6_var.h,v 1.83 2016/07/08 04:33:30 ozaki-r Exp $ */
|
||||
/* $NetBSD: in6_var.h,v 1.84 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: in6_var.h,v 1.81 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -134,6 +134,25 @@ struct in6_ifaddr {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
static inline void
|
||||
ia6_acquire(struct in6_ifaddr *ia, struct psref *psref)
|
||||
{
|
||||
|
||||
KASSERT(ia != NULL);
|
||||
ifa_acquire(&ia->ia_ifa, psref);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ia6_release(struct in6_ifaddr *ia, struct psref *psref)
|
||||
{
|
||||
|
||||
if (ia == NULL)
|
||||
return;
|
||||
ifa_release(&ia->ia_ifa, psref);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* control structure to manage address selection policy */
|
||||
struct in6_addrpolicy {
|
||||
struct sockaddr_in6 addr; /* prefix address */
|
||||
|
@ -489,13 +508,17 @@ struct in6_rrenumreq {
|
|||
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/pserialize.h>
|
||||
|
||||
#include <net/pktqueue.h>
|
||||
|
||||
extern pktqueue_t *ip6_pktq;
|
||||
|
||||
MALLOC_DECLARE(M_IP6OPT);
|
||||
|
||||
extern struct pslist_head in6_ifaddr_list;
|
||||
extern struct pslist_head in6_ifaddr_list;
|
||||
extern kmutex_t in6_ifaddr_lock;
|
||||
|
||||
#define IN6_ADDRLIST_ENTRY_INIT(__ia) \
|
||||
PSLIST_ENTRY_INIT((__ia), ia6_pslist_entry)
|
||||
|
@ -573,6 +596,20 @@ in6_get_ia_from_ifp(struct ifnet *ifp)
|
|||
return (struct in6_ifaddr *)ifa;
|
||||
}
|
||||
|
||||
static inline struct in6_ifaddr *
|
||||
in6_get_ia_from_ifp_psref(struct ifnet *ifp, struct psref *psref)
|
||||
{
|
||||
struct in6_ifaddr *ia;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia = in6_get_ia_from_ifp(ifp);
|
||||
if (ia != NULL)
|
||||
ia6_acquire(ia, psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return ia;
|
||||
}
|
||||
#endif /* _KERNEL */
|
||||
|
||||
/*
|
||||
|
@ -623,13 +660,18 @@ in6_lookup_multi(struct in6_addr *addr, struct ifnet *ifp)
|
|||
{
|
||||
struct in6_multi *in6m;
|
||||
struct in6_ifaddr *ia;
|
||||
int s;
|
||||
|
||||
if ((ia = in6_get_ia_from_ifp(ifp)) == NULL)
|
||||
s = pserialize_read_enter();
|
||||
if ((ia = in6_get_ia_from_ifp(ifp)) == NULL) {
|
||||
pserialize_read_exit(s);
|
||||
return NULL;
|
||||
}
|
||||
LIST_FOREACH(in6m, &ia->ia6_multiaddrs, in6m_entry) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, addr))
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
return in6m;
|
||||
}
|
||||
|
||||
|
@ -659,6 +701,7 @@ in6_next_multi(struct in6_multistep *step)
|
|||
}
|
||||
while (step->i_ia != NULL) {
|
||||
in6m = LIST_FIRST(&step->i_ia->ia6_multiaddrs);
|
||||
/* FIXME NOMPSAFE */
|
||||
step->i_ia = IN6_ADDRLIST_READER_NEXT(step->i_ia);
|
||||
if (in6m != NULL) {
|
||||
step->i_in6m = LIST_NEXT(in6m, in6m_entry);
|
||||
|
@ -672,6 +715,7 @@ static inline struct in6_multi *
|
|||
in6_first_multi(struct in6_multistep *step)
|
||||
{
|
||||
|
||||
/* FIXME NOMPSAFE */
|
||||
step->i_ia = IN6_ADDRLIST_READER_FIRST();
|
||||
step->i_in6m = NULL;
|
||||
return in6_next_multi(step);
|
||||
|
@ -748,9 +792,15 @@ void in6_ifremlocal(struct ifaddr *);
|
|||
void in6_ifaddlocal(struct ifaddr *);
|
||||
void in6_createmkludge(struct ifnet *);
|
||||
void in6_purgemkludge(struct ifnet *);
|
||||
struct in6_ifaddr *in6ifa_ifpforlinklocal(const struct ifnet *, int);
|
||||
struct in6_ifaddr *in6ifa_ifpwithaddr(const struct ifnet *,
|
||||
const struct in6_addr *);
|
||||
struct in6_ifaddr *
|
||||
in6ifa_ifpforlinklocal(const struct ifnet *, int);
|
||||
struct in6_ifaddr *
|
||||
in6ifa_ifpforlinklocal_psref(const struct ifnet *, int, struct psref *);
|
||||
struct in6_ifaddr *
|
||||
in6ifa_ifpwithaddr(const struct ifnet *, const struct in6_addr *);
|
||||
struct in6_ifaddr *
|
||||
in6ifa_ifpwithaddr_psref(const struct ifnet *, const struct in6_addr *,
|
||||
struct psref *);
|
||||
struct in6_ifaddr *in6ifa_ifwithaddr(const struct in6_addr *, uint32_t);
|
||||
char *ip6_sprintf(const struct in6_addr *);
|
||||
int in6_matchlen(struct in6_addr *, struct in6_addr *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_input.c,v 1.164 2016/07/07 09:32:03 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip6_input.c,v 1.165 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.164 2016/07/07 09:32:03 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.165 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_gateway.h"
|
||||
|
@ -565,8 +565,10 @@ ip6_input(struct mbuf *m, struct ifnet *rcvif)
|
|||
*/
|
||||
if (deliverifp && ip6_getdstifaddr(m) == NULL) {
|
||||
struct in6_ifaddr *ia6;
|
||||
int s = pserialize_read_enter();
|
||||
|
||||
ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
|
||||
/* Depends on ip6_setdstifaddr never sleep */
|
||||
if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) {
|
||||
/*
|
||||
* XXX maybe we should drop the packet here,
|
||||
|
@ -574,6 +576,7 @@ ip6_input(struct mbuf *m, struct ifnet *rcvif)
|
|||
* to the upper layers.
|
||||
*/
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -701,9 +704,11 @@ ip6_input(struct mbuf *m, struct ifnet *rcvif)
|
|||
#ifdef IFA_STATS
|
||||
if (deliverifp != NULL) {
|
||||
struct in6_ifaddr *ia6;
|
||||
int s = pserialize_read_enter();
|
||||
ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
|
||||
if (ia6)
|
||||
ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
#endif
|
||||
IP6_STATINC(IP6_STAT_DELIVERED);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_output.c,v 1.172 2016/07/29 06:02:03 ozaki-r Exp $ */
|
||||
/* $NetBSD: ip6_output.c,v 1.173 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.172 2016/07/29 06:02:03 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.173 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -526,6 +526,8 @@ ip6_output(
|
|||
*/
|
||||
if (ia != NULL && ia->ia_ifp) {
|
||||
origifp = ia->ia_ifp;
|
||||
if (if_is_deactivated(origifp))
|
||||
goto bad;
|
||||
if_acquire_NOMPSAFE(origifp, &psref_ia);
|
||||
release_psref_ia = true;
|
||||
} else
|
||||
|
@ -761,13 +763,16 @@ ip6_output(
|
|||
/* case 1-a and 2-a */
|
||||
struct in6_ifaddr *ia6;
|
||||
int sw_csum;
|
||||
int s;
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
s = pserialize_read_enter();
|
||||
ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
|
||||
if (ia6) {
|
||||
/* Record statistics for this interface address. */
|
||||
ia6->ia_ifa.ifa_data.ifad_outbytes += m->m_pkthdr.len;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
|
||||
if ((sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
|
||||
|
@ -953,7 +958,9 @@ sendorfree:
|
|||
m->m_nextpkt = 0;
|
||||
if (error == 0) {
|
||||
struct in6_ifaddr *ia6;
|
||||
int s;
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
s = pserialize_read_enter();
|
||||
ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
|
||||
if (ia6) {
|
||||
/*
|
||||
|
@ -963,6 +970,7 @@ sendorfree:
|
|||
ia6->ia_ifa.ifa_data.ifad_outbytes +=
|
||||
m->m_pkthdr.len;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
KASSERT(dst != NULL);
|
||||
error = nd6_output(ifp, origifp, m, dst, rt);
|
||||
} else
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mld6.c,v 1.73 2016/07/20 07:37:51 ozaki-r Exp $ */
|
||||
/* $NetBSD: mld6.c,v 1.74 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -102,7 +102,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.73 2016/07/20 07:37:51 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.74 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -402,7 +402,9 @@ mld_input(struct mbuf *m, int off)
|
|||
* if we sent the last report.
|
||||
*/
|
||||
switch (mldh->mld_type) {
|
||||
case MLD_LISTENER_QUERY:
|
||||
case MLD_LISTENER_QUERY: {
|
||||
struct psref psref;
|
||||
|
||||
if (ifp->if_flags & IFF_LOOPBACK)
|
||||
break;
|
||||
|
||||
|
@ -428,10 +430,14 @@ mld_input(struct mbuf *m, int off)
|
|||
*/
|
||||
timer = ntohs(mldh->mld_maxdelay);
|
||||
|
||||
ia = in6_get_ia_from_ifp(ifp);
|
||||
ia = in6_get_ia_from_ifp_psref(ifp, &psref);
|
||||
if (ia == NULL)
|
||||
break;
|
||||
|
||||
/* The following operations may sleep */
|
||||
m_put_rcvif(ifp, &s);
|
||||
ifp = NULL;
|
||||
|
||||
LIST_FOREACH(in6m, &ia->ia6_multiaddrs, in6m_entry) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_in6) ||
|
||||
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) <
|
||||
|
@ -457,7 +463,9 @@ mld_input(struct mbuf *m, int off)
|
|||
mld_starttimer(in6m);
|
||||
}
|
||||
}
|
||||
ia6_release(ia, &psref);
|
||||
break;
|
||||
}
|
||||
|
||||
case MLD_LISTENER_REPORT:
|
||||
/*
|
||||
|
@ -514,6 +522,8 @@ mld_sendpkt(struct in6_multi *in6m, int type,
|
|||
struct in6_ifaddr *ia = NULL;
|
||||
struct ifnet *ifp = in6m->in6m_ifp;
|
||||
int ignflags;
|
||||
struct psref psref;
|
||||
int bound;
|
||||
|
||||
/*
|
||||
* At first, find a link local address on the outgoing interface
|
||||
|
@ -522,20 +532,31 @@ mld_sendpkt(struct in6_multi *in6m, int type,
|
|||
* the case where we first join a link-local address.
|
||||
*/
|
||||
ignflags = (IN6_IFF_NOTREADY|IN6_IFF_ANYCAST) & ~IN6_IFF_TENTATIVE;
|
||||
if ((ia = in6ifa_ifpforlinklocal(ifp, ignflags)) == NULL)
|
||||
bound = curlwp_bind();
|
||||
ia = in6ifa_ifpforlinklocal_psref(ifp, ignflags, &psref);
|
||||
if (ia == NULL) {
|
||||
curlwp_bindx(bound);
|
||||
return;
|
||||
if ((ia->ia6_flags & IN6_IFF_TENTATIVE))
|
||||
}
|
||||
if ((ia->ia6_flags & IN6_IFF_TENTATIVE)) {
|
||||
ia6_release(ia, &psref);
|
||||
ia = NULL;
|
||||
}
|
||||
|
||||
/* Allocate two mbufs to store IPv6 header and MLD header */
|
||||
mldh = mld_allocbuf(&mh, sizeof(struct mld_hdr), in6m, type);
|
||||
if (mldh == NULL)
|
||||
if (mldh == NULL) {
|
||||
ia6_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fill src/dst here */
|
||||
ip6 = mtod(mh, struct ip6_hdr *);
|
||||
ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any;
|
||||
ip6->ip6_dst = dst ? *dst : in6m->in6m_addr;
|
||||
ia6_release(ia, &psref);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
mldh->mld_addr = in6m->in6m_addr;
|
||||
in6_clearscope(&mldh->mld_addr); /* XXX */
|
||||
|
@ -645,6 +666,7 @@ in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp,
|
|||
*/
|
||||
in6m->in6m_refcount++;
|
||||
} else {
|
||||
int _s;
|
||||
/*
|
||||
* New address; allocate a new multicast record
|
||||
* and link it into the interface's multicast list.
|
||||
|
@ -664,8 +686,10 @@ in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp,
|
|||
callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE);
|
||||
callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m);
|
||||
|
||||
_s = pserialize_read_enter();
|
||||
ia = in6_get_ia_from_ifp(ifp);
|
||||
if (ia == NULL) {
|
||||
pserialize_read_exit(_s);
|
||||
callout_destroy(&in6m->in6m_timer_ch);
|
||||
free(in6m, M_IPMADDR);
|
||||
splx(s);
|
||||
|
@ -674,7 +698,9 @@ in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp,
|
|||
}
|
||||
in6m->in6m_ia = ia;
|
||||
ifaref(&ia->ia_ifa); /* gain a reference */
|
||||
/* FIXME NOMPSAFE: need to lock */
|
||||
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
|
||||
pserialize_read_exit(_s);
|
||||
|
||||
/*
|
||||
* Ask the network driver to update its multicast reception
|
||||
|
@ -816,7 +842,9 @@ in6_savemkludge(struct in6_ifaddr *oia)
|
|||
{
|
||||
struct in6_ifaddr *ia;
|
||||
struct in6_multi *in6m;
|
||||
int s;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia = in6_get_ia_from_ifp(oia->ia_ifp);
|
||||
if (ia) { /* there is another address */
|
||||
KASSERT(ia != oia);
|
||||
|
@ -825,6 +853,7 @@ in6_savemkludge(struct in6_ifaddr *oia)
|
|||
ifaref(&ia->ia_ifa);
|
||||
ifafree(&in6m->in6m_ia->ia_ifa);
|
||||
in6m->in6m_ia = ia;
|
||||
/* FIXME NOMPSAFE: need to lock */
|
||||
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
|
||||
}
|
||||
} else { /* last address on this if deleted, save */
|
||||
|
@ -844,6 +873,7 @@ in6_savemkludge(struct in6_ifaddr *oia)
|
|||
LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry);
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -986,8 +1016,8 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
|
|||
uint32_t tmp;
|
||||
int error;
|
||||
size_t written;
|
||||
struct psref psref;
|
||||
int bound;
|
||||
struct psref psref, psref_ia;
|
||||
int bound, s;
|
||||
|
||||
if (namelen != 1)
|
||||
return EINVAL;
|
||||
|
@ -1001,6 +1031,7 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
|
|||
|
||||
if (oldp == NULL) {
|
||||
*oldlenp = 0;
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
@ -1010,6 +1041,7 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
|
|||
sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
if_put(ifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
return 0;
|
||||
|
@ -1017,9 +1049,14 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
|
|||
|
||||
error = 0;
|
||||
written = 0;
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
||||
ifa_acquire(ifa, &psref_ia);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
ifa6 = (struct in6_ifaddr *)ifa;
|
||||
LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) {
|
||||
if (written + 2 * sizeof(struct in6_addr) +
|
||||
|
@ -1044,8 +1081,13 @@ in6_multicast_sysctl(SYSCTLFN_ARGS)
|
|||
oldp = (char *)oldp + sizeof(tmp);
|
||||
written += sizeof(tmp);
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref_ia);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
done:
|
||||
ifa_release(ifa, &psref_ia);
|
||||
if_put(ifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
*oldlenp = written;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nd6.c,v 1.204 2016/07/15 07:40:09 ozaki-r Exp $ */
|
||||
/* $NetBSD: nd6.c,v 1.205 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: nd6.c,v 1.279 2002/06/08 11:16:51 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.204 2016/07/15 07:40:09 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.205 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_net_mpsafe.h"
|
||||
|
@ -571,6 +571,8 @@ nd6_timer_work(struct work *wk, void *arg)
|
|||
struct nd_defrouter *next_dr, *dr;
|
||||
struct nd_prefix *next_pr, *pr;
|
||||
struct in6_ifaddr *ia6, *nia6;
|
||||
int s, bound;
|
||||
struct psref psref;
|
||||
|
||||
callout_reset(&nd6_timer_ch, nd6_prune * hz,
|
||||
nd6_timer, NULL);
|
||||
|
@ -592,9 +594,15 @@ nd6_timer_work(struct work *wk, void *arg)
|
|||
* However, from a stricter speci-confrmance standpoint, we should
|
||||
* rather separate address lifetimes and prefix lifetimes.
|
||||
*/
|
||||
bound = curlwp_bind();
|
||||
addrloop:
|
||||
for (ia6 = IN6_ADDRLIST_WRITER_FIRST(); ia6; ia6 = nia6) {
|
||||
nia6 = IN6_ADDRLIST_WRITER_NEXT(ia6);
|
||||
s = pserialize_read_enter();
|
||||
for (ia6 = IN6_ADDRLIST_READER_FIRST(); ia6; ia6 = nia6) {
|
||||
nia6 = IN6_ADDRLIST_READER_NEXT(ia6);
|
||||
|
||||
ia6_acquire(ia6, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/* check address lifetime */
|
||||
if (IFA6_IS_INVALID(ia6)) {
|
||||
int regen = 0;
|
||||
|
@ -615,7 +623,9 @@ nd6_timer_work(struct work *wk, void *arg)
|
|||
regen = 1;
|
||||
}
|
||||
|
||||
ia6_release(ia6, &psref);
|
||||
in6_purgeaddr(&ia6->ia_ifa);
|
||||
ia6 = NULL;
|
||||
|
||||
if (regen)
|
||||
goto addrloop; /* XXX: see below */
|
||||
|
@ -649,6 +659,7 @@ nd6_timer_work(struct work *wk, void *arg)
|
|||
* loop just for safety. Or does this
|
||||
* significantly reduce performance??
|
||||
*/
|
||||
ia6_release(ia6, &psref);
|
||||
goto addrloop;
|
||||
}
|
||||
}
|
||||
|
@ -663,7 +674,11 @@ nd6_timer_work(struct work *wk, void *arg)
|
|||
(struct ifaddr *)ia6, 0, NULL);
|
||||
}
|
||||
}
|
||||
s = pserialize_read_enter();
|
||||
ia6_release(ia6, &psref);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
/* expire prefix list */
|
||||
LIST_FOREACH_SAFE(pr, &nd_prefix, ndpr_entry, next_pr) {
|
||||
|
@ -702,8 +717,10 @@ regen_tmpaddr(const struct in6_ifaddr *ia6)
|
|||
struct ifaddr *ifa;
|
||||
struct ifnet *ifp;
|
||||
struct in6_ifaddr *public_ifa6 = NULL;
|
||||
int s;
|
||||
|
||||
ifp = ia6->ia_ifa.ifa_ifp;
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct in6_ifaddr *it6;
|
||||
|
||||
|
@ -745,18 +762,24 @@ regen_tmpaddr(const struct in6_ifaddr *ia6)
|
|||
|
||||
if (public_ifa6 != NULL) {
|
||||
int e;
|
||||
struct psref psref;
|
||||
|
||||
ia6_acquire(public_ifa6, &psref);
|
||||
pserialize_read_exit(s);
|
||||
/*
|
||||
* Random factor is introduced in the preferred lifetime, so
|
||||
* we do not need additional delay (3rd arg to in6_tmpifadd).
|
||||
*/
|
||||
if ((e = in6_tmpifadd(public_ifa6, 0, 0)) != 0) {
|
||||
ia6_release(public_ifa6, &psref);
|
||||
log(LOG_NOTICE, "regen_tmpaddr: failed to create a new"
|
||||
" tmp addr, errno=%d\n", e);
|
||||
return -1;
|
||||
}
|
||||
ia6_release(public_ifa6, &psref);
|
||||
return 0;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -914,6 +937,7 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
|
|||
{
|
||||
struct nd_prefix *pr;
|
||||
struct ifaddr *dstaddr;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* A link-local address is always a neighbor.
|
||||
|
@ -979,20 +1003,15 @@ nd6_is_new_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
|
|||
* If the address is assigned on the node of the other side of
|
||||
* a p2p interface, the address should be a neighbor.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
dstaddr = ifa_ifwithdstaddr(sin6tocsa(addr));
|
||||
if (dstaddr != NULL) {
|
||||
if (dstaddr->ifa_ifp == ifp) {
|
||||
#ifdef __FreeBSD__
|
||||
/* XXX we need to ifaref in ifa_ifwithdstaddr as well */
|
||||
ifafree(dstaddr);
|
||||
#endif
|
||||
pserialize_read_exit(s);
|
||||
return 1;
|
||||
}
|
||||
#ifdef __FreeBSD__
|
||||
/* XXX we need to ifaref in ifa_ifwithdstaddr as well */
|
||||
ifafree(dstaddr);
|
||||
#endif
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* If the default router list is empty, all addresses are regarded
|
||||
|
@ -1374,7 +1393,9 @@ nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
}
|
||||
|
||||
switch (req) {
|
||||
case RTM_ADD:
|
||||
case RTM_ADD: {
|
||||
int s;
|
||||
|
||||
RT_DPRINTF("rt_getkey(rt) = %p\n", rt_getkey(rt));
|
||||
/*
|
||||
* There is no backward compatibility :)
|
||||
|
@ -1481,6 +1502,7 @@ nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
* check if rt_getkey(rt) is an address assigned
|
||||
* to the interface.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp,
|
||||
&satocsin6(rt_getkey(rt))->sin6_addr);
|
||||
if (ifa != NULL) {
|
||||
|
@ -1517,8 +1539,8 @@ nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
pserialize_read_exit(s);
|
||||
/*
|
||||
* If we have too many cache entries, initiate immediate
|
||||
* purging for some entries.
|
||||
|
@ -1526,6 +1548,7 @@ nd6_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info)
|
|||
if (rt->rt_ifp != NULL)
|
||||
nd6_gc_neighbors(LLTABLE6(rt->rt_ifp));
|
||||
break;
|
||||
}
|
||||
|
||||
case RTM_DELETE:
|
||||
/* leave from solicited node multicast for proxy ND */
|
||||
|
@ -1709,6 +1732,7 @@ nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
|
|||
*/
|
||||
int duplicated_linklocal = 0;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
|
@ -1720,6 +1744,7 @@ nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
|
|||
break;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (duplicated_linklocal) {
|
||||
ND.flags |= ND6_IFF_IFDISABLED;
|
||||
|
@ -1732,18 +1757,29 @@ nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
|
|||
in6_if_up(ifp);
|
||||
}
|
||||
} else if (!(ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) &&
|
||||
(ND.flags & ND6_IFF_IFDISABLED))
|
||||
{
|
||||
(ND.flags & ND6_IFF_IFDISABLED)) {
|
||||
int bound = curlwp_bind();
|
||||
/* Mark all IPv6 addresses as tentative. */
|
||||
|
||||
ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct psref psref;
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
continue;
|
||||
ifa_acquire(ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
nd6_dad_stop(ifa);
|
||||
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
ia->ia6_flags |= IN6_IFF_TENTATIVE;
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ifa_release(ifa, &psref);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
curlwp_bindx(bound);
|
||||
}
|
||||
|
||||
if (ND.flags & ND6_IFF_AUTO_LINKLOCAL) {
|
||||
|
@ -1761,9 +1797,10 @@ nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
|
|||
* address is assigned, and IFF_UP, try to
|
||||
* assign one.
|
||||
*/
|
||||
int haslinklocal = 0;
|
||||
int haslinklocal = 0;
|
||||
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family !=AF_INET6)
|
||||
continue;
|
||||
ia = (struct in6_ifaddr *)ifa;
|
||||
|
@ -1771,8 +1808,9 @@ nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
|
|||
haslinklocal = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!haslinklocal)
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
if (!haslinklocal)
|
||||
in6_ifattach(ifp, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -1793,22 +1831,30 @@ nd6_ioctl(u_long cmd, void *data, struct ifnet *ifp)
|
|||
s = splsoftnet();
|
||||
LIST_FOREACH_SAFE(pfx, &nd_prefix, ndpr_entry, next) {
|
||||
struct in6_ifaddr *ia, *ia_next;
|
||||
int _s;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&pfx->ndpr_prefix.sin6_addr))
|
||||
continue; /* XXX */
|
||||
|
||||
/* do we really have to remove addresses as well? */
|
||||
for (ia = IN6_ADDRLIST_WRITER_FIRST(); ia;
|
||||
restart:
|
||||
_s = pserialize_read_enter();
|
||||
for (ia = IN6_ADDRLIST_READER_FIRST(); ia;
|
||||
ia = ia_next) {
|
||||
/* ia might be removed. keep the next ptr. */
|
||||
ia_next = IN6_ADDRLIST_WRITER_NEXT(ia);
|
||||
ia_next = IN6_ADDRLIST_READER_NEXT(ia);
|
||||
|
||||
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
|
||||
continue;
|
||||
|
||||
if (ia->ia6_ndpr == pfx)
|
||||
if (ia->ia6_ndpr == pfx) {
|
||||
pserialize_read_exit(_s);
|
||||
/* XXX NOMPSAFE? */
|
||||
in6_purgeaddr(&ia->ia_ifa);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(_s);
|
||||
prelist_remove(pfx);
|
||||
}
|
||||
splx(s);
|
||||
|
@ -2172,6 +2218,7 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
|||
|
||||
if (rt != NULL && (rt->rt_flags & RTF_GATEWAY) != 0) {
|
||||
struct sockaddr_in6 *gw6 = satosin6(rt->rt_gateway);
|
||||
int s;
|
||||
|
||||
/* XXX remain the check to keep the original behavior. */
|
||||
/*
|
||||
|
@ -2182,6 +2229,7 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
|||
* if the gateway is our own address, which is
|
||||
* sometimes used to install a route to a p2p link.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
if (!nd6_is_addr_neighbor(gw6, ifp) ||
|
||||
in6ifa_ifpwithaddr(ifp, &gw6->sin6_addr)) {
|
||||
/*
|
||||
|
@ -2192,8 +2240,10 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m,
|
|||
if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
|
||||
senderr(EHOSTUNREACH);
|
||||
|
||||
pserialize_read_exit(s);
|
||||
goto sendpkt;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nd6_nbr.c,v 1.126 2016/07/28 09:03:50 ozaki-r Exp $ */
|
||||
/* $NetBSD: nd6_nbr.c,v 1.127 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.126 2016/07/28 09:03:50 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.127 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -104,7 +104,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
|||
struct in6_addr taddr6;
|
||||
struct in6_addr myaddr6;
|
||||
char *lladdr = NULL;
|
||||
struct ifaddr *ifa;
|
||||
struct ifaddr *ifa = NULL;
|
||||
int lladdrlen = 0;
|
||||
int anycast = 0, proxy = 0, tentative = 0;
|
||||
int router = ip6_forwarding;
|
||||
|
@ -112,6 +112,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
|||
union nd_opts ndopts;
|
||||
const struct sockaddr_dl *proxydl = NULL;
|
||||
struct psref psref;
|
||||
struct psref psref_ia;
|
||||
|
||||
ifp = m_get_rcvif_psref(m, &psref);
|
||||
if (ifp == NULL)
|
||||
|
@ -216,14 +217,20 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
|||
*/
|
||||
/* (1) and (3) check. */
|
||||
#if NCARP > 0
|
||||
if (ifp->if_carp && ifp->if_type != IFT_CARP)
|
||||
if (ifp->if_carp && ifp->if_type != IFT_CARP) {
|
||||
int s = pserialize_read_enter();
|
||||
ifa = carp_iamatch6(ifp->if_carp, &taddr6);
|
||||
else
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, &psref_ia);
|
||||
pserialize_read_exit(s);
|
||||
} else
|
||||
ifa = NULL;
|
||||
if (!ifa)
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr_psref(ifp, &taddr6,
|
||||
&psref_ia);
|
||||
#else
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr_psref(ifp, &taddr6,
|
||||
&psref_ia);
|
||||
#endif
|
||||
|
||||
/* (2) check. */
|
||||
|
@ -239,8 +246,8 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
|||
/*
|
||||
* proxy NDP for single entry
|
||||
*/
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
|
||||
IN6_IFF_NOTREADY|IN6_IFF_ANYCAST);
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal_psref(ifp,
|
||||
IN6_IFF_NOTREADY|IN6_IFF_ANYCAST, &psref_ia);
|
||||
if (ifa) {
|
||||
proxy = 1;
|
||||
proxydl = satocsdl(rt->rt_gateway);
|
||||
|
@ -299,9 +306,13 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
|||
*/
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
|
||||
nd6_dad_ns_input(ifa);
|
||||
ifa_release(ifa, &psref_ia);
|
||||
ifa = NULL;
|
||||
|
||||
goto freeit;
|
||||
}
|
||||
ifa_release(ifa, &psref_ia);
|
||||
ifa = NULL;
|
||||
|
||||
/*
|
||||
* If the source address is unspecified address, entries must not
|
||||
|
@ -331,6 +342,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
|||
(router ? ND_NA_FLAG_ROUTER : 0) | ND_NA_FLAG_SOLICITED,
|
||||
tlladdr, (const struct sockaddr *)proxydl);
|
||||
freeit:
|
||||
ifa_release(ifa, &psref_ia);
|
||||
m_put_rcvif_psref(ifp, &psref);
|
||||
m_freem(m);
|
||||
return;
|
||||
|
@ -340,6 +352,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
|
|||
nd6log(LOG_ERR, "dst=%s\n", ip6_sprintf(&daddr6));
|
||||
nd6log(LOG_ERR, "tgt=%s\n", ip6_sprintf(&taddr6));
|
||||
ICMP6_STATINC(ICMP6_STAT_BADNS);
|
||||
ifa_release(ifa, &psref_ia);
|
||||
m_put_rcvif_psref(ifp, &psref);
|
||||
m_freem(m);
|
||||
}
|
||||
|
@ -430,6 +443,7 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
|
|||
goto bad;
|
||||
}
|
||||
if (!dad) {
|
||||
int s;
|
||||
/*
|
||||
* RFC2461 7.2.2:
|
||||
* "If the source address of the packet prompting the
|
||||
|
@ -445,6 +459,7 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
|
|||
* - hsrc belongs to the outgoing interface.
|
||||
* Otherwise, we perform the source address selection as usual.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
if (hsrc && in6ifa_ifpwithaddr(ifp, hsrc))
|
||||
src = hsrc;
|
||||
else {
|
||||
|
@ -459,9 +474,11 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
|
|||
nd6log(LOG_DEBUG, "source can't be "
|
||||
"determined: dst=%s, error=%d\n",
|
||||
ip6_sprintf(&dst_sa.sin6_addr), error);
|
||||
pserialize_read_exit(s);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
} else {
|
||||
/*
|
||||
* Source address for DAD packet must always be IPv6
|
||||
|
@ -559,6 +576,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
|||
int rt_announce;
|
||||
bool checklink = false;
|
||||
struct psref psref;
|
||||
struct psref psref_ia;
|
||||
|
||||
ifp = m_get_rcvif_psref(m, &psref);
|
||||
if (ifp == NULL)
|
||||
|
@ -613,7 +631,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
|||
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
|
||||
}
|
||||
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &taddr6);
|
||||
ifa = (struct ifaddr *)in6ifa_ifpwithaddr_psref(ifp, &taddr6, &psref_ia);
|
||||
|
||||
/*
|
||||
* Target address matches one of my interface address.
|
||||
|
@ -627,6 +645,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
|||
if (ifa
|
||||
&& (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_TENTATIVE)) {
|
||||
nd6_dad_na_input(ifa);
|
||||
ifa_release(ifa, &psref_ia);
|
||||
ifa = NULL;
|
||||
goto freeit;
|
||||
}
|
||||
|
||||
|
@ -635,6 +655,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
|
|||
log(LOG_ERR,
|
||||
"nd6_na_input: duplicate IP6 address %s\n",
|
||||
ip6_sprintf(&taddr6));
|
||||
ifa_release(ifa, &psref_ia);
|
||||
ifa = NULL;
|
||||
goto freeit;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nd6_rtr.c,v 1.117 2016/07/20 07:37:51 ozaki-r Exp $ */
|
||||
/* $NetBSD: nd6_rtr.c,v 1.118 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: nd6_rtr.c,v 1.95 2001/02/07 08:09:47 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -31,7 +31,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.117 2016/07/20 07:37:51 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.118 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -66,7 +66,7 @@ static int rtpref(struct nd_defrouter *);
|
|||
static struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
|
||||
static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *,
|
||||
struct mbuf *, int);
|
||||
static struct in6_ifaddr *in6_ifadd(struct nd_prefixctl *, int);
|
||||
static struct in6_ifaddr *in6_ifadd(struct nd_prefixctl *, int, struct psref *);
|
||||
static struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *,
|
||||
struct nd_defrouter *);
|
||||
static void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *);
|
||||
|
@ -898,6 +898,7 @@ purge_detached(struct ifnet *ifp)
|
|||
struct ifaddr *ifa, *ifa_next;
|
||||
|
||||
for (pr = nd_prefix.lh_first; pr; pr = pr_next) {
|
||||
int s;
|
||||
pr_next = pr->ndpr_next;
|
||||
|
||||
/*
|
||||
|
@ -913,6 +914,8 @@ purge_detached(struct ifnet *ifp)
|
|||
!LIST_EMPTY(&pr->ndpr_advrtrs)))
|
||||
continue;
|
||||
|
||||
restart:
|
||||
s = pserialize_read_enter();
|
||||
for (ifa = IFADDR_READER_FIRST(ifp); ifa; ifa = ifa_next) {
|
||||
ifa_next = IFADDR_READER_NEXT(ifa);
|
||||
if (ifa->ifa_addr->sa_family != AF_INET6)
|
||||
|
@ -920,9 +923,13 @@ purge_detached(struct ifnet *ifp)
|
|||
ia = (struct in6_ifaddr *)ifa;
|
||||
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) ==
|
||||
IN6_IFF_AUTOCONF && ia->ia6_ndpr == pr) {
|
||||
pserialize_read_exit(s);
|
||||
in6_purgeaddr(ifa);
|
||||
goto restart;
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (pr->ndpr_refcnt == 0)
|
||||
prelist_remove(pr);
|
||||
}
|
||||
|
@ -1065,6 +1072,7 @@ prelist_update(struct nd_prefixctl *newprc,
|
|||
int error = 0;
|
||||
int auth;
|
||||
struct in6_addrlifetime lt6_tmp;
|
||||
int ss;
|
||||
|
||||
auth = 0;
|
||||
if (m) {
|
||||
|
@ -1187,6 +1195,7 @@ prelist_update(struct nd_prefixctl *newprc,
|
|||
* consider autoconfigured addresses while RFC2462 simply said
|
||||
* "address".
|
||||
*/
|
||||
ss = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
struct in6_ifaddr *ia6;
|
||||
u_int32_t remaininglifetime;
|
||||
|
@ -1308,9 +1317,12 @@ prelist_update(struct nd_prefixctl *newprc,
|
|||
ia6->ia6_lifetime = lt6_tmp;
|
||||
ia6->ia6_updatetime = time_uptime;
|
||||
}
|
||||
pserialize_read_exit(ss);
|
||||
|
||||
if (ia6_match == NULL && newprc->ndprc_vltime) {
|
||||
int ifidlen;
|
||||
struct in6_ifaddr *ia6;
|
||||
struct psref psref;
|
||||
|
||||
/*
|
||||
* 5.5.3 (d) (continued)
|
||||
|
@ -1340,7 +1352,7 @@ prelist_update(struct nd_prefixctl *newprc,
|
|||
goto end;
|
||||
}
|
||||
|
||||
if ((ia6 = in6_ifadd(newprc, mcast)) != NULL) {
|
||||
if ((ia6 = in6_ifadd(newprc, mcast, &psref)) != NULL) {
|
||||
/*
|
||||
* note that we should use pr (not newprc) for reference.
|
||||
*/
|
||||
|
@ -1367,6 +1379,7 @@ prelist_update(struct nd_prefixctl *newprc,
|
|||
"address, errno=%d\n", e);
|
||||
}
|
||||
}
|
||||
ia6_release(ia6, &psref);
|
||||
|
||||
/*
|
||||
* A newly added address might affect the status
|
||||
|
@ -1426,6 +1439,7 @@ pfxlist_onlink_check(void)
|
|||
struct in6_ifaddr *ia;
|
||||
struct nd_defrouter *dr;
|
||||
struct nd_pfxrouter *pfxrtr = NULL;
|
||||
int s;
|
||||
|
||||
/*
|
||||
* Check if there is a prefix that has a reachable advertising
|
||||
|
@ -1540,6 +1554,7 @@ pfxlist_onlink_check(void)
|
|||
* always be attached.
|
||||
* The precise detection logic is same as the one for prefixes.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
IN6_ADDRLIST_READER_FOREACH(ia) {
|
||||
if (!(ia->ia6_flags & IN6_IFF_AUTOCONF))
|
||||
continue;
|
||||
|
@ -1556,20 +1571,30 @@ pfxlist_onlink_check(void)
|
|||
if (find_pfxlist_reachable_router(ia->ia6_ndpr))
|
||||
break;
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (ia) {
|
||||
int bound = curlwp_bind();
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IN6_ADDRLIST_READER_FOREACH(ia) {
|
||||
struct ifaddr *ifa = (struct ifaddr *)ia;
|
||||
struct psref psref;
|
||||
|
||||
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
|
||||
continue;
|
||||
|
||||
if (ia->ia6_ndpr == NULL) /* XXX: see above. */
|
||||
continue;
|
||||
|
||||
ia6_acquire(ia, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
if (find_pfxlist_reachable_router(ia->ia6_ndpr)) {
|
||||
if (ia->ia6_flags & IN6_IFF_DETACHED) {
|
||||
ia->ia6_flags &= ~IN6_IFF_DETACHED;
|
||||
ia->ia6_flags |= IN6_IFF_TENTATIVE;
|
||||
nd6_dad_start((struct ifaddr *)ia,
|
||||
nd6_dad_start(ifa,
|
||||
0);
|
||||
/* We will notify the routing socket
|
||||
* of the DAD result, so no need to
|
||||
|
@ -1579,23 +1604,43 @@ pfxlist_onlink_check(void)
|
|||
if ((ia->ia6_flags & IN6_IFF_DETACHED) == 0) {
|
||||
ia->ia6_flags |= IN6_IFF_DETACHED;
|
||||
rt_newaddrmsg(RTM_NEWADDR,
|
||||
(struct ifaddr *)ia, 0, NULL);
|
||||
ifa, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia6_release(ia, &psref);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
curlwp_bindx(bound);
|
||||
}
|
||||
else {
|
||||
int bound = curlwp_bind();
|
||||
|
||||
s = pserialize_read_enter();
|
||||
IN6_ADDRLIST_READER_FOREACH(ia) {
|
||||
if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0)
|
||||
continue;
|
||||
|
||||
if (ia->ia6_flags & IN6_IFF_DETACHED) {
|
||||
struct ifaddr *ifa = (struct ifaddr *)ia;
|
||||
struct psref psref;
|
||||
|
||||
ia->ia6_flags &= ~IN6_IFF_DETACHED;
|
||||
ia->ia6_flags |= IN6_IFF_TENTATIVE;
|
||||
|
||||
ia6_acquire(ia, &psref);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/* Do we need a delay in this case? */
|
||||
nd6_dad_start((struct ifaddr *)ia, 0);
|
||||
nd6_dad_start(ifa, 0);
|
||||
|
||||
s = pserialize_read_enter();
|
||||
ia6_release(ia, &psref);
|
||||
}
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
curlwp_bindx(bound);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1608,6 +1653,8 @@ nd6_prefix_onlink(struct nd_prefix *pr)
|
|||
struct nd_prefix *opr;
|
||||
u_long rtflags;
|
||||
int error = 0;
|
||||
struct psref psref;
|
||||
int bound;
|
||||
|
||||
/* sanity check */
|
||||
if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
|
||||
|
@ -1640,14 +1687,18 @@ nd6_prefix_onlink(struct nd_prefix *pr)
|
|||
* We prefer link-local addresses as the associated interface address.
|
||||
*/
|
||||
/* search for a link-local addr */
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp,
|
||||
IN6_IFF_NOTREADY | IN6_IFF_ANYCAST);
|
||||
bound = curlwp_bind();
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal_psref(ifp,
|
||||
IN6_IFF_NOTREADY | IN6_IFF_ANYCAST, &psref);
|
||||
if (ifa == NULL) {
|
||||
/* XXX: freebsd does not have ifa_ifwithaf */
|
||||
int s = pserialize_read_enter();
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family == AF_INET6)
|
||||
break;
|
||||
}
|
||||
if (ifa != NULL)
|
||||
ifa_acquire(ifa, &psref);
|
||||
pserialize_read_exit(s);
|
||||
/* should we care about ia6_flags? */
|
||||
}
|
||||
if (ifa == NULL) {
|
||||
|
@ -1661,6 +1712,7 @@ nd6_prefix_onlink(struct nd_prefix *pr)
|
|||
" to add route for a prefix(%s/%d) on %s\n",
|
||||
ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
|
||||
pr->ndpr_plen, if_name(ifp));
|
||||
curlwp_bindx(bound);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1697,6 +1749,8 @@ nd6_prefix_onlink(struct nd_prefix *pr)
|
|||
ip6_sprintf(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
|
||||
ip6_sprintf(&mask6.sin6_addr), rtflags, error);
|
||||
}
|
||||
ifa_release(ifa, &psref);
|
||||
curlwp_bindx(bound);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -1772,7 +1826,7 @@ nd6_prefix_offlink(struct nd_prefix *pr)
|
|||
}
|
||||
|
||||
static struct in6_ifaddr *
|
||||
in6_ifadd(struct nd_prefixctl *prc, int mcast)
|
||||
in6_ifadd(struct nd_prefixctl *prc, int mcast, struct psref *psref)
|
||||
{
|
||||
struct ifnet *ifp = prc->ndprc_ifp;
|
||||
struct ifaddr *ifa;
|
||||
|
@ -1782,6 +1836,7 @@ in6_ifadd(struct nd_prefixctl *prc, int mcast)
|
|||
struct in6_addr mask;
|
||||
int prefixlen = prc->ndprc_plen;
|
||||
int updateflags;
|
||||
int s;
|
||||
|
||||
in6_prefixlen2mask(&mask, prefixlen);
|
||||
|
||||
|
@ -1805,11 +1860,14 @@ in6_ifadd(struct nd_prefixctl *prc, int mcast)
|
|||
* with the same interface identifier, than to have multiple addresses
|
||||
* with different interface identifiers.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
ifa = (struct ifaddr *)in6ifa_ifpforlinklocal(ifp, 0); /* 0 is OK? */
|
||||
if (ifa)
|
||||
ib = (struct in6_ifaddr *)ifa;
|
||||
else
|
||||
else {
|
||||
pserialize_read_exit(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0 /* don't care link local addr state, and always do DAD */
|
||||
/* if link-local address is not eligible, do not autoconfigure. */
|
||||
|
@ -1825,6 +1883,7 @@ in6_ifadd(struct nd_prefixctl *prc, int mcast)
|
|||
nd6log(LOG_INFO, "wrong prefixlen for %s "
|
||||
"(prefix=%d ifid=%d)\n",
|
||||
if_name(ifp), prefixlen, 128 - plen0);
|
||||
pserialize_read_exit(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1852,6 +1911,7 @@ in6_ifadd(struct nd_prefixctl *prc, int mcast)
|
|||
(ib->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
|
||||
ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
|
||||
(ib->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/* new prefix mask. */
|
||||
sockaddr_in6_init(&ifra.ifra_prefixmask, &mask, 0, 0, 0);
|
||||
|
@ -1869,12 +1929,15 @@ in6_ifadd(struct nd_prefixctl *prc, int mcast)
|
|||
* usually not happen, but we can still see this case, e.g., if we
|
||||
* have manually configured the exact address to be configured.
|
||||
*/
|
||||
s = pserialize_read_enter();
|
||||
if (in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr) != NULL) {
|
||||
/* this should be rare enough to make an explicit log */
|
||||
log(LOG_INFO, "in6_ifadd: %s is already configured\n",
|
||||
ip6_sprintf(&ifra.ifra_addr.sin6_addr));
|
||||
pserialize_read_exit(s);
|
||||
return (NULL);
|
||||
}
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* Allocate ifaddr structure, link into chain, etc.
|
||||
|
@ -1892,7 +1955,7 @@ in6_ifadd(struct nd_prefixctl *prc, int mcast)
|
|||
return (NULL); /* ifaddr must not have been allocated. */
|
||||
}
|
||||
|
||||
ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
|
||||
ia = in6ifa_ifpwithaddr_psref(ifp, &ifra.ifra_addr.sin6_addr, psref);
|
||||
|
||||
return (ia); /* this is always non-NULL */
|
||||
}
|
||||
|
@ -2007,14 +2070,17 @@ in6_tmpifadd(
|
|||
if ((error = in6_update_ifa(ifp, &ifra, NULL, updateflags)) != 0)
|
||||
return (error);
|
||||
|
||||
s = pserialize_read_enter();
|
||||
newia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
|
||||
if (newia == NULL) { /* XXX: can it happen? */
|
||||
pserialize_read_exit(s);
|
||||
nd6log(LOG_ERR,
|
||||
"ifa update succeeded, but we got no ifaddr\n");
|
||||
return (EINVAL); /* XXX */
|
||||
}
|
||||
newia->ia6_ndpr = ia0->ia6_ndpr;
|
||||
newia->ia6_ndpr->ndpr_refcnt++;
|
||||
pserialize_read_exit(s);
|
||||
|
||||
/*
|
||||
* A newly added address might affect the status of other addresses.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: raw_ip6.c,v 1.148 2016/07/15 07:40:09 ozaki-r Exp $ */
|
||||
/* $NetBSD: raw_ip6.c,v 1.149 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.148 2016/07/15 07:40:09 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.149 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -671,8 +671,9 @@ rip6_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
|
|||
{
|
||||
struct in6pcb *in6p = sotoin6pcb(so);
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
|
||||
struct ifaddr *ia = NULL;
|
||||
struct ifaddr *ifa = NULL;
|
||||
int error = 0;
|
||||
int s;
|
||||
|
||||
KASSERT(solocked(so));
|
||||
KASSERT(in6p != NULL);
|
||||
|
@ -692,15 +693,24 @@ rip6_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
|
|||
*/
|
||||
if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
|
||||
return EADDRNOTAVAIL;
|
||||
s = pserialize_read_enter();
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
|
||||
(ia = ifa_ifwithaddr(sin6tosa(addr))) == 0)
|
||||
return EADDRNOTAVAIL;
|
||||
if (ia && ifatoia6(ia)->ia6_flags &
|
||||
(ifa = ifa_ifwithaddr(sin6tosa(addr))) == NULL) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
if (ifa && (ifatoia6(ifa))->ia6_flags &
|
||||
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
|
||||
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED))
|
||||
return EADDRNOTAVAIL;
|
||||
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
|
||||
error = EADDRNOTAVAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
in6p->in6p_laddr = addr->sin6_addr;
|
||||
return 0;
|
||||
error = 0;
|
||||
out:
|
||||
pserialize_read_exit(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* $KAME: sctp6_usrreq.c,v 1.38 2005/08/24 08:08:56 suz Exp $ */
|
||||
/* $NetBSD: sctp6_usrreq.c,v 1.7 2016/07/15 07:40:09 ozaki-r Exp $ */
|
||||
/* $NetBSD: sctp6_usrreq.c,v 1.8 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
|
||||
|
@ -33,7 +33,7 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sctp6_usrreq.c,v 1.7 2016/07/15 07:40:09 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sctp6_usrreq.c,v 1.8 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -1294,6 +1294,7 @@ static int
|
|||
sctp6_purgeif(struct socket *so, struct ifnet *ifp)
|
||||
{
|
||||
struct ifaddr *ifa;
|
||||
/* FIXME NOMPSAFE */
|
||||
IFADDR_READER_FOREACH(ifa, ifp) {
|
||||
if (ifa->ifa_addr->sa_family == PF_INET6) {
|
||||
sctp_delete_ip_address(ifa);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: udp6_output.c,v 1.52 2016/06/21 10:25:27 ozaki-r Exp $ */
|
||||
/* $NetBSD: udp6_output.c,v 1.53 2016/08/01 03:15:31 ozaki-r Exp $ */
|
||||
/* $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.52 2016/06/21 10:25:27 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.53 2016/08/01 03:15:31 ozaki-r Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_inet.h"
|
||||
|
@ -227,6 +227,7 @@ udp6_output(struct in6pcb * const in6p, struct mbuf *m,
|
|||
|
||||
if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
|
||||
struct psref psref;
|
||||
int bound = curlwp_bind();
|
||||
|
||||
laddr = in6_selectsrc(sin6, optp,
|
||||
in6p->in6p_moptions,
|
||||
|
@ -236,9 +237,11 @@ udp6_output(struct in6pcb * const in6p, struct mbuf *m,
|
|||
(error = in6_setscope(&sin6->sin6_addr,
|
||||
oifp, NULL))) {
|
||||
if_put(oifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
goto release;
|
||||
}
|
||||
if_put(oifp, &psref);
|
||||
curlwp_bindx(bound);
|
||||
} else {
|
||||
/*
|
||||
* XXX: freebsd[34] does not have in_selectsrc, but
|
||||
|
@ -247,15 +250,20 @@ udp6_output(struct in6pcb * const in6p, struct mbuf *m,
|
|||
* never see this path.
|
||||
*/
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
|
||||
struct sockaddr_in *sinp, sin_dst;
|
||||
struct sockaddr_in sin_dst;
|
||||
struct in_addr ina;
|
||||
struct in_ifaddr *ia4;
|
||||
struct psref _psref;
|
||||
int bound;
|
||||
|
||||
memcpy(&ina, &faddr->s6_addr[12], sizeof(ina));
|
||||
sockaddr_in_init(&sin_dst, &ina, 0);
|
||||
sinp = in_selectsrc(&sin_dst, &in6p->in6p_route,
|
||||
bound = curlwp_bind();
|
||||
ia4 = in_selectsrc(&sin_dst, &in6p->in6p_route,
|
||||
in6p->in6p_socket->so_options, NULL,
|
||||
&error);
|
||||
if (sinp == NULL) {
|
||||
&error, &_psref);
|
||||
if (ia4 == NULL) {
|
||||
curlwp_bindx(bound);
|
||||
if (error == 0)
|
||||
error = EADDRNOTAVAIL;
|
||||
goto release;
|
||||
|
@ -263,8 +271,10 @@ udp6_output(struct in6pcb * const in6p, struct mbuf *m,
|
|||
memset(&laddr_mapped, 0, sizeof(laddr_mapped));
|
||||
laddr_mapped.s6_addr16[5] = 0xffff; /* ugly */
|
||||
memcpy(&laddr_mapped.s6_addr[12],
|
||||
&sinp->sin_addr,
|
||||
sizeof(sinp->sin_addr));
|
||||
&IA_SIN(ia4)->sin_addr,
|
||||
sizeof(IA_SIN(ia4)->sin_addr));
|
||||
ia4_release(ia4, &_psref);
|
||||
curlwp_bindx(bound);
|
||||
laddr = &laddr_mapped;
|
||||
} else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue