First-draft if_detach() implementation, originally from Bill Studnemund,

although this version has been changed somewhat:
- reference counting on ifaddrs isn't as complete as Bill's original
  work was.  This is hard to get right, and we should attack one
  protocol at a time.
- This doesn't do reference counting or dynamic allocation of ifnets yet.
- This version introduces a new PRU -- PRU_PURGEADDR, which is used to
  purge an ifaddr from a protocol.  The old method Bill used didn't work
  on all protocols, and it only worked on some because it was Very Lucky.

This mostly works ... i.e. works for my USB Ethernet, except for a dangling
ifaddr reference left by the IPv6 code; have not yet tracked this down.
This commit is contained in:
thorpej 2000-02-01 22:52:04 +00:00
parent d8e72e215d
commit d844a3ac41
31 changed files with 754 additions and 218 deletions

View File

@ -1,4 +1,40 @@
/* $NetBSD: if.c,v 1.52 1999/09/29 22:42:02 thorpej Exp $ */
/* $NetBSD: if.c,v 1.53 2000/02/01 22:52:04 thorpej Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by William Studnemund and Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -85,6 +121,7 @@
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/radix.h>
#include <net/route.h>
#ifdef NETATALK
#include <netatalk/at_extern.h>
#include <netatalk/at.h>
@ -106,6 +143,8 @@ void if_slowtimo __P((void *arg));
extern void nd6_setmtu __P((struct ifnet *));
#endif
int if_rt_walktree __P((struct radix_node *, void *));
/*
* Network interface utility routines.
*
@ -119,6 +158,81 @@ ifinit()
if_slowtimo(NULL);
}
/*
* Null routines used while an interface is going away. These routines
* just return an error.
*/
int if_nulloutput __P((struct ifnet *, struct mbuf *,
struct sockaddr *, struct rtentry *));
void if_nullinput __P((struct ifnet *, struct mbuf *));
void if_nullstart __P((struct ifnet *));
int if_nullioctl __P((struct ifnet *, u_long, caddr_t));
int if_nullreset __P((struct ifnet *));
void if_nullwatchdog __P((struct ifnet *));
void if_nulldrain __P((struct ifnet *));
int
if_nulloutput(ifp, m, so, rt)
struct ifnet *ifp;
struct mbuf *m;
struct sockaddr *so;
struct rtentry *rt;
{
return (ENXIO);
}
void
if_nullinput(ifp, m)
struct ifnet *ifp;
struct mbuf *m;
{
/* Nothing. */
}
void
if_nullstart(ifp)
struct ifnet *ifp;
{
/* Nothing. */
}
int
if_nullioctl(ifp, cmd, data)
struct ifnet *ifp;
u_long cmd;
caddr_t data;
{
return (ENXIO);
}
int
if_nullreset(ifp)
struct ifnet *ifp;
{
return (ENXIO);
}
void
if_nullwatchdog(ifp)
struct ifnet *ifp;
{
/* Nothing. */
}
void
if_nulldrain(ifp)
struct ifnet *ifp;
{
/* Nothing. */
}
int if_index = 0;
struct ifaddr **ifnet_addrs = NULL;
struct ifnet **ifindex2ifnet = NULL;
@ -149,11 +263,12 @@ if_attach(ifp)
* struct ifadd **ifnet_addrs
* struct ifnet **ifindex2ifnet
*/
if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
if (ifnet_addrs == 0 || ifindex2ifnet == 0 ||
ifp->if_index >= if_indexlim) {
size_t n;
caddr_t q;
while (if_index >= if_indexlim)
while (ifp->if_index >= if_indexlim)
if_indexlim <<= 1;
/* grow ifnet_addrs */
@ -177,7 +292,7 @@ if_attach(ifp)
ifindex2ifnet = (struct ifnet **)q;
}
ifindex2ifnet[if_index] = ifp;
ifindex2ifnet[ifp->if_index] = ifp;
/*
* create a Link Level name for this device
@ -199,10 +314,12 @@ if_attach(ifp)
sdl->sdl_nlen = namelen;
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = ifp->if_type;
ifnet_addrs[if_index] = ifa;
ifnet_addrs[ifp->if_index] = ifa;
IFAREF(ifa);
ifa->ifa_ifp = ifp;
ifa->ifa_rtrequest = link_rtrequest;
TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
IFAREF(ifa);
ifa->ifa_addr = (struct sockaddr *)sdl;
ifp->if_sadl = sdl;
sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
@ -214,6 +331,144 @@ if_attach(ifp)
ifp->if_snd.ifq_maxlen = ifqmaxlen;
ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */
}
/*
* Deactivate an interface. This points all of the procedure
* handles at error stubs. May be called from interrupt context.
*/
void
if_deactivate(ifp)
struct ifnet *ifp;
{
int s;
s = splimp();
ifp->if_output = if_nulloutput;
ifp->if_input = if_nullinput;
ifp->if_start = if_nullstart;
ifp->if_ioctl = if_nullioctl;
ifp->if_reset = if_nullreset;
ifp->if_watchdog = if_nullwatchdog;
ifp->if_drain = if_nulldrain;
/* No more packets may be enqueued. */
ifp->if_snd.ifq_maxlen = 0;
splx(s);
}
/*
* Detach an interface from the list of "active" interfaces,
* freeing any resources as we go along.
*
* NOTE: This routine must be called with a valid thread context,
* as it may block.
*/
void
if_detach(ifp)
struct ifnet *ifp;
{
struct ifaddr *ifa;
#ifdef IFAREF_DEBUG
struct ifaddr *last_ifa = NULL;
#endif
struct protosw *pr;
struct socket so;
struct radix_node_head *rnh;
int s, i;
/* XXX Rethink this part. */
so.so_type = SOCK_DGRAM;
so.so_options = 0;
so.so_linger = 0;
so.so_state = SS_NOFDREF | SS_CANTSENDMORE | SS_CANTRCVMORE;
so.so_pcb = 0;
so.so_head = 0;
TAILQ_INIT(&so.so_q0);
TAILQ_INIT(&so.so_q);
so.so_q0len = so.so_qlen = so.so_qlimit = 0;
so.so_timeo = so.so_oobmark = 0;
s = splimp();
/*
* Do an if_down() to give protocols a chance to do something.
*/
if_down(ifp);
/*
* Rip all the addresses off the interface. This should make
* all of the routes go away.
*/
while ((ifa = TAILQ_FIRST(&ifp->if_addrlist)) != NULL) {
#ifdef IFAREF_DEBUG
printf("if_detach: ifaddr %p, family %d, refcnt %d\n",
ifa, ifa->ifa_addr->sa_family, ifa->ifa_refcnt);
if (last_ifa != NULL && ifa == last_ifa)
panic("loop detected");
last_ifa = ifa;
#endif
if (ifa->ifa_addr->sa_family == AF_LINK) {
rtinit(ifa, RTM_DELETE, 0);
TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
IFAFREE(ifa);
} else {
pr = pffindtype(ifa->ifa_addr->sa_family, SOCK_DGRAM);
so.so_proto = pr;
if (pr->pr_usrreq) {
(void) (*pr->pr_usrreq)(&so, PRU_PURGEADDR,
NULL,
(struct mbuf *) ifa,
(struct mbuf *) ifp, curproc);
} else {
rtinit(ifa, RTM_DELETE, 0);
TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
IFAFREE(ifa);
}
}
}
/* Walk the routing table looking for straglers. */
for (i = 1; i <= AF_MAX; i++) {
if ((rnh = rt_tables[i]) != NULL &&
(*rnh->rnh_walktree)(rnh, if_rt_walktree, ifp) != 0)
break;
}
IFAFREE(ifnet_addrs[ifp->if_index]);
ifnet_addrs[ifp->if_index] = NULL;
TAILQ_REMOVE(&ifnet, ifp, if_list);
splx(s);
}
/*
* Callback for a radix tree walk to delete all references to an
* ifnet.
*/
int
if_rt_walktree(rn, v)
struct radix_node *rn;
void *v;
{
struct ifnet *ifp;
struct rtentry *rt = (struct rtentry *)rn;
int error;
if (rt->rt_ifp == ifp) {
/* Delete the entry. */
error = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,
rt_mask(rt), rt->rt_flags, NULL);
if (error)
printf("%s: warning: unable to delete rtentry @ %p, "
"error = %d\n", ifp->if_xname, rt, error);
}
return (0);
}
/*
* Locate an interface based on a complete address.
*/
@ -227,19 +482,26 @@ ifa_ifwithaddr(addr)
#define equal(a1, a2) \
(bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_list)) {
if (ifp->if_output == if_nulloutput)
continue;
if (equal(addr, ifa->ifa_addr))
return (ifa);
if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
/* IP6 doesn't have broadcast */
ifa->ifa_broadaddr->sa_len != 0 &&
equal(ifa->ifa_broadaddr, addr))
return (ifa);
for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
ifa = TAILQ_NEXT(ifa, ifa_list)) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
if (equal(addr, ifa->ifa_addr))
return (ifa);
if ((ifp->if_flags & IFF_BROADCAST) &&
ifa->ifa_broadaddr &&
/* IP6 doesn't have broadcast */
ifa->ifa_broadaddr->sa_len != 0 &&
equal(ifa->ifa_broadaddr, addr))
return (ifa);
}
}
return ((struct ifaddr *)0);
return (NULL);
}
/*
@ -253,16 +515,23 @@ ifa_ifwithdstaddr(addr)
register struct ifnet *ifp;
register struct ifaddr *ifa;
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
if (ifp->if_flags & IFF_POINTOPOINT)
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
if (ifa->ifa_addr->sa_family != addr->sa_family ||
ifa->ifa_dstaddr == NULL)
continue;
if (equal(addr, ifa->ifa_dstaddr))
return (ifa);
for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_list)) {
if (ifp->if_output == if_nulloutput)
continue;
if (ifp->if_flags & IFF_POINTOPOINT) {
for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
ifa = TAILQ_NEXT(ifa, ifa_list)) {
if (ifa->ifa_addr->sa_family !=
addr->sa_family ||
ifa->ifa_dstaddr == NULL)
continue;
if (equal(addr, ifa->ifa_dstaddr))
return (ifa);
}
}
}
return ((struct ifaddr *)0);
return (NULL);
}
/*
@ -275,49 +544,61 @@ ifa_ifwithnet(addr)
{
register struct ifnet *ifp;
register struct ifaddr *ifa;
register struct sockaddr_dl *sdl;
struct ifaddr *ifa_maybe = 0;
u_int af = addr->sa_family;
char *addr_data = addr->sa_data, *cplim;
if (af == AF_LINK) {
register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
if (sdl->sdl_index && sdl->sdl_index <= if_index)
return (ifnet_addrs[sdl->sdl_index]);
sdl = (struct sockaddr_dl *)addr;
if (sdl->sdl_index && sdl->sdl_index <= if_index &&
ifindex2ifnet[sdl->sdl_index]->if_output != if_nulloutput)
return (ifnet_addrs[sdl->sdl_index]);
}
#ifdef NETATALK
if (af == AF_APPLETALK) {
for (ifp = ifnet.tqh_first; ifp != 0;
ifp = ifp->if_list.tqe_next) {
for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_list)) {
if (ifp->if_output == if_nulloutput)
continue;
ifa = at_ifawithnet((struct sockaddr_at *)addr, ifp);
if (ifa)
return ifa;
return (ifa);
}
return NULL;
return (NULL);
}
#endif
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_list)) {
if (ifp->if_output == if_nulloutput)
continue;
for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
ifa = TAILQ_NEXT(ifa, ifa_list)) {
register char *cp, *cp2, *cp3;
if (ifa->ifa_addr->sa_family != af ||
ifa->ifa_netmask == 0)
next: continue;
next: continue;
cp = addr_data;
cp2 = ifa->ifa_addr->sa_data;
cp3 = ifa->ifa_netmask->sa_data;
cplim = (char *)ifa->ifa_netmask +
ifa->ifa_netmask->sa_len;
while (cp3 < cplim)
if ((*cp++ ^ *cp2++) & *cp3++)
/* want to continue for() loop */
ifa->ifa_netmask->sa_len;
while (cp3 < cplim) {
if ((*cp++ ^ *cp2++) & *cp3++) {
/* want to continue for() loop */
goto next;
}
}
if (ifa_maybe == 0 ||
rn_refines((caddr_t)ifa->ifa_netmask,
(caddr_t)ifa_maybe->ifa_netmask))
ifa_maybe = ifa;
}
}
return (ifa_maybe);
}
/*
* Find the interface of the addresss.
*/
@ -327,8 +608,8 @@ ifa_ifwithladdr(addr)
{
struct ifaddr *ia;
if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr))
|| (ia = ifa_ifwithnet(addr)))
if ((ia = ifa_ifwithaddr(addr)) || (ia = ifa_ifwithdstaddr(addr)) ||
(ia = ifa_ifwithnet(addr)))
return (ia);
return (NULL);
}
@ -343,11 +624,17 @@ ifa_ifwithaf(af)
register struct ifnet *ifp;
register struct ifaddr *ifa;
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_list)) {
if (ifp->if_output == if_nulloutput)
continue;
for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
ifa = TAILQ_NEXT(ifa, ifa_list)) {
if (ifa->ifa_addr->sa_family == af)
return (ifa);
return ((struct ifaddr *)0);
}
}
return (NULL);
}
/*
@ -365,15 +652,21 @@ ifaof_ifpforaddr(addr, ifp)
struct ifaddr *ifa_maybe = 0;
u_int af = addr->sa_family;
if (ifp->if_output == if_nulloutput)
return (NULL);
if (af >= AF_MAX)
return (0);
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
return (NULL);
for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
ifa = TAILQ_NEXT(ifa, ifa_list)) {
if (ifa->ifa_addr->sa_family != af)
continue;
ifa_maybe = ifa;
if (ifa->ifa_netmask == 0) {
if (equal(addr, ifa->ifa_addr) ||
(ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
(ifa->ifa_dstaddr &&
equal(addr, ifa->ifa_dstaddr)))
return (ifa);
continue;
}
@ -381,17 +674,16 @@ ifaof_ifpforaddr(addr, ifp)
cp2 = ifa->ifa_addr->sa_data;
cp3 = ifa->ifa_netmask->sa_data;
cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
for (; cp3 < cplim; cp3++)
for (; cp3 < cplim; cp3++) {
if ((*cp++ ^ *cp2++) & *cp3)
break;
}
if (cp3 == cplim)
return (ifa);
}
return (ifa_maybe);
}
#include <net/route.h>
/*
* Default action when installing a route with a Link Level gateway.
* Lookup an appropriate real ifa to point to.
@ -413,7 +705,7 @@ link_rtrequest(cmd, rt, sa)
if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
IFAFREE(rt->rt_ifa);
rt->rt_ifa = ifa;
ifa->ifa_refcnt++;
IFAREF(ifa);
if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
ifa->ifa_rtrequest(cmd, rt, sa);
}
@ -431,7 +723,8 @@ if_down(ifp)
register struct ifaddr *ifa;
ifp->if_flags &= ~IFF_UP;
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next)
for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
ifa = TAILQ_NEXT(ifa, ifa_list))
pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
if_qflush(&ifp->if_snd);
rt_ifmsg(ifp);
@ -453,8 +746,8 @@ if_up(ifp)
ifp->if_flags |= IFF_UP;
#ifdef notyet
/* this has no effect on IP, and will kill all ISO connections XXX */
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
ifa = ifa->ifa_list.tqe_next)
for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa != NULL;
ifa = TAILQ_NEXT(ifa, ifa_list))
pfctlinput(PRC_IFUP, ifa->ifa_addr);
#endif
rt_ifmsg(ifp);
@ -494,7 +787,8 @@ if_slowtimo(arg)
register struct ifnet *ifp;
int s = splimp();
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) {
for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_list)) {
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
if (ifp->if_watchdog)
@ -514,10 +808,13 @@ ifunit(name)
{
register struct ifnet *ifp;
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
if (strcmp(ifp->if_xname, name) == 0)
for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
ifp = TAILQ_NEXT(ifp, if_list)) {
if (ifp->if_output == if_nulloutput)
continue;
if (strcmp(ifp->if_xname, name) == 0)
return (ifp);
}
return (NULL);
}
@ -533,9 +830,9 @@ if_withname(sa)
char ifname[IFNAMSIZ+1];
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
(sdl->sdl_nlen > IFNAMSIZ) )
return NULL;
if ((sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
(sdl->sdl_nlen > IFNAMSIZ))
return (NULL);
/*
* ifunit wants a null-terminated name. It may not be null-terminated

View File

@ -1,4 +1,40 @@
/* $NetBSD: if.h,v 1.43 1999/12/13 15:17:19 itojun Exp $ */
/* $NetBSD: if.h,v 1.44 2000/02/01 22:52:05 thorpej Exp $ */
/*-
* Copyright (c) 1999, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by William Studnemund and Jason R. Thorpe.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1982, 1986, 1989, 1993
@ -158,7 +194,10 @@ struct ifnet { /* and the entries */
short if_flags; /* up/down, broadcast, etc. */
short if__pad1; /* be nice to m68k ports */
struct if_data if_data; /* statistics and other data about if */
/* procedure handles */
/*
* Procedure handles. If you add more of these, don't forget the
* corresponding NULL stub in if.c.
*/
int (*if_output) /* output routine (enqueue) */
__P((struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *));
@ -438,11 +477,43 @@ struct if_laddrreq {
#endif /* !_XOPEN_SOURCE */
#ifdef _KERNEL
#define IFAFREE(ifa) \
if ((ifa)->ifa_refcnt <= 0) \
ifafree(ifa); \
else \
(ifa)->ifa_refcnt--;
#ifdef IFAREF_DEBUG
#define IFAREF(ifa) \
do { \
printf("IFAREF: %s:%d %p -> %d\n", __FILE__, __LINE__, \
(ifa), ++(ifa)->ifa_refcnt); \
} while (0)
#define IFAFREE(ifa) \
do { \
if ((ifa)->ifa_refcnt <= 0) \
panic("%s:%d: %p ifa_refcnt <= 0", __FILE__, \
__LINE__, (ifa)); \
printf("IFAFREE: %s:%d %p -> %d\n", __FILE__, __LINE__, \
(ifa), --(ifa)->ifa_refcnt); \
if ((ifa)->ifa_refcnt == 0) \
ifafree(ifa); \
} while (0)
#else
#define IFAREF(ifa) (ifa)->ifa_refcnt++
#ifdef DIAGNOSTIC
#define IFAFREE(ifa) \
do { \
if ((ifa)->ifa_refcnt <= 0) \
panic("%s:%d: %p ifa_refcnt <= 0", __FILE__, \
__LINE__, (ifa)); \
if (--(ifa)->ifa_refcnt == 0) \
ifafree(ifa); \
} while (0)
#else
#define IFAFREE(ifa) \
do { \
if (--(ifa)->ifa_refcnt == 0) \
ifafree(ifa); \
} while (0)
#endif /* DIAGNOSTIC */
#endif /* IFAREF_DEBUG */
struct ifnet_head ifnet;
struct ifnet **ifindex2ifnet;
@ -452,9 +523,12 @@ struct ifnet loif[];
int if_index;
void ether_ifattach __P((struct ifnet *, const u_int8_t *));
void ether_ifdetach __P((struct ifnet *));
char *ether_sprintf __P((const u_char *));
void if_attach __P((struct ifnet *));
void if_deactivate __P((struct ifnet *));
void if_detach __P((struct ifnet *));
void if_down __P((struct ifnet *));
void if_qflush __P((struct ifqueue *));
void if_slowtimo __P((void *));
@ -482,6 +556,19 @@ void loopattach __P((int));
int looutput __P((struct ifnet *,
struct mbuf *, struct sockaddr *, struct rtentry *));
void lortrequest __P((int, struct rtentry *, struct sockaddr *));
/*
* These are exported because they're an easy way to tell if
* an interface is going away without having to burn a flag.
*/
int if_nulloutput __P((struct ifnet *, struct mbuf *,
struct sockaddr *, struct rtentry *));
void if_nullinput __P((struct ifnet *, struct mbuf *));
void if_nullstart __P((struct ifnet *));
int if_nullioctl __P((struct ifnet *, u_long, caddr_t));
int if_nullreset __P((struct ifnet *));
void if_nullwatchdog __P((struct ifnet *));
void if_nulldrain __P((struct ifnet *));
#else
struct if_nameindex {
unsigned int if_index; /* 1, 2, ... */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ethersubr.c,v 1.51 1999/12/13 15:17:19 itojun Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.52 2000/02/01 22:52:05 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -783,6 +783,14 @@ ether_ifattach(ifp, lla)
#endif
}
void
ether_ifdetach(ifp)
struct ifnet *ifp;
{
/* Nothing. */
}
#ifdef INET
u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };

View File

@ -1,4 +1,4 @@
/* $NetBSD: route.c,v 1.29 1999/10/09 18:55:30 sommerfeld Exp $ */
/* $NetBSD: route.c,v 1.30 2000/02/01 22:52:05 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -238,12 +238,15 @@ void
ifafree(ifa)
register struct ifaddr *ifa;
{
#ifdef DIAGNOSTIC
if (ifa == NULL)
panic("ifafree");
if (ifa->ifa_refcnt == 0)
free(ifa, M_IFADDR);
else
ifa->ifa_refcnt--;
panic("ifafree: null ifa");
if (ifa->ifa_refcnt != 0)
panic("ifafree: ifa_refcnt != 0 (%d)", ifa->ifa_refcnt);
#endif
printf("ifafree: freeing ifaddr %p\n", ifa);
free(ifa, M_IFADDR);
}
/*
@ -486,7 +489,7 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
pool_put(&rtentry_pool, rt);
senderr(EEXIST);
}
ifa->ifa_refcnt++;
IFAREF(ifa);
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
if (req == RTM_RESOLVE) {
@ -627,7 +630,7 @@ rtinit(ifa, cmd, flags)
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu; /*XXX*/
ifa->ifa_refcnt++;
IFAREF(ifa);
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(RTM_ADD, rt, SA(0));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtsock.c,v 1.32 1999/11/19 10:41:42 bouyer Exp $ */
/* $NetBSD: rtsock.c,v 1.33 2000/02/01 22:52:05 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -466,32 +466,31 @@ rt_setif(rt, Ifpaddr, Ifaaddr, Gate)
(ifp = ifa->ifa_ifp) && (Ifaaddr || Gate))
ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate,
ifp);
else if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) {
else if (Ifpaddr && (ifp = if_withname(Ifpaddr))) {
ifa = Gate ? ifaof_ifpforaddr(Gate, ifp) :
TAILQ_FIRST(&ifp->if_addrlist);
}
else if ((Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) ||
} else if ((Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) ||
(Gate && (ifa = ifa_ifwithroute(rt->rt_flags,
rt_key(rt), Gate))))
ifp = ifa->ifa_ifp;
if (ifa) {
register struct ifaddr *oifa = rt->rt_ifa;
if (oifa != ifa) {
if (oifa && oifa->ifa_rtrequest)
oifa->ifa_rtrequest(RTM_DELETE,
rt, Gate);
IFAFREE(rt->rt_ifa);
rt->rt_ifa = ifa;
ifa->ifa_refcnt++;
rt->rt_ifp = ifp;
rt->rt_rmx.rmx_mtu = ifp->if_mtu;
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
} else
if (oifa == ifa)
goto call_ifareq;
if (oifa && oifa->ifa_rtrequest)
oifa->ifa_rtrequest(RTM_DELETE, rt, Gate);
IFAFREE(rt->rt_ifa);
rt->rt_ifa = ifa;
IFAREF(rt->rt_ifa);
rt->rt_ifp = ifp;
rt->rt_rmx.rmx_mtu = ifp->if_mtu;
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
return;
}
call_ifareq:
call_ifareq:
/* XXX: to reset gateway to correct value, at RTM_CHANGE */
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);

View File

@ -1,4 +1,4 @@
/* $NetBSD: at_control.c,v 1.1 1997/04/02 21:31:04 christos Exp $ */
/* $NetBSD: at_control.c,v 1.2 2000/02/01 22:52:06 thorpej Exp $ */
/*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
@ -190,6 +190,7 @@ at_control(cmd, data, ifp, p)
} else {
TAILQ_INSERT_TAIL(&at_ifaddr, aa, aa_list);
}
IFAREF(&aa->aa_ifa);
/*
* Find the end of the interface's addresses
@ -197,6 +198,7 @@ at_control(cmd, data, ifp, p)
*/
TAILQ_INSERT_TAIL(&ifp->if_addrlist,
(struct ifaddr *) aa, ifa_list);
IFAREF(&aa->aa_ifa);
/*
* As the at_ifaddr contains the actual sockaddrs,
@ -295,17 +297,7 @@ at_control(cmd, data, ifp, p)
(struct sockaddr_at *) &ifr->ifr_addr));
case SIOCDIFADDR:
/*
* scrub all routes.. didn't we just DO this? XXX yes, del it
*/
at_scrub(ifp, aa);
/*
* remove the ifaddr from the interface
*/
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *) aa, ifa_list);
TAILQ_REMOVE(&at_ifaddr, aa, aa_list);
IFAFREE((struct ifaddr *) aa);
at_purgeaddr((struct ifaddr *) aa, ifp);
break;
default:
@ -316,6 +308,28 @@ at_control(cmd, data, ifp, p)
return (0);
}
void
at_purgeaddr(ifa, ifp)
struct ifaddr *ifa;
struct ifnet *ifp;
{
struct at_ifaddr *aa = (void *) ifa;
/*
* scrub all routes.. didn't we just DO this? XXX yes, del it
* XXX above XXX not necessarily true anymore
*/
at_scrub(ifp, aa);
/*
* remove the ifaddr from the interface
*/
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *) aa, ifa_list);
IFAFREE(&aa->aa_ifa);
TAILQ_REMOVE(&at_ifaddr, aa, aa_list);
IFAFREE(&aa->aa_ifa);
}
/*
* Given an interface and an at_ifaddr (supposedly on that interface) remove
* any routes that depend on this. Why ifp is needed I'm not sure, as

View File

@ -1,4 +1,4 @@
/* $NetBSD: at_extern.h,v 1.3 1997/04/03 18:38:23 christos Exp $ */
/* $NetBSD: at_extern.h,v 1.4 2000/02/01 22:52:06 thorpej Exp $ */
/*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
@ -33,6 +33,7 @@ struct ifnet;
struct mbuf;
struct sockaddr_at;
struct proc;
struct ifaddr;
struct at_ifaddr;
struct route;
struct socket;
@ -45,6 +46,7 @@ void aarpinput __P((struct ifnet *, struct mbuf *));
int at_broadcast __P((struct sockaddr_at *));
void aarp_clean __P((void));
int at_control __P((u_long, caddr_t, struct ifnet *, struct proc *));
void at_purgeaddr __P((struct ifaddr *, struct ifnet *));
u_int16_t
at_cksum __P((struct mbuf *, int));
int ddp_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *,

View File

@ -1,4 +1,4 @@
/* $NetBSD: ddp_usrreq.c,v 1.2 1997/04/29 13:44:47 christos Exp $ */
/* $NetBSD: ddp_usrreq.c,v 1.3 2000/02/01 22:52:06 thorpej Exp $ */
/*
* Copyright (c) 1990,1991 Regents of The University of Michigan.
@ -79,6 +79,10 @@ ddp_usrreq(so, req, m, addr, rights, p)
return (at_control((long) m, (caddr_t) addr,
(struct ifnet *) rights, (struct proc *) p));
}
if (req == PRU_PURGEADDR) {
at_purgeaddr((struct ifaddr *) addr, (struct ifnet *) rights);
return (0);
}
if (rights && rights->m_len) {
error = EINVAL;
goto release;

View File

@ -1,4 +1,4 @@
/* $NetBSD: hd_subr.c,v 1.10 1998/09/13 16:21:17 christos Exp $ */
/* $NetBSD: hd_subr.c,v 1.11 2000/02/01 22:52:07 thorpej Exp $ */
/*
* Copyright (c) 1984 University of British Columbia.
@ -106,6 +106,7 @@ hd_ctlinput(prc, addr, ext)
return (void *) (ENOBUFS);
}
hdp->hd_ifp = ifp;
IFAREF(ifa);
hdp->hd_ifa = ifa;
hdp->hd_xcp = xcp;
hdp->hd_state = INIT;

View File

@ -1,4 +1,4 @@
/* $NetBSD: pk_input.c,v 1.13 1998/09/13 16:21:19 christos Exp $ */
/* $NetBSD: pk_input.c,v 1.14 2000/02/01 22:52:07 thorpej Exp $ */
/*
* Copyright (c) 1984 University of British Columbia.
@ -128,6 +128,7 @@ pk_newlink(ia, llnext)
pkp->pk_lloutput = pp->pr_output;
pkp->pk_llctlinput = pp->pr_ctlinput;
pkp->pk_xcp = xcp;
IFAREF(&ia->ia_ifa);
pkp->pk_ia = ia;
pkp->pk_state = DTE_WAITING;
pkp->pk_llnext = llnext;
@ -204,6 +205,9 @@ pk_dellink(pkp)
(struct sockaddr *)pkp->pk_xcp,
&ctlinfo);
}
if (pkp->pk_ia != NULL)
IFAFREE(&pkp->pk_ia->ia_ifa);
free((caddr_t) pkp->pk_chan, M_IFADDR);
free((caddr_t) pkp, M_PCB);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: pk_usrreq.c,v 1.16 1998/09/13 16:21:19 christos Exp $ */
/* $NetBSD: pk_usrreq.c,v 1.17 2000/02/01 22:52:07 thorpej Exp $ */
/*
* Copyright (c) 1984 University of British Columbia.
@ -387,6 +387,7 @@ pk_control(so, cmd, data, ifp, p)
TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
ifa_list);
ifa = &ia->ia_ifa;
IFAREF(ifa);
ifa->ifa_netmask = (struct sockaddr *) & pk_sockmask;
ifa->ifa_addr = (struct sockaddr *) & ia->ia_xc.xc_addr;
ifa->ifa_dstaddr = (struct sockaddr *) & ia->ia_dstaddr; /* XXX */

View File

@ -1,4 +1,4 @@
/* $NetBSD: in.c,v 1.49 1999/12/12 15:57:07 itojun Exp $ */
/* $NetBSD: in.c,v 1.50 2000/02/01 22:52:07 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -383,8 +383,10 @@ in_control(so, cmd, data, ifp, p)
return (ENOBUFS);
bzero((caddr_t)ia, sizeof *ia);
TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
IFAREF(&ia->ia_ifa);
TAILQ_INSERT_TAIL(&ifp->if_addrlist, &ia->ia_ifa,
ifa_list);
IFAREF(&ia->ia_ifa);
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);
@ -512,12 +514,7 @@ in_control(so, cmd, data, ifp, p)
return 0;
case SIOCDIFADDR:
in_ifscrub(ifp, ia);
LIST_REMOVE(ia, ia_hash);
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
IFAFREE((&ia->ia_ifa));
in_setmaxmtu();
in_purgeaddr(&ia->ia_ifa, ifp);
break;
#ifdef MROUTING
@ -536,6 +533,22 @@ in_control(so, cmd, data, ifp, p)
return (0);
}
void
in_purgeaddr(ifa, ifp)
struct ifaddr *ifa;
struct ifnet *ifp;
{
struct in_ifaddr *ia = (void *) ifa;
in_ifscrub(ifp, ia);
LIST_REMOVE(ia, ia_hash);
TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
IFAFREE(&ia->ia_ifa);
TAILQ_REMOVE(&in_ifaddr, ia, ia_list);
IFAFREE(&ia->ia_ifa);
in_setmaxmtu();
}
/*
* SIOC[GAD]LIFADDR.
* SIOCGLIFADDR: get first address. (???)

View File

@ -1,4 +1,4 @@
/* $NetBSD: in_var.h,v 1.35 1999/07/01 08:12:50 itojun Exp $ */
/* $NetBSD: in_var.h,v 1.36 2000/02/01 22:52:08 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -301,6 +301,8 @@ struct in_multistep {
IN_NEXT_MULTI((step), (inm)); \
}
struct ifaddr;
int in_ifinit __P((struct ifnet *,
struct in_ifaddr *, struct sockaddr_in *, int));
struct in_multi *in_addmulti __P((struct in_addr *, struct ifnet *));
@ -310,6 +312,7 @@ void in_setmaxmtu __P((void));
const char *in_fmtaddr __P((struct in_addr));
int in_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
struct proc *));
void in_purgeaddr __P((struct ifaddr *, struct ifnet *));
void ip_input __P((struct mbuf *));
int ipflow_fastforward __P((struct mbuf *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: raw_ip.c,v 1.48 2000/01/31 14:18:55 itojun Exp $ */
/* $NetBSD: raw_ip.c,v 1.49 2000/02/01 22:52:08 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -431,6 +431,11 @@ rip_usrreq(so, req, m, nam, control, p)
return (in_control(so, (long)m, (caddr_t)nam,
(struct ifnet *)control, p));
if (req == PRU_PURGEADDR) {
in_purgeaddr((struct ifaddr *)nam, (struct ifnet *)control);
return (0);
}
s = splsoftnet();
inp = sotoinpcb(so);
#ifdef DIAGNOSTIC

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_usrreq.c,v 1.44 2000/01/31 14:18:58 itojun Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.45 2000/02/01 22:52:10 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -200,6 +200,11 @@ tcp_usrreq(so, req, m, nam, control, p)
}
}
if (req == PRU_PURGEADDR) {
in_purgeaddr((struct ifaddr *)nam, (struct ifnet *)control);
return (0);
}
s = splsoftnet();
switch (family) {
case PF_INET:

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp_usrreq.c,v 1.58 2000/01/31 14:18:58 itojun Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.59 2000/02/01 22:52:10 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -1309,6 +1309,11 @@ udp_usrreq(so, req, m, nam, control, p)
return (in_control(so, (long)m, (caddr_t)nam,
(struct ifnet *)control, p));
if (req == PRU_PURGEADDR) {
in_purgeaddr((struct ifaddr *)nam, (struct ifnet *)control);
return (0);
}
s = splsoftnet();
inp = sotoinpcb(so);
#ifdef DIAGNOSTIC

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6.c,v 1.9 2000/01/06 15:46:09 itojun Exp $ */
/* $NetBSD: in6.c,v 1.10 2000/02/01 22:52:10 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -210,8 +210,8 @@ in6_ifloop_request(int cmd, struct ifaddr *ifa)
* loopback address.
*/
if (cmd == RTM_ADD && nrt && ifa != nrt->rt_ifa) {
nrt->rt_ifa->ifa_refcnt--;
ifa->ifa_refcnt++;
IFAFREE(nrt->rt_ifa);
IFAREF(ifa);
nrt->rt_ifa = ifa;
}
if (nrt)
@ -559,8 +559,12 @@ in6_control(so, cmd, data, ifp, p)
oia->ia_next = ia;
} else
in6_ifaddr = ia;
IFAREF(&ia->ia_ifa);
TAILQ_INSERT_TAIL(&ifp->if_addrlist,
(struct ifaddr *)ia, ifa_list);
IFAREF(&ia->ia_ifa);
if ((ifp->if_flags & IFF_LOOPBACK) == 0)
in6_interfaces++; /*XXX*/
}
@ -862,58 +866,7 @@ in6_control(so, cmd, data, ifp, p)
return(error);
case SIOCDIFADDR_IN6:
in6_ifscrub(ifp, ia);
if (ifp->if_flags & IFF_MULTICAST) {
/*
* delete solicited multicast addr for deleting host id
*/
struct in6_multi *in6m;
struct in6_addr llsol;
bzero(&llsol, sizeof(struct in6_addr));
llsol.s6_addr16[0] = htons(0xff02);
llsol.s6_addr16[1] = htons(ifp->if_index);
llsol.s6_addr32[1] = 0;
llsol.s6_addr32[2] = htonl(1);
llsol.s6_addr32[3] =
ia->ia_addr.sin6_addr.s6_addr32[3];
llsol.s6_addr8[12] = 0xff;
IN6_LOOKUP_MULTI(llsol, ifp, in6m);
if (in6m)
in6_delmulti(in6m);
}
/* Leave dstaddr's solicited multicast if necessary. */
if (nd6_proxyall)
in6_ifremproxy(ia);
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
oia = ia;
if (oia == (ia = in6_ifaddr))
in6_ifaddr = ia->ia_next;
else {
while (ia->ia_next && (ia->ia_next != oia))
ia = ia->ia_next;
if (ia->ia_next)
ia->ia_next = oia->ia_next;
else
printf("Didn't unlink in6_ifaddr from list\n");
}
{
int iilen;
iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) -
in6_mask2len(&oia->ia_prefixmask.sin6_addr);
in6_prefix_remove_ifid(iilen, oia);
}
if (oia->ia6_multiaddrs.lh_first == NULL) {
IFAFREE(&oia->ia_ifa);
break;
}
else
in6_savemkludge(oia);
IFAFREE((&oia->ia_ifa));
in6_purgeaddr(&ia->ia_ifa, ifp);
break;
default:
@ -924,6 +877,77 @@ in6_control(so, cmd, data, ifp, p)
return(0);
}
void
in6_purgeaddr(ifa, ifp)
struct ifaddr *ifa;
struct ifnet *ifp;
{
struct in6_ifaddr *oia, *ia = (void *) ifa;
in6_ifscrub(ifp, ia);
if (ifp->if_flags & IFF_MULTICAST) {
/*
* delete solicited multicast addr for deleting host id
*/
struct in6_multi *in6m;
struct in6_addr llsol;
bzero(&llsol, sizeof(struct in6_addr));
llsol.s6_addr16[0] = htons(0xff02);
llsol.s6_addr16[1] = htons(ifp->if_index);
llsol.s6_addr32[1] = 0;
llsol.s6_addr32[2] = htonl(1);
llsol.s6_addr32[3] =
ia->ia_addr.sin6_addr.s6_addr32[3];
llsol.s6_addr8[12] = 0xff;
IN6_LOOKUP_MULTI(llsol, ifp, in6m);
if (in6m)
in6_delmulti(in6m);
}
/* Leave dstaddr's solicited multicast if necessary. */
if (nd6_proxyall)
in6_ifremproxy(ia);
TAILQ_REMOVE(&ifp->if_addrlist, &ia->ia_ifa, ifa_list);
IFAFREE(&ia->ia_ifa);
oia = ia;
if (oia == (ia = in6_ifaddr))
in6_ifaddr = ia->ia_next;
else {
while (ia->ia_next && (ia->ia_next != oia))
ia = ia->ia_next;
if (ia->ia_next)
ia->ia_next = oia->ia_next;
else
printf("Didn't unlink in6_ifaddr from list\n");
}
{
int iilen;
iilen = (sizeof(oia->ia_prefixmask.sin6_addr) << 3) -
in6_mask2len(&oia->ia_prefixmask.sin6_addr);
in6_prefix_remove_ifid(iilen, oia);
}
if (oia->ia6_multiaddrs.lh_first != NULL) {
/*
* XXX thorpej@netbsd.org -- if the interface is going
* XXX away, don't save the multicast entries, delete them!
*/
if (oia->ia_ifa.ifa_ifp->if_output == if_nulloutput) {
struct in6_multi *in6m;
while ((in6m =
LIST_FIRST(&oia->ia6_multiaddrs)) != NULL)
in6_delmulti(in6m);
} else
in6_savemkludge(oia);
}
IFAFREE(&oia->ia_ifa);
}
/*
* SIOC[GAD]LIFADDR.
* SIOCGLIFADDR: get first address. (???)
@ -1279,7 +1303,7 @@ in6_savemkludge(oia)
for (in6m = oia->ia6_multiaddrs.lh_first; in6m; in6m = next){
next = in6m->in6m_entry.le_next;
IFAFREE(&in6m->in6m_ia->ia_ifa);
ia->ia_ifa.ifa_refcnt++;
IFAREF(&ia->ia_ifa);
in6m->in6m_ia = ia;
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
}
@ -1381,7 +1405,7 @@ in6_addmulti(maddr6, ifp, errorp)
return(NULL);
}
in6m->in6m_ia = ia;
ia->ia_ifa.ifa_refcnt++; /* gain a reference */
IFAREF(&ia->ia_ifa); /* gain a reference */
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry);
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_ifattach.c,v 1.14 2000/01/06 15:46:09 itojun Exp $ */
/* $NetBSD: in6_ifattach.c,v 1.15 2000/02/01 22:52:11 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -339,6 +339,8 @@ in6_ifattach(ifp, type, laddr, noloop)
ia->ia_ifa.ifa_netmask = (struct sockaddr *)&ia->ia_prefixmask;
ia->ia_ifp = ifp;
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
IFAREF((struct ifaddr *)ia);
/*
* Also link into the IPv6 address chain beginning with in6_ifaddr.
* kazu opposed it, but itojun & jinmei wanted.
@ -349,6 +351,7 @@ in6_ifattach(ifp, type, laddr, noloop)
oia->ia_next = ia;
} else
in6_ifaddr = ia;
IFAREF((struct ifaddr *)ia);
ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
ia->ia_prefixmask.sin6_family = AF_INET6;
@ -435,11 +438,12 @@ in6_ifattach(ifp, type, laddr, noloop)
/* undo changes */
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
IFAFREE((struct ifaddr *)ia);
if (oia)
oia->ia_next = ia->ia_next;
else
in6_ifaddr = ia->ia_next;
free(ia, M_IFADDR);
IFAFREE((struct ifaddr *)ia);
return;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_var.h,v 1.6 2000/01/06 15:46:09 itojun Exp $ */
/* $NetBSD: in6_var.h,v 1.7 2000/02/01 22:52:11 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -550,6 +550,7 @@ extern int in6_mask2len __P((struct in6_addr *));
extern void in6_len2mask __P((struct in6_addr *, int));
int in6_control __P((struct socket *,
u_long, caddr_t, struct ifnet *, struct proc *));
void in6_purgeaddr __P((struct ifaddr *, struct ifnet *));
void in6_savemkludge __P((struct in6_ifaddr *));
void in6_setmaxmtu __P((void));
void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6.c,v 1.13 2000/01/06 15:46:10 itojun Exp $ */
/* $NetBSD: nd6.c,v 1.14 2000/02/01 22:52:11 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -1011,8 +1011,8 @@ nd6_rtrequest(req, rt, sa)
* of the loopback address.
*/
if (ifa != rt->rt_ifa) {
rt->rt_ifa->ifa_refcnt--;
ifa->ifa_refcnt++;
IFAFREE(rt->rt_ifa);
IFAREF(ifa);
rt->rt_ifa = ifa;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6_nbr.c,v 1.12 2000/01/28 07:21:29 itojun Exp $ */
/* $NetBSD: nd6_nbr.c,v 1.13 2000/02/01 22:52:11 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -927,7 +927,7 @@ nd6_dad_start(ifa, tick)
* (re)initialization.
*/
dp->dad_ifa = ifa;
ifa->ifa_refcnt++; /*just for safety*/
IFAREF(ifa); /* just for safety */
dp->dad_count = ip6_dad_count;
dp->dad_ns_icount = dp->dad_na_icount = 0;
dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
@ -991,7 +991,7 @@ nd6_dad_timer(ifa)
TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
free(dp, M_IP6NDP);
dp = NULL;
ifa->ifa_refcnt--;
IFAFREE(ifa);
goto done;
}
@ -1068,7 +1068,7 @@ nd6_dad_timer(ifa)
TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
free(dp, M_IP6NDP);
dp = NULL;
ifa->ifa_refcnt--;
IFAFREE(ifa);
}
}
@ -1107,7 +1107,7 @@ nd6_dad_duplicated(ifa)
TAILQ_REMOVE(&dadq, (struct dadq *)dp, dad_list);
free(dp, M_IP6NDP);
dp = NULL;
ifa->ifa_refcnt--;
IFAFREE(ifa);
}
static void

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6_rtr.c,v 1.8 2000/01/06 15:46:11 itojun Exp $ */
/* $NetBSD: nd6_rtr.c,v 1.9 2000/02/01 22:52:12 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -430,7 +430,7 @@ defrouter_addreq(new)
Free(rt);
goto bad;
}
ifa->ifa_refcnt++;
IFAREF(ifa);
rt->rt_ifa = ifa;
rt->rt_ifp = ifp;
rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu;
@ -1250,11 +1250,13 @@ in6_ifadd(ifp, in6, addr, prefixlen)
oia->ia_next = ia;
} else
in6_ifaddr = ia;
IFAREF((struct ifaddr *)ia);
/* link to if_addrlist */
if (ifp->if_addrlist.tqh_first != NULL) {
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
ifa_list);
IFAREF((struct ifaddr *)ia);
}
#if 0
else {
@ -1386,6 +1388,7 @@ in6_ifdel(ifp, in6)
}
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
IFAFREE((struct ifaddr *)ia);
/* lladdr is never deleted */
oia = ia;

View File

@ -1,4 +1,4 @@
/* $NetBSD: raw_ip6.c,v 1.16 2000/01/31 14:19:06 itojun Exp $ */
/* $NetBSD: raw_ip6.c,v 1.17 2000/02/01 22:52:12 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -494,6 +494,11 @@ rip6_usrreq(so, req, m, nam, control, p)
return (in6_control(so, (u_long)m, (caddr_t)nam,
(struct ifnet *)control, p));
if (req == PRU_PURGEADDR) {
in6_purgeaddr((struct ifaddr *)nam, (struct ifnet *)control);
return (0);
}
switch (req) {
case PRU_ATTACH:
if (in6p)

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp6_usrreq.c,v 1.19 2000/01/31 14:19:07 itojun Exp $ */
/* $NetBSD: udp6_usrreq.c,v 1.20 2000/02/01 22:52:12 thorpej Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -798,6 +798,11 @@ udp6_usrreq(so, req, m, addr6, control, p)
return(in6_control(so, (u_long)m, (caddr_t)addr6,
(struct ifnet *)control, p));
if (req == PRU_PURGEADDR) {
in6_purgeaddr((struct ifaddr *)addr6, (struct ifnet *)control);
return (0);
}
if (in6p == NULL && req != PRU_ATTACH) {
error = EINVAL;
goto release;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cltp_usrreq.c,v 1.14 1997/06/24 02:26:09 thorpej Exp $ */
/* $NetBSD: cltp_usrreq.c,v 1.15 2000/02/01 22:52:12 thorpej Exp $ */
/*
* Copyright (c) 1989, 1993
@ -307,6 +307,11 @@ cltp_usrreq(so, req, m, nam, control, p)
return (iso_control(so, (long)m, (caddr_t)nam,
(struct ifnet *)control, p));
if (req == PRU_PURGEADDR) {
iso_purgeaddr((struct ifaddr *)nam, (struct ifnet *)control);
return (0);
}
s = splsoftnet();
isop = sotoisopcb(so);
#ifdef DIAGNOSTIC

View File

@ -1,4 +1,4 @@
/* $NetBSD: iso.c,v 1.25 1999/07/12 18:15:09 thorpej Exp $ */
/* $NetBSD: iso.c,v 1.26 2000/02/01 22:52:12 thorpej Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -494,8 +494,10 @@ iso_control(so, cmd, data, ifp, p)
return (ENOBUFS);
bzero((caddr_t)ia, sizeof(*ia));
TAILQ_INSERT_TAIL(&iso_ifaddr, ia, ia_list);
IFAREF((struct ifaddr *)ia);
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
ifa_list);
IFAREF((struct ifaddr *)ia);
ia->ia_ifa.ifa_addr = sisotosa(&ia->ia_addr);
ia->ia_ifa.ifa_dstaddr = sisotosa(&ia->ia_dstaddr);
ia->ia_ifa.ifa_netmask = sisotosa(&ia->ia_sockmask);
@ -558,10 +560,7 @@ iso_control(so, cmd, data, ifp, p)
return (error);
case SIOCDIFADDR_ISO:
iso_ifscrub(ifp, ia);
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
TAILQ_REMOVE(&iso_ifaddr, ia, ia_list);
IFAFREE((&ia->ia_ifa));
iso_purgeaddr(&ia->ia_ifa, ifp);
break;
#define cmdbyte(x) (((x) >> 8) & 0xff)
@ -575,6 +574,20 @@ iso_control(so, cmd, data, ifp, p)
return (0);
}
void
iso_purgeaddr(ifa, ifp)
struct ifaddr *ifa;
struct ifnet *ifp;
{
struct iso_ifaddr *ia = (void *) ifa;
iso_ifscrub(ifp, ia);
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
IFAFREE(&ia->ia_ifa);
TAILQ_REMOVE(&iso_ifaddr, ia, ia_list);
IFAFREE((&ia->ia_ifa));
}
/*
* Delete any existing route for an interface.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: iso_var.h,v 1.11 1999/04/01 06:51:48 chopps Exp $ */
/* $NetBSD: iso_var.h,v 1.12 2000/02/01 22:52:13 thorpej Exp $ */
/*-
* Copyright (c) 1988, 1991, 1993
@ -143,6 +143,7 @@ int iso_hash __P((struct sockaddr_iso *, struct afhash *));
int iso_netof __P((struct iso_addr *, caddr_t));
int iso_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
struct proc *));
void iso_purgeaddr __P((struct ifaddr *, struct ifnet *));
void iso_ifscrub __P((struct ifnet *, struct iso_ifaddr *));
int iso_ifinit __P((struct ifnet *, struct iso_ifaddr *, struct sockaddr_iso *,
int ));

View File

@ -1,4 +1,4 @@
/* $NetBSD: idp_usrreq.c,v 1.15 1998/07/05 06:49:17 jonathan Exp $ */
/* $NetBSD: idp_usrreq.c,v 1.16 2000/02/01 22:52:13 thorpej Exp $ */
/*
* Copyright (c) 1984, 1985, 1986, 1987, 1993
@ -371,6 +371,11 @@ idp_usrreq(so, req, m, nam, control, p)
return (ns_control(so, (u_long)m, (caddr_t)nam,
(struct ifnet *)control, p));
if (req == PRU_PURGEADDR) {
ns_purgeaddr((struct ifaddr *)nam, (struct ifnet *)control);
return (0);
}
s = splsoftnet();
nsp = sotonspcb(so);
if (nsp == 0 && req != PRU_ATTACH) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: ns.c,v 1.17 1999/10/25 19:18:11 drochner Exp $ */
/* $NetBSD: ns.c,v 1.18 2000/02/01 22:52:13 thorpej Exp $ */
/*
* Copyright (c) 1984, 1985, 1986, 1987, 1993
@ -109,8 +109,10 @@ ns_control(so, cmd, data, ifp, p)
return (ENOBUFS);
bzero((caddr_t)ia, sizeof(*ia));
TAILQ_INSERT_TAIL(&ns_ifaddr, ia, ia_list);
IFAREF((struct ifaddr *)ia);
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ia,
ifa_list);
IFAREF((struct ifaddr *)ia);
ia->ia_ifa.ifa_addr = snstosa(&ia->ia_addr);
ia->ia_ifa.ifa_netmask = snstosa(&ns_netmask);
ia->ia_ifa.ifa_dstaddr = snstosa(&ia->ia_dstaddr);
@ -193,16 +195,7 @@ ns_control(so, cmd, data, ifp, p)
return (error);
case SIOCDIFADDR:
ns_ifscrub(ifp, ia);
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
TAILQ_REMOVE(&ns_ifaddr, ia, ia_list);
IFAFREE((&ia->ia_ifa));
if (0 == --ns_interfaces) {
/*
* We reset to virginity and start all over again
*/
ns_thishost = ns_zerohost;
}
ns_purgeaddr(&ia->ia_ifa, ifp);
break;
default:
@ -213,6 +206,26 @@ ns_control(so, cmd, data, ifp, p)
return (0);
}
void
ns_purgeaddr(ifa, ifp)
struct ifaddr *ifa;
struct ifnet *ifp;
{
struct ns_ifaddr *ia = (void *) ifa;
ns_ifscrub(ifp, ia);
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
IFAFREE(&ia->ia_ifa);
TAILQ_REMOVE(&ns_ifaddr, ia, ia_list);
IFAFREE((&ia->ia_ifa));
if (0 == --ns_interfaces) {
/*
* We reset to virginity and start all over again
*/
ns_thishost = ns_zerohost;
}
}
/*
* Delete any previous route for an old address.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: spp_usrreq.c,v 1.21 1999/09/10 03:24:15 simonb Exp $ */
/* $NetBSD: spp_usrreq.c,v 1.22 2000/02/01 22:52:13 thorpej Exp $ */
/*
* Copyright (c) 1984, 1985, 1986, 1987, 1993
@ -1339,6 +1339,11 @@ spp_usrreq(so, req, m, nam, control, p)
return (ns_control(so, (u_long)m, (caddr_t)nam,
(struct ifnet *)control, p));
if (req == PRU_PURGEADDR) {
ns_purgeaddr((struct ifaddr *)nam, (struct ifnet *)control);
return (0);
}
s = splsoftnet();
nsp = sotonspcb(so);
if (nsp == 0 && req != PRU_ATTACH) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: protosw.h,v 1.18 1999/07/01 05:56:53 darrenr Exp $ */
/* $NetBSD: protosw.h,v 1.19 2000/02/01 22:52:14 thorpej Exp $ */
/*-
* Copyright (c) 1982, 1986, 1993
@ -153,8 +153,9 @@ struct protosw {
#define PRU_SLOWTIMO 19 /* 500ms timeout */
#define PRU_PROTORCV 20 /* receive from below */
#define PRU_PROTOSEND 21 /* send to below */
#define PRU_PURGEADDR 22 /* purge specified ifaddr */
#define PRU_NREQ 22
#define PRU_NREQ 23
#ifdef PRUREQUESTS
char *prurequests[] = {
@ -163,7 +164,7 @@ char *prurequests[] = {
"RCVD", "SEND", "ABORT", "CONTROL",
"SENSE", "RCVOOB", "SENDOOB", "SOCKADDR",
"PEERADDR", "CONNECT2", "FASTTIMO", "SLOWTIMO",
"PROTORCV", "PROTOSEND",
"PROTORCV", "PROTOSEND", "PURGEADDR",
};
#endif