attach nd_ifinfo structure into if_afdata.

split IPv6 link MTU (advertised by RA) from real link MTU.
sync with kame
This commit is contained in:
itojun 2002-05-29 07:53:39 +00:00
parent 9ea1dc0d36
commit 5c1df51d53
14 changed files with 254 additions and 230 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_fil.c,v 1.79 2002/05/02 17:13:28 martti Exp $ */
/* $NetBSD: ip_fil.c,v 1.80 2002/05/29 07:53:39 itojun Exp $ */
/*
* Copyright (C) 1993-2001 by Darren Reed.
@ -123,7 +123,7 @@ extern int ip_optcopy __P((struct ip *, struct ip *));
#if !defined(lint)
#if defined(__NetBSD__)
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_fil.c,v 1.79 2002/05/02 17:13:28 martti Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_fil.c,v 1.80 2002/05/29 07:53:39 itojun Exp $");
#else
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
static const char rcsid[] = "@(#)Id: ip_fil.c,v 2.42.2.55 2002/03/26 15:54:39 darrenr Exp";
@ -1928,7 +1928,7 @@ frdest_t *fdp;
dst6 = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
ro->ro_rt->rt_use++;
if (m0->m_pkthdr.len <= nd_ifinfo[ifp->if_index].linkmtu)
if (m0->m_pkthdr.len <= IN6_LINKMTU(ifp))
error = nd6_output(ifp, fin->fin_ifp, m0, dst6,
ro->ro_rt);
else

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_output.c,v 1.80 2002/05/26 16:05:43 itojun Exp $ */
/* $NetBSD: tcp_output.c,v 1.81 2002/05/29 07:53:39 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -142,7 +142,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.80 2002/05/26 16:05:43 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.81 2002/05/29 07:53:39 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -173,8 +173,10 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.80 2002/05/26 16:05:43 itojun Exp $
#include <netinet/in.h>
#endif
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
#include <netinet6/in6_var.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_pcb.h>
#include <netinet6/nd6.h>
#endif
#include <netinet/tcp.h>
@ -297,7 +299,7 @@ tcp_segsize(struct tcpcb *tp, int *txsegsizep, int *rxsegsizep)
* for IPv6, path MTU discovery is always turned on,
* or the node must use packet size <= 1280.
*/
size = tp->t_mtudisc ? ifp->if_mtu : IPV6_MMTU;
size = tp->t_mtudisc ? IN6_LINKMTU(ifp) : IPV6_MMTU;
size -= (iphlen + sizeof(struct tcphdr));
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_subr.c,v 1.129 2002/05/28 10:17:27 itojun Exp $ */
/* $NetBSD: tcp_subr.c,v 1.130 2002/05/29 07:53:39 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.129 2002/05/28 10:17:27 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.130 2002/05/29 07:53:39 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -146,6 +146,7 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.129 2002/05/28 10:17:27 itojun Exp $"
#include <netinet6/in6_var.h>
#include <netinet6/ip6protosw.h>
#include <netinet/icmp6.h>
#include <netinet6/nd6.h>
#endif
#include <netinet/tcp.h>
@ -1660,7 +1661,16 @@ tcp_mss_to_advertise(ifp, af)
*/
if (ifp != NULL)
mss = ifp->if_mtu;
switch (af) {
case AF_INET:
mss = ifp->if_mtu;
break;
#ifdef INET6
case AF_INET6:
mss = IN6_LINKMTU(ifp);
break;
#endif
}
if (tcp_mss_ifmtu == 0)
switch (af) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6.c,v 1.58 2002/05/29 02:58:29 itojun Exp $ */
/* $NetBSD: in6.c,v 1.59 2002/05/29 07:53:40 itojun Exp $ */
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
/*
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.58 2002/05/29 02:58:29 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.59 2002/05/29 07:53:40 itojun Exp $");
#include "opt_inet.h"
@ -366,6 +366,7 @@ in6_control(so, cmd, data, ifp, p)
if (!privileged)
return(EPERM);
/* fall through */
case OSIOCGIFINFO_IN6:
case SIOCGIFINFO_IN6:
case SIOCGDRLST_IN6:
case SIOCGPRLST_IN6:
@ -789,14 +790,6 @@ in6_control(so, cmd, data, ifp, p)
} else
ia->ia6_lifetime.ia6t_preferred = 0;
/*
* make sure to initialize ND6 information. this is to
* workaround issues with interfaces with IPv6 addresses,
* which have never brought # up. we are assuming that it is
* safe to nd6_ifattach multiple times.
*/
nd6_ifattach(ifp);
/*
* Perform DAD, if needed.
*/
@ -2232,11 +2225,14 @@ in6_setmaxmtu()
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
{
/* this function can be called during ifnet initialization */
if (!ifp->if_afdata[AF_INET6])
continue;
if ((ifp->if_flags & IFF_LOOPBACK) == 0 &&
nd_ifinfo[ifp->if_index].linkmtu > maxmtu)
maxmtu = nd_ifinfo[ifp->if_index].linkmtu;
IN6_LINKMTU(ifp) > maxmtu)
maxmtu = IN6_LINKMTU(ifp);
}
if (maxmtu) /* update only when maxmtu is positive */
if (maxmtu) /* update only when maxmtu is positive */
in6_maxmtu = maxmtu;
}
@ -2258,9 +2254,7 @@ in6_domifattach(ifp)
M_IFADDR, M_WAITOK);
bzero(ext->icmp6_ifstat, sizeof(*ext->icmp6_ifstat));
#if 0
ext->nd_ifinfo = nd6_ifattach(ifp);
#endif
return ext;
}
@ -2271,9 +2265,7 @@ in6_domifdetach(ifp, aux)
{
struct in6_ifextra *ext = (struct in6_ifextra *)aux;
#if 0
nd6_ifdetach(ext->nd_ifinfo);
#endif
free(ext->in6_ifstat, M_IFADDR);
free(ext->icmp6_ifstat, M_IFADDR);
free(ext, M_IFADDR);

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_ifattach.c,v 1.45 2002/05/29 02:58:30 itojun Exp $ */
/* $NetBSD: in6_ifattach.c,v 1.46 2002/05/29 07:53:40 itojun 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.45 2002/05/29 02:58:30 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: in6_ifattach.c,v 1.46 2002/05/29 07:53:40 itojun Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -579,6 +579,14 @@ in6_ifattach(ifp, altifp)
return;
}
/*
* if link mtu is too small, don't try to configure IPv6.
* remember there could be some link-layer that has special
* fragmentation logic.
*/
if (ifp->if_mtu < IPV6_MMTU)
return;
/* create a multicast kludge storage (if we have not had one) */
in6_createmkludge(ifp);
@ -594,7 +602,7 @@ in6_ifattach(ifp, altifp)
* linklocals for 6to4 interface, but there's no use and
* it is rather harmful to have one.
*/
goto statinit;
return;
#endif
default:
break;
@ -624,7 +632,7 @@ in6_ifattach(ifp, altifp)
if_name(ifp));
/* we can't initialize multicasts without link-local */
goto statinit;
return;
}
}
@ -733,15 +741,6 @@ in6_ifattach(ifp, altifp)
}
}
}
statinit:;
/* update dynamically. */
if (in6_maxmtu < ifp->if_mtu)
in6_maxmtu = ifp->if_mtu;
/* initialize NDP variables */
nd6_ifattach(ifp);
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_src.c,v 1.11 2002/05/29 01:43:25 itojun Exp $ */
/* $NetBSD: in6_src.c,v 1.12 2002/05/29 07:53:41 itojun Exp $ */
/* $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $ */
/*
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.11 2002/05/29 01:43:25 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: in6_src.c,v 1.12 2002/05/29 07:53:41 itojun Exp $");
#include "opt_inet.h"
@ -326,7 +326,7 @@ in6_selecthlim(in6p, ifp)
if (in6p && in6p->in6p_hops >= 0)
return(in6p->in6p_hops);
else if (ifp)
return(nd_ifinfo[ifp->if_index].chlim);
return(ND_IFINFO(ifp)->chlim);
else
return(ip6_defhlim);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6_var.h,v 1.26 2002/05/29 02:58:31 itojun Exp $ */
/* $NetBSD: in6_var.h,v 1.27 2002/05/29 07:53:41 itojun Exp $ */
/* $KAME: in6_var.h,v 1.53 2001/02/10 02:44:27 itojun Exp $ */
/*
@ -90,15 +90,11 @@ struct in6_addrlifetime {
u_int32_t ia6t_pltime; /* prefix lifetime */
};
#if 0
struct nd_ifinfo;
#endif
struct in6_ifextra {
struct in6_ifstat *in6_ifstat;
struct icmp6_ifstat *icmp6_ifstat;
#if 0
struct nd_ifinfo *nd_ifinfo;
#endif
};
struct in6_ifaddr {
@ -392,7 +388,10 @@ struct in6_rrenumreq {
#define SIOCGDRLST_IN6 _IOWR('i', 74, struct in6_drlist)
#define SIOCGPRLST_IN6 _IOWR('i', 75, struct in6_prlist)
#define SIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ndireq)
#ifdef _KERNEL
#define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq)
#endif
#define SIOCGIFINFO_IN6 _IOWR('i', 108, struct in6_ndireq)
#define SIOCSNDFLUSH_IN6 _IOWR('i', 77, struct in6_ifreq)
#define SIOCGNBRINFO_IN6 _IOWR('i', 78, struct in6_nbrinfo)
#define SIOCSPFXFLUSH_IN6 _IOWR('i', 79, struct in6_ifreq)
@ -439,11 +438,7 @@ struct in6_rrenumreq {
#ifdef _KERNEL
extern struct in6_ifaddr *in6_ifaddr;
extern struct in6_ifstat **in6_ifstat;
extern size_t in6_ifstatmax;
extern struct icmp6stat icmp6stat;
extern struct icmp6_ifstat **icmp6_ifstat;
extern size_t icmp6_ifstatmax;
#define in6_ifstat_inc(ifp, tag) \
do { \
if (ifp) \

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip6_forward.c,v 1.27 2001/12/18 03:04:03 itojun Exp $ */
/* $NetBSD: ip6_forward.c,v 1.28 2002/05/29 07:53:41 itojun Exp $ */
/* $KAME: ip6_forward.c,v 1.74 2001/06/12 23:54:55 itojun Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.27 2001/12/18 03:04:03 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip6_forward.c,v 1.28 2002/05/29 07:53:41 itojun Exp $");
#include "opt_ipsec.h"
#include "opt_pfil_hooks.h"
@ -372,7 +372,7 @@ ip6_forward(m, srcrt)
return;
}
if (m->m_pkthdr.len > rt->rt_ifp->if_mtu) {
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
if (mcopy) {
u_long mtu;
@ -382,11 +382,11 @@ ip6_forward(m, srcrt)
size_t ipsechdrsiz;
#endif
mtu = rt->rt_ifp->if_mtu;
mtu = IN6_LINKMTU(rt->rt_ifp);
#ifdef IPSEC
/*
* When we do IPsec tunnel ingress, we need to play
* with if_mtu value (decrement IPsec header size
* with the link value (decrement IPsec header size
* from mtu value). The code is much simpler than v4
* case, as we have the outgoing interface for
* encapsulated packet as "rt->rt_ifp".

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip6_mroute.c,v 1.28 2002/05/14 02:58:33 matt Exp $ */
/* $NetBSD: ip6_mroute.c,v 1.29 2002/05/29 07:53:41 itojun Exp $ */
/* $KAME: ip6_mroute.c,v 1.49 2001/07/25 09:21:18 jinmei Exp $ */
/*
@ -46,7 +46,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.28 2002/05/14 02:58:33 matt Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.29 2002/05/29 07:53:41 itojun Exp $");
#include "opt_inet.h"
@ -82,6 +82,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip6_mroute.c,v 1.28 2002/05/14 02:58:33 matt Exp $")
#include <netinet6/ip6_mroute.h>
#include <netinet6/pim6.h>
#include <netinet6/pim6_var.h>
#include <netinet6/nd6.h>
#include <net/net_osdep.h>
@ -1416,6 +1417,7 @@ phyint_send(ip6, mifp, m)
static struct route_in6 ro;
struct in6_multi *in6m;
struct sockaddr_in6 *dst6;
u_long linkmtu;
/*
* Make a new reference to the packet; make sure that
@ -1475,7 +1477,8 @@ phyint_send(ip6, mifp, m)
* Put the packet into the sending queue of the outgoing interface
* if it would fit in the MTU of the interface.
*/
if (mb_copy->m_pkthdr.len < ifp->if_mtu || ifp->if_mtu < IPV6_MMTU) {
linkmtu = IN6_LINKMTU(ifp);
if (mb_copy->m_pkthdr.len < linkmtu || linkmtu < IPV6_MMTU) {
dst6->sin6_len = sizeof(struct sockaddr_in6);
dst6->sin6_family = AF_INET6;
dst6->sin6_addr = ip6->ip6_dst;
@ -1492,7 +1495,7 @@ phyint_send(ip6, mifp, m)
#endif
} else {
#ifdef MULTICAST_PMTUD
icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
icmp6_error(mb_copy, ICMP6_PACKET_TOO_BIG, 0, linkmtu);
#else
#ifdef MRT6DEBUG
if (mrt6debug & DEBUG_XMIT)

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip6_output.c,v 1.44 2002/03/28 01:33:50 itojun Exp $ */
/* $NetBSD: ip6_output.c,v 1.45 2002/05/29 07:53:41 itojun Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.44 2002/03/28 01:33:50 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.45 2002/05/29 07:53:41 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -126,6 +126,8 @@ static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
struct ip6_frag **));
static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
static int ip6_getpmtu __P((struct route_in6 *, struct route_in6 *,
struct ifnet *, struct in6_addr *, u_long *));
extern struct ifnet loif[NLOOP];
@ -708,55 +710,17 @@ skip_ipsec2:;
if (ifpp)
*ifpp = ifp;
/* Determine path MTU. */
if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu)) != 0)
goto bad;
/*
* Determine path MTU.
* The caller of this function may specify to use the minimum MTU
* in some cases.
*/
if (ro_pmtu != ro) {
/* The first hop and the final destination may differ. */
struct sockaddr_in6 *sin6_fin =
(struct sockaddr_in6 *)&ro_pmtu->ro_dst;
if (ro_pmtu->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
!IN6_ARE_ADDR_EQUAL(&sin6_fin->sin6_addr,
&finaldst))) {
RTFREE(ro_pmtu->ro_rt);
ro_pmtu->ro_rt = (struct rtentry *)0;
}
if (ro_pmtu->ro_rt == 0) {
bzero(sin6_fin, sizeof(*sin6_fin));
sin6_fin->sin6_family = AF_INET6;
sin6_fin->sin6_len = sizeof(struct sockaddr_in6);
sin6_fin->sin6_addr = finaldst;
rtalloc((struct route *)ro_pmtu);
}
}
if (ro_pmtu->ro_rt != NULL) {
u_int32_t ifmtu = nd_ifinfo[ifp->if_index].linkmtu;
mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
if (mtu > ifmtu || mtu == 0) {
/*
* The MTU on the route is larger than the MTU on
* the interface! This shouldn't happen, unless the
* MTU of the interface has been changed after the
* interface was brought up. Change the MTU in the
* route to match the interface MTU (as long as the
* field isn't locked).
*
* if MTU on the route is 0, we need to fix the MTU.
* this case happens with path MTU discovery timeouts.
*/
mtu = ifmtu;
if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */
}
} else {
mtu = nd_ifinfo[ifp->if_index].linkmtu;
}
if (mtu > IPV6_MMTU &&
(flags & IPV6_MINMTU)) {
mtu = IPV6_MMTU;
if (mtu > IPV6_MMTU) {
if ((flags & IPV6_MINMTU))
mtu = IPV6_MMTU;
}
/* Fake scoped addresses */
@ -1220,6 +1184,69 @@ ip6_insertfraghdr(m0, m, hlen, frghdrp)
return(0);
}
static int
ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup)
struct route_in6 *ro_pmtu, *ro;
struct ifnet *ifp;
struct in6_addr *dst;
u_long *mtup;
{
u_int32_t mtu = 0;
int error = 0;
if (ro_pmtu != ro) {
/* The first hop and the final destination may differ. */
struct sockaddr_in6 *sa6_dst =
(struct sockaddr_in6 *)&ro_pmtu->ro_dst;
if (ro_pmtu->ro_rt &&
((ro_pmtu->ro_rt->rt_flags & RTF_UP) == 0 ||
!IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))) {
RTFREE(ro_pmtu->ro_rt);
ro_pmtu->ro_rt = (struct rtentry *)0;
}
if (ro_pmtu->ro_rt == 0) {
bzero(sa6_dst, sizeof(*sa6_dst));
sa6_dst->sin6_family = AF_INET6;
sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
sa6_dst->sin6_addr = *dst;
rtalloc((struct route *)ro_pmtu);
}
}
if (ro_pmtu->ro_rt) {
u_int32_t ifmtu;
if (ifp == NULL)
ifp = ro_pmtu->ro_rt->rt_ifp;
ifmtu = IN6_LINKMTU(ifp);
mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
if (mtu > ifmtu || mtu == 0) {
/*
* The MTU on the route is larger than the MTU on
* the interface! This shouldn't happen, unless the
* MTU of the interface has been changed after the
* interface was brought up. Change the MTU in the
* route to match the interface MTU (as long as the
* field isn't locked).
*
* if MTU on the route is 0, we need to fix the MTU.
* this case happens with path MTU discovery timeouts.
*/
mtu = ifmtu;
if (!(ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU)) {
/* XXX */
ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu;
}
}
} else if (ifp) {
mtu = IN6_LINKMTU(ifp);
} else
error = EHOSTUNREACH; /* XXX */
*mtup = mtu;
return(error);
}
/*
* IP6 socket option processing.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6.c,v 1.57 2002/03/20 22:47:59 itojun Exp $ */
/* $NetBSD: nd6.c,v 1.58 2002/05/29 07:53:41 itojun Exp $ */
/* $KAME: nd6.c,v 1.151 2001/06/19 14:24:41 sumikawa Exp $ */
/*
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.57 2002/03/20 22:47:59 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.58 2002/05/29 07:53:41 itojun Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -59,6 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: nd6.c,v 1.57 2002/03/20 22:47:59 itojun Exp $");
#include <net/if_ether.h>
#include <netinet/if_inarp.h>
#include <net/if_fddi.h>
#include <net/if_ieee80211.h>
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
@ -100,8 +101,6 @@ int nd6_debug = 0;
static int nd6_inuse, nd6_allocated;
struct llinfo_nd6 llinfo_nd6 = {&llinfo_nd6, &llinfo_nd6};
static size_t nd_ifinfo_indexlim = 8;
struct nd_ifinfo *nd_ifinfo = NULL;
struct nd_drhead nd_defrouter;
struct nd_prhead nd_prefix = { 0 };
@ -140,71 +139,40 @@ nd6_init()
nd6_slowtimo, NULL);
}
void
struct nd_ifinfo *
nd6_ifattach(ifp)
struct ifnet *ifp;
{
struct nd_ifinfo *nd;
/*
* We have some arrays that should be indexed by if_index.
* since if_index will grow dynamically, they should grow too.
*/
if (nd_ifinfo == NULL || if_index >= nd_ifinfo_indexlim) {
size_t n;
caddr_t q;
nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK);
bzero(nd, sizeof(*nd));
while (if_index >= nd_ifinfo_indexlim)
nd_ifinfo_indexlim <<= 1;
nd->initialized = 1;
/* grow nd_ifinfo */
n = nd_ifinfo_indexlim * sizeof(struct nd_ifinfo);
q = (caddr_t)malloc(n, M_IP6NDP, M_WAITOK);
bzero(q, n);
if (nd_ifinfo) {
bcopy((caddr_t)nd_ifinfo, q, n/2);
free((caddr_t)nd_ifinfo, M_IP6NDP);
}
nd_ifinfo = (struct nd_ifinfo *)q;
}
nd->chlim = IPV6_DEFHLIM;
nd->basereachable = REACHABLE_TIME;
nd->reachable = ND_COMPUTE_RTIME(nd->basereachable);
nd->retrans = RETRANS_TIMER;
nd->flags = ND6_IFF_PERFORMNUD;
nd6_setmtu(ifp, nd);
#define ND nd_ifinfo[ifp->if_index]
/*
* Don't initialize if called twice.
* XXX: to detect this, we should choose a member that is never set
* before initialization of the ND structure itself. We formaly used
* the linkmtu member, which was not suitable because it could be
* initialized via "ifconfig mtu".
*/
if (ND.basereachable)
return;
#ifdef DIAGNOSTIC
if (!ifindex2ifnet[ifp->if_index])
panic("nd6_ifattach: ifindex2ifnet is NULL");
#endif
ND.linkmtu = ifindex2ifnet[ifp->if_index]->if_mtu;
ND.chlim = IPV6_DEFHLIM;
ND.basereachable = REACHABLE_TIME;
ND.reachable = ND_COMPUTE_RTIME(ND.basereachable);
ND.retrans = RETRANS_TIMER;
ND.receivedra = 0;
ND.flags = ND6_IFF_PERFORMNUD;
nd6_setmtu(ifp);
#undef ND
return nd;
}
/*
* Reset ND level link MTU. This function is called when the physical MTU
* changes, which means we might have to adjust the ND level MTU.
*/
void
nd6_setmtu(ifp)
struct ifnet *ifp;
nd6_ifdetach(nd)
struct nd_ifinfo *nd;
{
free(nd, M_IP6NDP);
}
void
nd6_setmtu(ifp, ndi)
struct ifnet *ifp;
struct nd_ifinfo *ndi;
{
struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
u_long oldmaxmtu = ndi->maxmtu;
u_long oldlinkmtu = ndi->linkmtu;
switch (ifp->if_type) {
case IFT_ARCNET: /* XXX MTU handling needs more work */
@ -213,41 +181,31 @@ nd6_setmtu(ifp)
case IFT_ETHER:
ndi->maxmtu = MIN(ETHERMTU, ifp->if_mtu);
break;
case IFT_FDDI:
ndi->maxmtu = MIN(FDDIIPMTU, ifp->if_mtu);
break;
case IFT_ATM:
ndi->maxmtu = MIN(ATMMTU, ifp->if_mtu);
break;
case IFT_IEEE1394:
ndi->maxmtu = MIN(IEEE1394MTU, ifp->if_mtu);
break;
case IFT_IEEE80211:
ndi->maxmtu = MIN(IEEE80211_MTU, ifp->if_mtu);
break;
default:
ndi->maxmtu = ifp->if_mtu;
break;
}
if (oldmaxmtu != ndi->maxmtu) {
/*
* If the ND level MTU is not set yet, or if the maxmtu
* is reset to a smaller value than the ND level MTU,
* also reset the ND level MTU.
*/
if (ndi->linkmtu == 0 ||
ndi->maxmtu < ndi->linkmtu) {
ndi->linkmtu = ndi->maxmtu;
/* also adjust in6_maxmtu if necessary. */
if (oldlinkmtu == 0) {
/*
* XXX: the case analysis is grotty, but
* it is not efficient to call in6_setmaxmtu()
* here when we are during the initialization
* procedure.
*/
if (in6_maxmtu < ndi->linkmtu)
in6_maxmtu = ndi->linkmtu;
} else
in6_setmaxmtu();
}
if (ndi->maxmtu < IPV6_MMTU) {
nd6log((LOG_INFO, "nd6_setmtu: "
"link MTU on %s (%lu) is too small for IPv6\n",
if_name(ifp), (unsigned long)ndi->maxmtu));
}
#undef MIN
if (ndi->maxmtu > in6_maxmtu)
in6_setmaxmtu(); /* check all interfaces just in case */
}
void
@ -256,6 +214,7 @@ nd6_option_init(opt, icmp6len, ndopts)
int icmp6len;
union nd_opts *ndopts;
{
bzero(ndopts, sizeof(*ndopts));
ndopts->nd_opts_search = (struct nd_opt_hdr *)opt;
ndopts->nd_opts_last
@ -433,7 +392,7 @@ nd6_timer(ignored_arg)
ln = next;
continue;
}
ndi = &nd_ifinfo[ifp->if_index];
ndi = ND_IFINFO(ifp);
dst = (struct sockaddr_in6 *)rt_key(rt);
if (ln->ln_expire > time_second) {
@ -455,7 +414,7 @@ nd6_timer(ignored_arg)
if (ln->ln_asked < nd6_mmaxtries) {
ln->ln_asked++;
ln->ln_expire = time_second +
nd_ifinfo[ifp->if_index].retrans / 1000;
ND6_RETRANS_SEC(ND_IFINFO(ifp)->retrans);
nd6_ns_output(ifp, NULL, &dst->sin6_addr,
ln, 0);
} else {
@ -510,7 +469,7 @@ nd6_timer(ignored_arg)
if (ln->ln_asked < nd6_umaxtries) {
ln->ln_asked++;
ln->ln_expire = time_second +
nd_ifinfo[ifp->if_index].retrans / 1000;
ND6_RETRANS_SEC(ND_IFINFO(ifp)->retrans);
nd6_ns_output(ifp, &dst->sin6_addr,
&dst->sin6_addr, ln, 0);
} else {
@ -968,8 +927,7 @@ nd6_nud_hint(rt, dst6, force)
ln->ln_state = ND6_LLINFO_REACHABLE;
if (ln->ln_expire)
ln->ln_expire = time_second +
nd_ifinfo[rt->rt_ifp->if_index].reachable;
ln->ln_expire = time_second + ND_IFINFO(rt->rt_ifp)->reachable;
}
void
@ -1376,21 +1334,24 @@ nd6_ioctl(cmd, data, ifp)
}
splx(s);
break;
case OSIOCGIFINFO_IN6:
/* XXX: old ndp(8) assumes a positive value for linkmtu. */
ndi->ndi.linkmtu = IN6_LINKMTU(ifp);
ndi->ndi.maxmtu = ND_IFINFO(ifp)->maxmtu;
ndi->ndi.basereachable = ND_IFINFO(ifp)->basereachable;
ndi->ndi.reachable = ND_IFINFO(ifp)->reachable;
ndi->ndi.retrans = ND_IFINFO(ifp)->retrans;
ndi->ndi.flags = ND_IFINFO(ifp)->flags;
ndi->ndi.recalctm = ND_IFINFO(ifp)->recalctm;
ndi->ndi.chlim = ND_IFINFO(ifp)->chlim;
ndi->ndi.receivedra = ND_IFINFO(ifp)->receivedra;
break;
case SIOCGIFINFO_IN6:
if (!nd_ifinfo || i >= nd_ifinfo_indexlim) {
error = EINVAL;
break;
}
ndi->ndi = nd_ifinfo[ifp->if_index];
ndi->ndi = *ND_IFINFO(ifp);
break;
case SIOCSIFINFO_FLAGS:
/* XXX: almost all other fields of ndi->ndi is unused */
if (!nd_ifinfo || i >= nd_ifinfo_indexlim) {
error = EINVAL;
break;
}
nd_ifinfo[ifp->if_index].flags = ndi->ndi.flags;
ND_IFINFO(ifp)->flags = ndi->ndi.flags;
break;
case SIOCSNDFLUSH_IN6: /* XXX: the ioctl name is confusing... */
/* flush default router list */
@ -1721,15 +1682,14 @@ nd6_slowtimo(ignored_arg)
void *ignored_arg;
{
int s = splsoftnet();
int i;
struct nd_ifinfo *nd6if;
struct ifnet *ifp;
callout_reset(&nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
nd6_slowtimo, NULL);
for (i = 1; i < if_index + 1; i++) {
if (!nd_ifinfo || i >= nd_ifinfo_indexlim)
continue;
nd6if = &nd_ifinfo[i];
for (ifp = TAILQ_FIRST(&ifnet); ifp; ifp = TAILQ_NEXT(ifp, if_list))
{
nd6if = ND_IFINFO(ifp);
if (nd6if->basereachable && /* already initialized */
(nd6if->recalctm -= ND6_SLOWTIMER_INTERVAL) <= 0) {
/*
@ -1850,7 +1810,7 @@ nd6_output(ifp, origifp, m0, dst, rt0)
}
if (!ln || !rt) {
if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
!(nd_ifinfo[ifp->if_index].flags & ND6_IFF_PERFORMNUD)) {
!(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
log(LOG_DEBUG,
"nd6_output: can't allocate llinfo for %s "
"(ln=%p, rt=%p)\n",
@ -1907,7 +1867,7 @@ nd6_output(ifp, origifp, m0, dst, rt0)
ln->ln_expire < time_second) {
ln->ln_asked++;
ln->ln_expire = time_second +
nd_ifinfo[ifp->if_index].retrans / 1000;
ND6_RETRANS_SEC(ND_IFINFO(ifp)->retrans);
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6.h,v 1.25 2002/05/28 11:26:43 itojun Exp $ */
/* $NetBSD: nd6.h,v 1.26 2002/05/29 07:53:42 itojun Exp $ */
/* $KAME: nd6.h,v 1.52 2001/02/19 04:40:37 itojun Exp $ */
/*
@ -70,6 +70,12 @@ struct llinfo_nd6 {
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
/*
* Since the granularity of our retransmission timer is seconds, we should
* ensure that a positive timer value will be mapped to at least one second.
*/
#define ND6_RETRANS_SEC(r) (((r) + 999) / 1000)
struct nd_ifinfo {
u_int32_t linkmtu; /* LinkMTU */
u_int32_t maxmtu; /* Upper bound of LinkMTU */
@ -79,11 +85,24 @@ struct nd_ifinfo {
u_int32_t flags; /* Flags */
int recalctm; /* BaseReacable re-calculation timer */
u_int8_t chlim; /* CurHopLimit */
u_int8_t receivedra;
u_int8_t initialized; /* Flag to see the entry is initialized */
#define receivedra initialized /* obsoleted */
/* the following 3 members are for privacy extension for addrconf */
u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */
u_int8_t randomid[8]; /* current random ID */
};
#define ND6_IFF_PERFORMNUD 0x1
#ifdef _KERNEL
#define ND_IFINFO(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
#define IN6_LINKMTU(ifp) \
((ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) \
? ND_IFINFO(ifp)->linkmtu : (ifp)->if_mtu)
#endif
struct in6_nbrinfo {
char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */
struct in6_addr addr; /* IPv6 address of the neighbor */
@ -122,6 +141,23 @@ struct in6_prlist {
} prefix[PRLSTSIZ];
};
#ifdef _KERNEL
struct in6_ondireq {
char ifname[IFNAMSIZ];
struct {
u_int32_t linkmtu; /* LinkMTU */
u_int32_t maxmtu; /* Upper bound of LinkMTU */
u_int32_t basereachable; /* BaseReachableTime */
u_int32_t reachable; /* Reachable Time */
u_int32_t retrans; /* Retrans Timer */
u_int32_t flags; /* Flags */
int recalctm; /* BaseReacable re-calculation timer */
u_int8_t chlim; /* CurHopLimit */
u_int8_t receivedra;
} ndi;
};
#endif
struct in6_ndireq {
char ifname[IFNAMSIZ];
struct nd_ifinfo ndi;
@ -242,7 +278,6 @@ extern int nd6_useloopback;
extern int nd6_maxnudhint;
extern int nd6_gctimer;
extern struct llinfo_nd6 llinfo_nd6;
extern struct nd_ifinfo *nd_ifinfo;
extern struct nd_drhead nd_defrouter;
extern struct nd_prhead nd_prefix;
extern int nd6_debug;
@ -260,7 +295,7 @@ union nd_opts {
struct nd_opt_hdr *zero;
struct nd_opt_hdr *src_lladdr;
struct nd_opt_hdr *tgt_lladdr;
struct nd_opt_prefix_info *pi_beg;/* multiple opts, start */
struct nd_opt_prefix_info *pi_beg; /* multiple opts, start */
struct nd_opt_rd_hdr *rh;
struct nd_opt_mtu *mtu;
struct nd_opt_hdr *search; /* multiple opts */
@ -282,13 +317,14 @@ union nd_opts {
/* XXX: need nd6_var.h?? */
/* nd6.c */
void nd6_init __P((void));
void nd6_ifattach __P((struct ifnet *));
struct nd_ifinfo *nd6_ifattach __P((struct ifnet *));
void nd6_ifdetach __P((struct nd_ifinfo *));
int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));
void nd6_option_init __P((void *, int, union nd_opts *));
struct nd_opt_hdr *nd6_option __P((union nd_opts *));
int nd6_options __P((union nd_opts *));
struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
void nd6_setmtu __P((struct ifnet *));
void nd6_setmtu __P((struct ifnet *, struct nd_ifinfo *));
void nd6_timer __P((void *));
void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6_nbr.c,v 1.35 2002/05/28 10:11:51 itojun Exp $ */
/* $NetBSD: nd6_nbr.c,v 1.36 2002/05/29 07:53:42 itojun 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.35 2002/05/28 10:11:51 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: nd6_nbr.c,v 1.36 2002/05/29 07:53:42 itojun Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -657,7 +657,7 @@ nd6_na_input(m, off, icmp6len)
ln->ln_byhint = 0;
if (ln->ln_expire)
ln->ln_expire = time_second +
nd_ifinfo[rt->rt_ifp->if_index].reachable;
ND_IFINFO(rt->rt_ifp)->reachable;
} else {
ln->ln_state = ND6_LLINFO_STALE;
ln->ln_expire = time_second + nd6_gctimer;
@ -738,7 +738,7 @@ nd6_na_input(m, off, icmp6len)
ln->ln_byhint = 0;
if (ln->ln_expire) {
ln->ln_expire = time_second +
nd_ifinfo[ifp->if_index].reachable;
ND_IFINFO(ifp)->reachable;
}
} else {
if (lladdr && llchange) {
@ -1094,7 +1094,7 @@ nd6_dad_start(ifa, tick)
if (tick == NULL) {
nd6_dad_ns_output(dp, ifa);
nd6_dad_starttimer(dp,
nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
ND6_RETRANS_SEC(ND_IFINFO(ifa->ifa_ifp)->retrans) * hz);
} else {
int ntick;
@ -1186,7 +1186,7 @@ nd6_dad_timer(ifa)
*/
nd6_dad_ns_output(dp, ifa);
nd6_dad_starttimer(dp,
nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000);
ND6_RETRANS_SEC(ND_IFINFO(ifa->ifa_ifp)->retrans) * hz);
} else {
/*
* We have transmitted sufficient number of DAD packets.

View File

@ -1,4 +1,4 @@
/* $NetBSD: nd6_rtr.c,v 1.28 2001/12/18 03:04:05 itojun Exp $ */
/* $NetBSD: nd6_rtr.c,v 1.29 2002/05/29 07:53:42 itojun 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.28 2001/12/18 03:04:05 itojun Exp $");
__KERNEL_RCSID(0, "$NetBSD: nd6_rtr.c,v 1.29 2002/05/29 07:53:42 itojun Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -193,7 +193,7 @@ nd6_ra_input(m, off, icmp6len)
int off, icmp6len;
{
struct ifnet *ifp = m->m_pkthdr.rcvif;
struct nd_ifinfo *ndi = &nd_ifinfo[ifp->if_index];
struct nd_ifinfo *ndi = ND_IFINFO(ifp);
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct nd_router_advert *nd_ra;
struct in6_addr saddr6 = ip6->ip6_src;