KAME netinet6 basic part(no IPsec,no V6 Multicast Forwarding, no UDP/TCP

for IPv6 yet)

With this patch, you can assigne IPv6 addr automatically, and can reply to
IPv6 ping.

Reviewed by: freebsd-arch, cvs-committers
Obtained from: KAME project
This commit is contained in:
Yoshinobu Inoue 1999-11-22 02:45:11 +00:00
parent a7a9b4714d
commit 82cd038d51
66 changed files with 21626 additions and 223 deletions

View file

@ -29,6 +29,7 @@ maxusers 32
options MATH_EMULATE #Support for x87 emulation
options INET #InterNETworking
#options "INET6" #IPv6
options FFS #Berkeley Fast Filesystem
options FFS_ROOT #FFS usable as root device [keep this!]
options MFS #Memory Filesystem

View file

@ -41,7 +41,9 @@ INCLUDES+= -I$S/../include
.else
INCLUDES+= -I/usr/include
.endif
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h
# KAME mandatory flags
COPTS+= -D_KERNEL
CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS}
# XXX LOCORE means "don't declare C stuff" not "for locore.s".

View file

@ -41,7 +41,9 @@ INCLUDES+= -I$S/../include
.else
INCLUDES+= -I/usr/include
.endif
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h
# KAME mandatory flags
COPTS+= -D_KERNEL
CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS}
# XXX LOCORE means "don't declare C stuff" not "for locore.s".

View file

@ -483,6 +483,7 @@ net/rtsock.c standard
net/slcompress.c optional ppp
net/slcompress.c optional sl
net/zlib.c optional ppp_deflate
net/net_osdep.c standard
netatalk/aarp.c optional netatalk
netatalk/at_control.c optional netatalk
netatalk/at_proto.c optional netatalk
@ -612,6 +613,25 @@ netinet/tcp_subr.c optional inet
netinet/tcp_timer.c optional inet
netinet/tcp_usrreq.c optional inet
netinet/udp_usrreq.c optional inet
netinet6/in6.c optional inet6
netinet6/in6_ifattach.c optional inet6
netinet6/in6_cksum.c optional inet6
netinet6/in6_pcb.c optional inet6
netinet6/in6_proto.c optional inet6
netinet6/in6_rmx.c optional inet6
netinet6/in6_prefix.c optional inet6
netinet6/dest6.c optional inet6
netinet6/frag6.c optional inet6
netinet6/icmp6.c optional inet6
netinet6/ip6_input.c optional inet6
netinet6/ip6_forward.c optional inet6
netinet6/ip6_output.c optional inet6
netinet6/route6.c optional inet6
netinet6/mld6.c optional inet6
netinet6/nd6.c optional inet6
netinet6/nd6_nbr.c optional inet6
netinet6/nd6_rtr.c optional inet6
netinet6/raw_ip6.c optional inet6
netipx/ipx.c optional ipx
netipx/ipx_cksum.c optional ipx
netipx/ipx_input.c optional ipx

View file

@ -1,7 +1,7 @@
# $FreeBSD$
#
# On the handling of kernel options
#
#
# All kernel options should be listed in LINT, with suitable
# descriptions. Negative options (options that make some code not
# compile) should be commented out; LINT should compile as much code
@ -10,7 +10,7 @@
# possible to have a full compile-test. If necessary, you can include
# "opt_lint.h" and check for COMPILING_LINT to get maximum code
# coverage.
#
#
# All new options shall also be listed in either "conf/options" or
# "<machine>/conf/options.<machine>". Options that affect a single
# source-file <xxx>.[c|s] should be directed into "opt_<xxx>.h", while
@ -20,7 +20,7 @@
# only some files. Note that the effect of listing only an option
# without a header-file-name in conf/options (and cousins) is that the
# last convention is followed.
#
#
# This handling scheme is not yet fully implemented.
#
#
@ -103,8 +103,8 @@ FFS
NFS
NWFS
# If you are following the conditions in the copyright,
# you can enable soft-updates which will speed up a lot of thigs
# If you are following the conditions in the copyright,
# you can enable soft-updates which will speed up a lot of thigs
# and make the system safer from crashes at the same time.
# otherwise a STUB module will be compiled in.
SOFTUPDATES opt_ffs.h
@ -216,6 +216,10 @@ BRIDGE opt_bdg.h
MROUTING opt_mrouting.h
INET opt_inet.h
INET6 opt_inet.h
IPSEC opt_ipsec.h
IPSEC_ESP opt_ipsec.h
IPSEC_DEBUG opt_ipsec.h
IPSEC_IPV6FWD opt_ipsec.h
IPDIVERT
DUMMYNET opt_ipdn.h
IPFILTER_LKM opt_ipfilter.h
@ -224,6 +228,10 @@ IPFIREWALL_VERBOSE opt_ipfw.h
IPFIREWALL_VERBOSE_LIMIT opt_ipfw.h
IPFIREWALL_DEFAULT_TO_ACCEPT opt_ipfw.h
IPFIREWALL_FORWARD opt_ipfw.h
IPV6FIREWALL opt_ip6fw.h
IPV6FIREWALL_VERBOSE opt_ip6fw.h
IPV6FIREWALL_VERBOSE_LIMIT opt_ip6fw.h
IPV6FIREWALL_DEFAULT_TO_ACCEPT opt_ip6fw.h
IPSTEALTH
IPX opt_ipx.h
IPXIP opt_ipx.h

View file

@ -29,6 +29,7 @@ maxusers 32
options MATH_EMULATE #Support for x87 emulation
options INET #InterNETworking
#options "INET6" #IPv6
options FFS #Berkeley Fast Filesystem
options FFS_ROOT #FFS usable as root device [keep this!]
options MFS #Memory Filesystem

View file

@ -41,7 +41,9 @@ INCLUDES+= -I$S/../include
.else
INCLUDES+= -I/usr/include
.endif
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h
COPTS= ${INCLUDES} ${IDENT} -DKERNEL -include opt_global.h
# KAME mandatory flags
COPTS+= -D_KERNEL
CFLAGS= ${COPTFLAGS} ${CWARNFLAGS} ${DEBUG} ${COPTS}
# XXX LOCORE means "don't declare C stuff" not "for locore.s".

View file

@ -59,6 +59,9 @@ MALLOC_DEFINE(M_CACHE, "cache", "Various Dynamically allocated caches");
MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory");
MALLOC_DEFINE(M_TEMP, "temp", "misc temporary data buffers");
MALLOC_DEFINE(M_IP6OPT, "ip6opt", "IPv6 options");
MALLOC_DEFINE(M_IP6NDP, "ip6ndp", "IPv6 Neighbor Discovery");
static void kmeminit __P((void *));
SYSINIT(kmem, SI_SUB_KMEM, SI_ORDER_FIRST, kmeminit, NULL)
@ -473,7 +476,7 @@ malloc_init(data)
{
struct malloc_type *type = (struct malloc_type *)data;
if (type->ks_magic != M_MAGIC)
if (type->ks_magic != M_MAGIC)
panic("malloc type lacks magic");
if (type->ks_limit != 0)
@ -498,7 +501,7 @@ malloc_uninit(data)
struct malloc_type *type = (struct malloc_type *)data;
struct malloc_type *t;
if (type->ks_magic != M_MAGIC)
if (type->ks_magic != M_MAGIC)
panic("malloc type lacks magic");
if (cnt.v_page_count == 0)

View file

@ -64,7 +64,7 @@ MALLOC_DEFINE(M_PCB, "pcb", "protocol control block");
SYSCTL_DECL(_kern_ipc);
static int somaxconn = SOMAXCONN;
SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW,
SYSCTL_INT(_kern_ipc, KIPC_SOMAXCONN, somaxconn, CTLFLAG_RW,
&somaxconn, 0, "Maximum pending socket connection queue size");
/*
@ -1218,6 +1218,117 @@ integer:
}
}
/* XXX; prepare mbuf for (__FreeBSD__ < 3) routines. */
int
soopt_getm(struct sockopt *sopt, struct mbuf **mp)
{
struct mbuf *m, *m_prev;
int sopt_size = sopt->sopt_valsize;
MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_DATA);
if (m == 0)
return ENOBUFS;
if (sopt_size > MLEN) {
MCLGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
m_free(m);
return ENOBUFS;
}
m->m_len = min(MCLBYTES, sopt_size);
} else {
m->m_len = min(MLEN, sopt_size);
}
sopt_size -= m->m_len;
*mp = m;
m_prev = m;
while (sopt_size) {
MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_DATA);
if (m == 0) {
m_freem(*mp);
return ENOBUFS;
}
if (sopt_size > MLEN) {
MCLGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT);
if ((m->m_flags & M_EXT) == 0) {
m_freem(*mp);
return ENOBUFS;
}
m->m_len = min(MCLBYTES, sopt_size);
} else {
m->m_len = min(MLEN, sopt_size);
}
sopt_size -= m->m_len;
m_prev->m_next = m;
m_prev = m;
}
return 0;
}
/* XXX; copyin sopt data into mbuf chain for (__FreeBSD__ < 3) routines. */
int
soopt_mcopyin(struct sockopt *sopt, struct mbuf *m)
{
struct mbuf *m0 = m;
if (sopt->sopt_val == NULL)
return 0;
while (m != NULL && sopt->sopt_valsize >= m->m_len) {
if (sopt->sopt_p != NULL) {
int error;
error = copyin(sopt->sopt_val, mtod(m, char *),
m->m_len);
if (error != 0) {
m_freem(m0);
return(error);
}
} else
bcopy(sopt->sopt_val, mtod(m, char *), m->m_len);
sopt->sopt_valsize -= m->m_len;
(caddr_t)sopt->sopt_val += m->m_len;
m = m->m_next;
}
if (m != NULL) /* should be allocated enoughly at ip6_sooptmcopyin() */
panic("ip6_sooptmcopyin");
return 0;
}
/* XXX; copyout mbuf chain data into soopt for (__FreeBSD__ < 3) routines. */
int
soopt_mcopyout(struct sockopt *sopt, struct mbuf *m)
{
struct mbuf *m0 = m;
size_t valsize = 0;
if (sopt->sopt_val == NULL)
return 0;
while (m != NULL && sopt->sopt_valsize >= m->m_len) {
if (sopt->sopt_p != NULL) {
int error;
error = copyout(mtod(m, char *), sopt->sopt_val,
m->m_len);
if (error != 0) {
m_freem(m0);
return(error);
}
} else
bcopy(mtod(m, char *), sopt->sopt_val, m->m_len);
sopt->sopt_valsize -= m->m_len;
(caddr_t)sopt->sopt_val += m->m_len;
valsize += m->m_len;
m = m->m_next;
}
if (m != NULL) {
/* enough soopt buffer should be given from user-land */
m_freem(m0);
return(EINVAL);
}
sopt->sopt_valsize = valsize;
return 0;
}
void
sohasoutofband(so)
register struct socket *so;

View file

@ -35,6 +35,7 @@
*/
#include "opt_compat.h"
#include "opt_inet.h"
#include <sys/param.h>
#include <sys/malloc.h>
@ -53,6 +54,11 @@
#include <net/if_dl.h>
#include <net/radix.h>
#ifdef INET6
/*XXX*/
#include <netinet/in.h>
#endif
/*
* System initialization
*/
@ -71,6 +77,14 @@ MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
int ifqmaxlen = IFQ_MAXLEN;
struct ifnethead ifnet; /* depend on static init XXX */
#ifdef INET6
/*
* XXX: declare here to avoid to include many inet6 related files..
* should be more generalized?
*/
extern void nd6_setmtu __P((struct ifnet *));
#endif
/*
* Network interface utility routines.
*
@ -98,6 +112,7 @@ ifinit(dummy)
int if_index = 0;
struct ifaddr **ifnet_addrs;
struct ifnet **ifindex2ifnet = NULL;
/*
@ -131,19 +146,32 @@ if_attach(ifp)
* this unlikely case.
*/
TAILQ_INIT(&ifp->if_addrhead);
TAILQ_INIT(&ifp->if_prefixhead);
LIST_INIT(&ifp->if_multiaddrs);
getmicrotime(&ifp->if_lastchange);
if (ifnet_addrs == 0 || if_index >= if_indexlim) {
unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
struct ifaddr **q = (struct ifaddr **)
malloc(n, M_IFADDR, M_WAITOK);
bzero((caddr_t)q, n);
caddr_t q = malloc(n, M_IFADDR, M_WAITOK);
bzero(q, n);
if (ifnet_addrs) {
bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
free((caddr_t)ifnet_addrs, M_IFADDR);
}
ifnet_addrs = q;
ifnet_addrs = (struct ifaddr **)q;
/* grow ifindex2ifnet */
n = if_indexlim * sizeof(struct ifnet *);
q = malloc(n, M_IFADDR, M_WAITOK);
bzero(q, n);
if (ifindex2ifnet) {
bcopy((caddr_t)ifindex2ifnet, q, n/2);
free((caddr_t)ifindex2ifnet, M_IFADDR);
}
ifindex2ifnet = (struct ifnet **)q;
}
ifindex2ifnet[if_index] = ifp;
/*
* create a Link Level name for this device
*/
@ -207,7 +235,7 @@ if_detach(ifp)
ifa = TAILQ_FIRST(&ifp->if_addrhead)) {
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
IFAFREE(ifa);
}
}
TAILQ_REMOVE(&ifnet, ifp, if_link);
}
@ -226,13 +254,15 @@ 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; ifp = ifp->if_link.tqe_next)
for (ifa = ifp->if_addrhead.tqh_first; ifa;
for (ifa = ifp->if_addrhead.tqh_first; ifa;
ifa = ifa->ifa_link.tqe_next) {
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);
}
@ -251,7 +281,7 @@ ifa_ifwithdstaddr(addr)
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
if (ifp->if_flags & IFF_POINTOPOINT)
for (ifa = ifp->if_addrhead.tqh_first; ifa;
for (ifa = ifp->if_addrhead.tqh_first; ifa;
ifa = ifa->ifa_link.tqe_next) {
if (ifa->ifa_addr->sa_family != addr->sa_family)
continue;
@ -285,7 +315,7 @@ ifa_ifwithnet(addr)
return (ifnet_addrs[sdl->sdl_index - 1]);
}
/*
/*
* Scan though each interface, looking for ones that have
* addresses in this address family.
*/
@ -296,13 +326,17 @@ ifa_ifwithnet(addr)
if (ifa->ifa_addr->sa_family != af)
next: continue;
if (ifp->if_flags & IFF_POINTOPOINT) {
if (
#ifdef INET6 /* XXX: for maching gif tunnel dst as routing entry gateway */
addr->sa_family != AF_INET6 &&
#endif
ifp->if_flags & IFF_POINTOPOINT) {
/*
* This is a bit broken as it doesn't
* take into account that the remote end may
* This is a bit broken as it doesn't
* take into account that the remote end may
* be a single node in the network we are
* looking for.
* The trouble is that we don't know the
* The trouble is that we don't know the
* netmask for the remote end.
*/
if (ifa->ifa_dstaddr != 0
@ -372,7 +406,7 @@ ifaof_ifpforaddr(addr, ifp)
if (af >= AF_MAX)
return (0);
for (ifa = ifp->if_addrhead.tqh_first; ifa;
for (ifa = ifp->if_addrhead.tqh_first; ifa;
ifa = ifa->ifa_link.tqe_next) {
if (ifa->ifa_addr->sa_family != af)
continue;
@ -471,6 +505,9 @@ if_route(ifp, flag, fam)
if (fam == PF_UNSPEC || (fam == ifa->ifa_addr->sa_family))
pfctlinput(PRC_IFUP, ifa->ifa_addr);
rt_ifmsg(ifp);
#ifdef INET6
in6_if_up(ifp);
#endif
}
/*
@ -559,9 +596,9 @@ ifunit(name)
/*
* Look for a non numeric part
*/
end = name + IFNAMSIZ;
end = name + IFNAMSIZ;
cp2 = namebuf;
cp = name;
cp = name;
while ((cp < end) && (c = *cp)) {
if (c >= '0' && c <= '9')
break;
@ -576,7 +613,7 @@ ifunit(name)
*/
len = cp - name + 1;
for (unit = 0;
((c = *cp) >= '0') && (c <= '9') && (unit < 1000000); cp++ )
((c = *cp) >= '0') && (c <= '9') && (unit < 1000000); cp++ )
unit = (unit * 10) + (c - '0');
if (*cp != '\0')
return 0; /* no trailing garbage allowed */
@ -592,6 +629,35 @@ ifunit(name)
return (ifp);
}
/*
* Map interface name in a sockaddr_dl to
* interface structure pointer.
*/
struct ifnet *
if_withname(sa)
struct sockaddr *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;
/*
* ifunit wants a null-terminated name. It may not be null-terminated
* in the sockaddr. We don't want to change the caller's sockaddr,
* and there might not be room to put the trailing null anyway, so we
* make a local copy that we know we can null terminate safely.
*/
bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
ifname[sdl->sdl_nlen] = '\0';
return ifunit(ifname);
}
/*
* Interface ioctls.
*/
@ -606,6 +672,7 @@ ifioctl(so, cmd, data, p)
register struct ifreq *ifr;
struct ifstat *ifs;
int error;
short oif_flags;
switch (cmd) {
@ -680,6 +747,9 @@ ifioctl(so, cmd, data, p)
return(error);
case SIOCSIFMTU:
{
u_long oldmtu = ifp->if_mtu;
error = suser(p);
if (error)
return (error);
@ -690,7 +760,16 @@ ifioctl(so, cmd, data, p)
error = (*ifp->if_ioctl)(ifp, cmd, data);
if (error == 0)
getmicrotime(&ifp->if_lastchange);
return(error);
/*
* If the link MTU changed, do network layer specific procedure.
*/
if (ifp->if_mtu != oldmtu) {
#ifdef INET6
nd6_setmtu(ifp);
#endif
}
return (error);
}
case SIOCADDMULTI:
case SIOCDELMULTI:
@ -739,10 +818,11 @@ ifioctl(so, cmd, data, p)
return ((*ifp->if_ioctl)(ifp, cmd, data));
default:
oif_flags = ifp->if_flags;
if (so->so_proto == 0)
return (EOPNOTSUPP);
#ifndef COMPAT_43
return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
data,
ifp, p));
#else
@ -793,11 +873,22 @@ ifioctl(so, cmd, data, p)
case OSIOCGIFBRDADDR:
case OSIOCGIFNETMASK:
*(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
}
}
#endif /* COMPAT_43 */
if ((oif_flags ^ ifp->if_flags) & IFF_UP) {
#ifdef INET6
if (ifp->if_flags & IFF_UP) {
int s = splimp();
in6_if_up(ifp);
splx(s);
}
#endif
}
return (error);
}
#endif
}
return (0);
}
@ -960,7 +1051,7 @@ if_allmulti(ifp, onswitch)
/*
* Add a multicast listenership to the interface in question.
* The link layer provides a routine which converts
* The link layer provides a routine which converts
*/
int
if_addmulti(ifp, sa, retifma)
@ -976,7 +1067,7 @@ if_addmulti(ifp, sa, retifma)
* If the matching multicast address already exists
* then don't add a new one, just add a reference
*/
for (ifma = ifp->if_multiaddrs.lh_first; ifma;
for (ifma = ifp->if_multiaddrs.lh_first; ifma;
ifma = ifma->ifma_link.le_next) {
if (equal(sa, ifma->ifma_addr)) {
ifma->ifma_refcount++;
@ -1063,7 +1154,7 @@ if_delmulti(ifp, sa)
struct ifmultiaddr *ifma;
int s;
for (ifma = ifp->if_multiaddrs.lh_first; ifma;
for (ifma = ifp->if_multiaddrs.lh_first; ifma;
ifma = ifma->ifma_link.le_next)
if (equal(sa, ifma->ifma_addr))
break;
@ -1096,7 +1187,7 @@ if_delmulti(ifp, sa)
* in the record for the link-layer address. (So we don't complain
* in that case.)
*/
for (ifma = ifp->if_multiaddrs.lh_first; ifma;
for (ifma = ifp->if_multiaddrs.lh_first; ifma;
ifma = ifma->ifma_link.le_next)
if (equal(sa, ifma->ifma_addr))
break;

View file

@ -56,11 +56,15 @@
#include <net/if_dl.h>
#include <net/if_types.h>
#ifdef INET
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#endif
#ifdef INET6
#include <netinet6/nd6.h>
#include <netinet6/in6_ifattach.h>
#endif
#ifdef IPX
#include <netipx/ipx.h>
@ -112,7 +116,7 @@ extern u_char aarp_org_code[3];
#include <net/if_vlan_var.h>
#endif /* NVLAN > 0 */
static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
static int ether_resolvemulti __P((struct ifnet *, struct sockaddr **,
struct sockaddr *));
u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
#define senderr(e) do { error = (e); goto bad;} while (0)
@ -146,7 +150,7 @@ static struct ng_type typestruct = {
ngether_connect,
ngether_rcvdata,
ngether_rcvdata,
ngether_disconnect
ngether_disconnect
};
#define AC2NG(AC) ((node_p)((AC)->ac_ng))
@ -214,6 +218,17 @@ ether_output(ifp, m0, dst, rt0)
type = htons(ETHERTYPE_IP);
break;
#endif
#ifdef INET6
case AF_INET6:
if (!nd6_storelladdr(&ac->ac_if, rt, m, dst, (u_char *)edst)) {
/* this must be impossible, so we bark */
printf("nd6_storelladdr failed\n");
return(0);
}
off = m->m_pkthdr.len - m->m_len;
type = htons(ETHERTYPE_IPV6);
break;
#endif
#ifdef IPX
case AF_IPX:
type = htons(ETHERTYPE_IPX);
@ -530,6 +545,12 @@ ether_input(ifp, eh, m)
inq = &ipxintrq;
break;
#endif
#ifdef INET6
case ETHERTYPE_IPV6:
schednetisr(NETISR_IPV6);
inq = &ip6intrq;
break;
#endif
#ifdef NS
case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */
schednetisr(NETISR_NS);
@ -741,6 +762,9 @@ ether_ifattach(ifp)
#ifdef NETGRAPH
ngether_init(ifp);
#endif /* NETGRAPH */
#ifdef INET6
in6_ifattach_getifid(ifp);
#endif
}
SYSCTL_DECL(_net_link);
@ -778,7 +802,7 @@ ether_ioctl(ifp, command, data)
if (ipx_nullhost(*ina))
ina->x_host =
*(union ipx_host *)
*(union ipx_host *)
ac->ac_enaddr;
else {
bcopy((caddr_t) ina->x_host.c_host,
@ -856,11 +880,14 @@ ether_resolvemulti(ifp, llsa, sa)
{
struct sockaddr_dl *sdl;
struct sockaddr_in *sin;
#ifdef INET6
struct sockaddr_in6 *sin6;
#endif
u_char *e_addr;
switch(sa->sa_family) {
case AF_LINK:
/*
/*
* No mapping needed. Just check that it's a valid MC address.
*/
sdl = (struct sockaddr_dl *)sa;
@ -889,9 +916,28 @@ ether_resolvemulti(ifp, llsa, sa)
*llsa = (struct sockaddr *)sdl;
return 0;
#endif
#ifdef INET6
case AF_INET6:
sin6 = (struct sockaddr_in6 *)sa;
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
return EADDRNOTAVAIL;
MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR,
M_WAITOK);
sdl->sdl_len = sizeof *sdl;
sdl->sdl_family = AF_LINK;
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = IFT_ETHER;
sdl->sdl_nlen = 0;
sdl->sdl_alen = ETHER_ADDR_LEN;
sdl->sdl_slen = 0;
e_addr = LLADDR(sdl);
ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr);
*llsa = (struct sockaddr *)sdl;
return 0;
#endif
default:
/*
/*
* Well, the text isn't quite right, but it's the name
* that counts...
*/
@ -976,8 +1022,8 @@ ngether_constructor(node_p *nodep)
/*
* Give our ok for a hook to be added...
*
* Allow one hook at a time (rawdata).
*
* Allow one hook at a time (rawdata).
* It can eiteh rdivert everything or only unclaimed packets.
*/
static int
@ -1014,10 +1060,10 @@ ngether_rcvmsg(node_p node,
ifp = node->private;
switch (msg->header.typecookie) {
case NGM_ETHER_COOKIE:
case NGM_ETHER_COOKIE:
error = EINVAL;
break;
case NGM_GENERIC_COOKIE:
case NGM_GENERIC_COOKIE:
switch(msg->header.cmd) {
case NGM_TEXT_STATUS: {
char *arg;
@ -1025,10 +1071,10 @@ ngether_rcvmsg(node_p node,
int resplen = sizeof(struct ng_mesg) + 512;
MALLOC(*resp, struct ng_mesg *, resplen,
M_NETGRAPH, M_NOWAIT);
if (*resp == NULL) {
if (*resp == NULL) {
error = ENOMEM;
break;
}
}
bzero(*resp, resplen);
arg = (*resp)->data;
@ -1135,10 +1181,10 @@ bad:
* pass an mbuf out to the connected hook
* More complicated than just an m_prepend, as it tries to save later nodes
* from needing to do lots of m_pullups.
*/
*/
static void
ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
{
{
int room;
node_p node = AC2NG(ac);
struct ether_header *eh2;
@ -1150,15 +1196,15 @@ ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
eh2 = mtod(m, struct ether_header *) - 1;
if ( eh == eh2) {
/*
* This is the case so just move the markers back to
* This is the case so just move the markers back to
* re-include it. We lucked out.
* This allows us to avoid a yucky m_pullup
* in later nodes if it works.
*/
m->m_len += sizeof(*eh);
*/
m->m_len += sizeof(*eh);
m->m_data -= sizeof(*eh);
m->m_pkthdr.len += sizeof(*eh);
} else {
} else {
/*
* Alternatively there may be room even though
* it is stored somewhere else. If so, copy it in.
@ -1170,7 +1216,7 @@ ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
* that fall into these cases. So we are not optimising
* contorted cases.
*/
if (m->m_flags & M_EXT) {
room = (mtod(m, caddr_t) - m->m_ext.ext_buf);
if (room > m->m_ext.ext_size) /* garbage */
@ -1178,14 +1224,14 @@ ngether_send(struct arpcom *ac, struct ether_header *eh, struct mbuf *m)
} else {
room = (mtod(m, caddr_t) - m->m_pktdat);
}
if (room > sizeof (*eh)) {
if (room > sizeof (*eh)) {
/* we have room, just copy it and adjust */
m->m_len += sizeof(*eh);
m->m_data -= sizeof(*eh);
m->m_pkthdr.len += sizeof(*eh);
} else {
/*
* Doing anything more is likely to get more
* Doing anything more is likely to get more
* expensive than it's worth..
* it's probable that everything else is in one
* big lump. The next node will do an m_pullup()
@ -1230,7 +1276,7 @@ ngether_connect(hook_p hook)
/*
* notify on hook disconnection (destruction)
*
* For this type, removal of the last lins no effect. The interface can run
* For this type, removal of the last lins no effect. The interface can run
* independently.
* Since we have no per-hook information, this is rather simple.
*/

71
sys/net/if_gif.h Normal file
View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* if_gif.h
*/
#ifndef _NET_IF_GIF_H_
#define _NET_IF_GIF_H_
#include <netinet/in.h>
/* xxx sigh, why route have struct route instead of pointer? */
struct gif_softc {
struct ifnet gif_if; /* common area */
struct sockaddr *gif_psrc; /* Physical src addr */
struct sockaddr *gif_pdst; /* Physical dst addr */
union {
struct route gifscr_ro; /* xxx */
struct route_in6 gifscr_ro6; /* xxx */
} gifsc_gifscr;
int gif_flags;
};
#define gif_ro gifsc_gifscr.gifscr_ro
#define gif_ro6 gifsc_gifscr.gifscr_ro6
#define GIFF_INUSE 0x1 /* gif is in use */
#define GIF_MTU (1280) /* Default MTU */
#define GIF_MTU_MIN (1280) /* Minimum MTU */
#define GIF_MTU_MAX (8192) /* Maximum MTU */
extern int ngif;
extern struct gif_softc *gif;
/* Prototypes */
void gif_input __P((struct mbuf *, int, struct ifnet *));
int gif_output __P((struct ifnet *, struct mbuf *,
struct sockaddr *, struct rtentry *));
int gif_ioctl __P((struct ifnet *, u_long, caddr_t));
#endif /* _NET_IF_GIF_H_ */

View file

@ -67,6 +67,14 @@
#include <netipx/ipx_if.h>
#endif
#ifdef INET6
#ifndef INET
#include <netinet/in.h>
#endif
#include <netinet6/in6_var.h>
#include <netinet6/ip6.h>
#endif
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
@ -93,6 +101,8 @@ static int looutput __P((struct ifnet *ifp,
#ifdef TINY_LOMTU
#define LOMTU (1024+512)
#elif defined(LARGE_LOMTU)
#define LOMTU 131072
#else
#define LOMTU 16384
#endif
@ -136,11 +146,41 @@ looutput(ifp, m, dst, rt)
return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
}
/*
* KAME requires that the packet to be contiguous on the
* mbuf. We need to make that sure.
* this kind of code should be avoided.
* XXX: fails to join if interface MTU > MCLBYTES. jumbogram?
*/
if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
struct mbuf *n;
MGETHDR(n, M_DONTWAIT, MT_HEADER);
if (!n)
goto contiguousfail;
MCLGET(n, M_DONTWAIT);
if (! (n->m_flags & M_EXT)) {
m_freem(n);
goto contiguousfail;
}
m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
n->m_pkthdr = m->m_pkthdr;
n->m_len = m->m_pkthdr.len;
m_freem(m);
m = n;
}
if (0) {
contiguousfail:
printf("looutput: mbuf allocation failed\n");
}
ifp->if_opackets++;
ifp->if_obytes += m->m_pkthdr.len;
#if 1 /* XXX */
switch (dst->sa_family) {
case AF_INET:
case AF_INET6:
case AF_IPX:
case AF_NS:
case AF_ISO:
@ -227,6 +267,13 @@ if_simloop(ifp, m, dst, hlen)
isr = NETISR_IP;
break;
#endif
#ifdef INET6
case AF_INET6:
m->m_flags |= M_LOOP;
ifq = &ip6intrq;
isr = NETISR_IPV6;
break;
#endif
#ifdef IPX
case AF_IPX:
ifq = &ipxintrq;
@ -285,7 +332,7 @@ lortrequest(cmd, rt, sa)
* should be at least twice the MTU plus a little more for
* overhead.
*/
rt->rt_rmx.rmx_recvpipe =
rt->rt_rmx.rmx_recvpipe =
rt->rt_rmx.rmx_sendpipe = 3 * LOMTU;
}
}
@ -327,6 +374,10 @@ loioctl(ifp, cmd, data)
case AF_INET:
break;
#endif
#ifdef INET6
case AF_INET6:
break;
#endif
default:
error = EAFNOSUPPORT;

View file

@ -166,6 +166,10 @@ typedef void if_init_f_t __P((void *));
#define if_xmitquota if_data.ifi_xmitquota
#define if_rawoutput(if, m, sa) if_output(if, m, sa, (struct rtentry *)0)
/* for compatibility with other BSDs */
#define if_addrlist if_addrhead
#define if_list if_link
/*
* Bit values in if_ipending
*/
@ -270,16 +274,19 @@ struct ifaddr {
};
#define IFA_ROUTE RTF_UP /* route installed */
/* for compatibility with other BSDs */
#define ifa_list ifa_link
/*
* The prefix structure contains information about one prefix
* of an interface. They are maintained by the different address families,
* are allocated and attached when an prefix or an address is set,
* and are linked together so all prfefixes for an interface can be located.
* and are linked together so all prefixes for an interface can be located.
*/
struct ifprefix {
struct sockaddr *ifpr_prefix; /* prefix of interface */
struct ifnet *ifpr_ifp; /* back-pointer to interface */
TAILQ_ENTRY(ifprefix) *ifpr_list; /* queue macro glue */
TAILQ_ENTRY(ifprefix) ifpr_list; /* queue macro glue */
u_char ifpr_plen; /* prefix length in bits */
u_char ifpr_type; /* protocol dependent prefix type */
};
@ -321,7 +328,7 @@ int ether_output __P((struct ifnet *,
struct mbuf *, struct sockaddr *, struct rtentry *));
int ether_ioctl __P((struct ifnet *, int, caddr_t));
int if_addmulti __P((struct ifnet *, struct sockaddr *,
int if_addmulti __P((struct ifnet *, struct sockaddr *,
struct ifmultiaddr **));
int if_allmulti __P((struct ifnet *, int));
void if_attach __P((struct ifnet *));
@ -352,7 +359,7 @@ struct ifaddr *ifa_ifwithroute __P((int, struct sockaddr *,
struct ifaddr *ifaof_ifpforaddr __P((struct sockaddr *, struct ifnet *));
void ifafree __P((struct ifaddr *));
struct ifmultiaddr *ifmaof_ifpforaddr __P((struct sockaddr *,
struct ifmultiaddr *ifmaof_ifpforaddr __P((struct sockaddr *,
struct ifnet *));
int if_simloop __P((struct ifnet *ifp, struct mbuf *m,
struct sockaddr *dst, int hlen));

58
sys/net/net_osdep.c Normal file
View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/syslog.h>
#include <machine/cpu.h>
#include <net/if.h>
#include <net/if_types.h>
#include <net/netisr.h>
#include <net/route.h>
#include <net/bpf.h>
#include <net/net_osdep.h>
const char *
if_name(ifp)
struct ifnet *ifp;
{
static char nam[IFNAMSIZ + 10]; /*enough?*/
snprintf(nam, sizeof(nam), "%s%d", ifp->if_name, ifp->if_unit);
return nam;
}

121
sys/net/net_osdep.h Normal file
View file

@ -0,0 +1,121 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* glue for kernel code programming differences.
*/
/*
* OS dependencies:
*
* - privileged process
* NetBSD, FreeBSD 3
* struct proc *p;
* if (p && !suser(p->p_ucred, &p->p_acflag))
* privileged;
* OpenBSD, BSDI [34], FreeBSD 2
* struct socket *so;
* if (so->so_state & SS_PRIV)
* privileged;
* - foo_control
* NetBSD, FreeBSD 3
* needs to give struct proc * as argument
* OpenBSD, BSDI [34], FreeBSD 2
* do not need struct proc *
* - bpf:
* OpenBSD, NetBSD, BSDI [34]
* need caddr_t * (= if_bpf **) and struct ifnet *
* FreeBSD 2, FreeBSD 3
* need only struct ifnet * as argument
* - struct ifnet
* use queue.h? member names if name
* --- --- ---
* FreeBSD 2 no old standard if_name+unit
* FreeBSD 3 yes strange if_name+unit
* OpenBSD yes standard if_xname
* NetBSD yes standard if_xname
* BSDI [34] no old standard if_name+unit
* - usrreq
* NetBSD, OpenBSD, BSDI [34], FreeBSD 2
* single function with PRU_xx, arguments are mbuf
* FreeBSD 3
* separates functions, non-mbuf arguments
* - {set,get}sockopt
* NetBSD, OpenBSD, BSDI [34], FreeBSD 2
* manipulation based on mbuf
* FreeBSD 3
* non-mbuf manipulation using sooptcopy{in,out}()
* - timeout() and untimeout()
* NetBSD, OpenBSD, BSDI [34], FreeBSD 2
* timeout() is a void function
* FreeBSD 3
* timeout() is non-void, must keep returned value for untimeuot()
* - sysctl
* NetBSD, OpenBSD
* foo_sysctl()
* BSDI [34]
* foo_sysctl() but with different style
* FreeBSD 2, FreeBSD 3
* linker hack
*
* - if_ioctl
* NetBSD, FreeBSD 3, BSDI [34]
* 2nd argument is u_long cmd
* FreeBSD 2
* 2nd argument is int cmd
* - if attach routines
* NetBSD
* void xxattach(int);
* FreeBSD 2, FreeBSD 3
* void xxattach(void *);
* PSEUDO_SET(xxattach, if_xx);
*
* - ovbcopy()
* in NetBSD 1.4 or later, ovbcopy() is not supplied in the kernel.
* bcopy() is safe against overwrites.
* - splnet()
* NetBSD 1.4 or later requires splsoftnet().
* other operating systems use splnet().
*
* - dtom()
* NEVER USE IT!
*/
#ifndef __NET_NET_OSDEP_H_DEFINED_
#define __NET_NET_OSDEP_H_DEFINED_
#ifdef _KERNEL
struct ifnet;
extern const char *if_name __P((struct ifnet *));
#define HAVE_OLD_BPF
#endif /*_KERNEL*/
#endif /*__NET_NET_OSDEP_H_DEFINED_ */

420
sys/net/pfkeyv2.h Normal file
View file

@ -0,0 +1,420 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/* $Id: keyv2.h,v 1.1.6.1.6.4 1999/06/08 05:33:39 itojun Exp $ */
/*
* This file has been derived rfc 2367,
* And added some flags of SADB_KEY_FLAGS_ as SADB_X_EXT_.
* sakane@ydc.co.jp
*/
#ifndef _NET_PFKEYV2_H_
#define _NET_PFKEYV2_H_
/*
This file defines structures and symbols for the PF_KEY Version 2
key management interface. It was written at the U.S. Naval Research
Laboratory. This file is in the public domain. The authors ask that
you leave this credit intact on any copies of this file.
*/
#ifndef __PFKEY_V2_H
#define __PFKEY_V2_H 1
#define PF_KEY_V2 2
#define PFKEYV2_REVISION 199806L
#define SADB_RESERVED 0
#define SADB_GETSPI 1
#define SADB_UPDATE 2
#define SADB_ADD 3
#define SADB_DELETE 4
#define SADB_GET 5
#define SADB_ACQUIRE 6
#define SADB_REGISTER 7
#define SADB_EXPIRE 8
#define SADB_FLUSH 9
#define SADB_DUMP 10
#define SADB_X_PROMISC 11
#define SADB_X_PCHANGE 12
#define SADB_X_SPDUPDATE 13 /* not yet */
#define SADB_X_SPDADD 14
#define SADB_X_SPDDELETE 15
#define SADB_X_SPDGET 16 /* not yet */
#define SADB_X_SPDACQUIRE 17 /* not yet */
#define SADB_X_SPDDUMP 18
#define SADB_X_SPDFLUSH 19
#define SADB_MAX 19
struct sadb_msg {
u_int8_t sadb_msg_version;
u_int8_t sadb_msg_type;
u_int8_t sadb_msg_errno;
u_int8_t sadb_msg_satype;
u_int16_t sadb_msg_len;
u_int8_t sadb_msg_mode; /* XXX */
u_int8_t sadb_msg_reserved;
u_int32_t sadb_msg_seq;
u_int32_t sadb_msg_pid;
};
struct sadb_ext {
u_int16_t sadb_ext_len;
u_int16_t sadb_ext_type;
};
struct sadb_sa {
u_int16_t sadb_sa_len;
u_int16_t sadb_sa_exttype;
u_int32_t sadb_sa_spi;
u_int8_t sadb_sa_replay;
u_int8_t sadb_sa_state;
u_int8_t sadb_sa_auth;
u_int8_t sadb_sa_encrypt;
u_int32_t sadb_sa_flags;
};
struct sadb_lifetime {
u_int16_t sadb_lifetime_len;
u_int16_t sadb_lifetime_exttype;
u_int32_t sadb_lifetime_allocations;
u_int64_t sadb_lifetime_bytes;
u_int64_t sadb_lifetime_addtime;
u_int64_t sadb_lifetime_usetime;
};
struct sadb_address {
u_int16_t sadb_address_len;
u_int16_t sadb_address_exttype;
u_int8_t sadb_address_proto;
u_int8_t sadb_address_prefixlen;
u_int16_t sadb_address_reserved;
};
struct sadb_key {
u_int16_t sadb_key_len;
u_int16_t sadb_key_exttype;
u_int16_t sadb_key_bits;
u_int16_t sadb_key_reserved;
};
struct sadb_ident {
u_int16_t sadb_ident_len;
u_int16_t sadb_ident_exttype;
u_int16_t sadb_ident_type;
u_int16_t sadb_ident_reserved;
u_int64_t sadb_ident_id;
};
/* in order to use to divide sadb_ident.sadb_ident_id */
union sadb_x_ident_id {
u_int64_t sadb_x_ident_id;
struct _sadb_x_ident_id_addr {
u_int16_t prefix;
u_int16_t ul_proto;
u_int32_t reserved;
} sadb_x_ident_id_addr;
};
struct sadb_sens {
u_int16_t sadb_sens_len;
u_int16_t sadb_sens_exttype;
u_int32_t sadb_sens_dpd;
u_int8_t sadb_sens_sens_level;
u_int8_t sadb_sens_sens_len;
u_int8_t sadb_sens_integ_level;
u_int8_t sadb_sens_integ_len;
u_int32_t sadb_sens_reserved;
};
struct sadb_prop {
u_int16_t sadb_prop_len;
u_int16_t sadb_prop_exttype;
u_int8_t sadb_prop_replay;
u_int8_t sadb_prop_reserved[3];
};
struct sadb_comb {
u_int8_t sadb_comb_auth;
u_int8_t sadb_comb_encrypt;
u_int16_t sadb_comb_flags;
u_int16_t sadb_comb_auth_minbits;
u_int16_t sadb_comb_auth_maxbits;
u_int16_t sadb_comb_encrypt_minbits;
u_int16_t sadb_comb_encrypt_maxbits;
u_int32_t sadb_comb_reserved;
u_int32_t sadb_comb_soft_allocations;
u_int32_t sadb_comb_hard_allocations;
u_int64_t sadb_comb_soft_bytes;
u_int64_t sadb_comb_hard_bytes;
u_int64_t sadb_comb_soft_addtime;
u_int64_t sadb_comb_hard_addtime;
u_int64_t sadb_comb_soft_usetime;
u_int64_t sadb_comb_hard_usetime;
};
struct sadb_supported {
u_int16_t sadb_supported_len;
u_int16_t sadb_supported_exttype;
u_int32_t sadb_supported_reserved;
};
struct sadb_alg {
u_int8_t sadb_alg_id;
u_int8_t sadb_alg_ivlen;
u_int16_t sadb_alg_minbits;
u_int16_t sadb_alg_maxbits;
u_int16_t sadb_alg_reserved;
};
struct sadb_spirange {
u_int16_t sadb_spirange_len;
u_int16_t sadb_spirange_exttype;
u_int32_t sadb_spirange_min;
u_int32_t sadb_spirange_max;
u_int32_t sadb_spirange_reserved;
};
struct sadb_x_kmprivate {
u_int16_t sadb_x_kmprivate_len;
u_int16_t sadb_x_kmprivate_exttype;
u_int32_t sadb_x_kmprivate_reserved;
};
/* XXX Policy Extension */
/* sizeof(struct sadb_x_policy) == 8 */
struct sadb_x_policy {
u_int16_t sadb_x_policy_len;
u_int16_t sadb_x_policy_exttype;
/* See policy type of ipsec.h */
u_int16_t sadb_x_policy_type;
u_int8_t sadb_x_policy_dir; /* direction, see ipsec.h */
u_int8_t sadb_x_policy_reserved;
};
/*
* When policy_type == IPSEC, it is followed by some of
* the ipsec policy request.
* [total length of ipsec policy requests]
* = (sadb_x_policy_len * sizeof(uint64_t) - sizeof(struct sadb_x_policy))
*/
/* XXX IPsec Policy Request Extension */
/*
* This structure is aligned 8 bytes.
*/
struct sadb_x_ipsecrequest {
u_int16_t sadb_x_ipsecrequest_len;
/* structure length aligned to 8 bytes.
* This value is true length of bytes.
* Not in units of 64 bits. */
u_int16_t sadb_x_ipsecrequest_proto; /* See ipsec.h */
/* See ipsec.h. Not SADB_SATYPE_XX */
u_int16_t sadb_x_ipsecrequest_mode;
u_int16_t sadb_x_ipsecrequest_level; /* See ipsec.h */
/*
* followed by source IP address of SA, and immediately followed by
* destination IP address of SA. These encoded into two of sockaddr
* structure without any padding. Must set each sa_len exactly.
* Each of length of the sockaddr structure are not aligned to 64bits,
* but sum of x_request and addresses is aligned to 64bits.
*/
};
#define SADB_EXT_RESERVED 0
#define SADB_EXT_SA 1
#define SADB_EXT_LIFETIME_CURRENT 2
#define SADB_EXT_LIFETIME_HARD 3
#define SADB_EXT_LIFETIME_SOFT 4
#define SADB_EXT_ADDRESS_SRC 5
#define SADB_EXT_ADDRESS_DST 6
#define SADB_EXT_ADDRESS_PROXY 7
#define SADB_EXT_KEY_AUTH 8
#define SADB_EXT_KEY_ENCRYPT 9
#define SADB_EXT_IDENTITY_SRC 10
#define SADB_EXT_IDENTITY_DST 11
#define SADB_EXT_SENSITIVITY 12
#define SADB_EXT_PROPOSAL 13
#define SADB_EXT_SUPPORTED_AUTH 14
#define SADB_EXT_SUPPORTED_ENCRYPT 15
#define SADB_EXT_SPIRANGE 16
#define SADB_X_EXT_KMPRIVATE 17
#define SADB_X_EXT_POLICY 18
#define SADB_EXT_MAX 18
#define SADB_SATYPE_UNSPEC 0
#define SADB_SATYPE_AH 2
#define SADB_SATYPE_ESP 3
#define SADB_SATYPE_RSVP 5
#define SADB_SATYPE_OSPFV2 6
#define SADB_SATYPE_RIPV2 7
#define SADB_SATYPE_MIP 8
#define SADB_X_SATYPE_IPCOMP 9
#define SADB_SATYPE_MAX 9
#define SADB_SASTATE_LARVAL 0
#define SADB_SASTATE_MATURE 1
#define SADB_SASTATE_DYING 2
#define SADB_SASTATE_DEAD 3
#define SADB_SASTATE_MAX 3
#define SADB_SAFLAGS_PFS 1
#define SADB_AALG_NONE 0
#define SADB_AALG_MD5HMAC 1 /* 2 */
#define SADB_AALG_SHA1HMAC 2 /* 3 */
#define SADB_AALG_MD5 3 /* Keyed MD5 */
#define SADB_AALG_SHA 4 /* Keyed SHA */
#define SADB_AALG_NULL 5 /* null authentication */
#define SADB_AALG_MAX 6
#define SADB_EALG_NONE 0
#define SADB_EALG_DESCBC 1 /* 2 */
#define SADB_EALG_3DESCBC 2 /* 3 */
#define SADB_EALG_NULL 3 /* 11 */
#define SADB_EALG_BLOWFISHCBC 4
#define SADB_EALG_CAST128CBC 5
#define SADB_EALG_RC5CBC 6
#define SADB_EALG_MAX 7
/*nonstandard */
#define SADB_X_CALG_NONE 0
#define SADB_X_CALG_OUI 1
#define SADB_X_CALG_DEFLATE 2
#define SADB_X_CALG_LZS 3
#define SADB_IDENTTYPE_RESERVED 0
#define SADB_IDENTTYPE_PREFIX 1
#define SADB_IDENTTYPE_FQDN 2
#define SADB_IDENTTYPE_USERFQDN 3
#define SADB_X_IDENTTYPE_ADDR 4
#define SADB_IDENTTYPE_MAX 4
/* `flags' in sadb_sa structure holds followings */
#define SADB_X_EXT_NONE 0x0000 /* i.e. new format. */
#define SADB_X_EXT_OLD 0x0001 /* old format. */
#define SADB_X_EXT_IV4B 0x0010 /* IV length of 4 bytes in use */
#define SADB_X_EXT_DERIV 0x0020 /* DES derived */
#define SADB_X_EXT_CYCSEQ 0x0040 /* allowing to cyclic sequence. */
/* three of followings are exclusive flags each them */
#define SADB_X_EXT_PSEQ 0x0000 /* sequencial padding for ESP */
#define SADB_X_EXT_PRAND 0x0100 /* random padding for ESP */
#define SADB_X_EXT_PZERO 0x0200 /* zero padding for ESP */
#define SADB_X_EXT_PMASK 0x0300 /* mask for padding flag */
#define SADB_X_EXT_RAWCPI 0x0080 /* use well known CPI (IPComp) */
#define SADB_KEY_FLAGS_MAX 0x0fff
/* SPI size for PF_KEYv2 */
#define PFKEY_SPI_SIZE sizeof(u_int32_t)
/* Identifier for menber of lifetime structure */
#define SADB_X_LIFETIME_ALLOCATIONS 0
#define SADB_X_LIFETIME_BYTES 1
#define SADB_X_LIFETIME_ADDTIME 2
#define SADB_X_LIFETIME_USETIME 3
/* The rate for SOFT lifetime against HARD one. */
#define PFKEY_SOFT_LIFETIME_RATE 80
/* Utilities */
#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
#define PFKEY_EXTLEN(msg) \
PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len)
#define PFKEY_ADDR_PREFIX(ext) \
(((struct sadb_address *)(ext))->sadb_address_prefixlen)
#define PFKEY_ADDR_PROTO(ext) \
(((struct sadb_address *)(ext))->sadb_address_proto)
#define PFKEY_ADDR_SADDR(ext) \
((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address)))
/* in 64bits */
#define PFKEY_UNUNIT64(a) ((a) << 3)
#define PFKEY_UNIT64(a) ((a) >> 3)
#ifndef KERNEL
extern void pfkey_sadump(struct sadb_msg *m);
extern void pfkey_spdump(struct sadb_msg *m);
struct sockaddr;
int ipsec_check_keylen __P((u_int supported, u_int alg_id, u_int keylen));
u_int pfkey_set_softrate __P((u_int type, u_int rate));
u_int pfkey_get_softrate __P((u_int type));
int pfkey_send_getspi __P((int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
u_int32_t min, u_int32_t max, u_int32_t seq));
int pfkey_send_update __P((int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
u_int32_t spi, u_int wsize, caddr_t keymat,
u_int e_type, u_int e_keylen, u_int a_type,
u_int a_keylen, u_int flags, u_int32_t l_alloc,
u_int64_t l_bytes, u_int64_t l_addtime,
u_int64_t l_usetime, u_int32_t seq));
int pfkey_send_add __P((int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
u_int32_t spi, u_int wsize, caddr_t keymat,
u_int e_type, u_int e_keylen, u_int a_type,
u_int a_keylen, u_int flags, u_int32_t l_alloc,
u_int64_t l_bytes, u_int64_t l_addtime,
u_int64_t l_usetime, u_int32_t seq));
int pfkey_send_delete __P((int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
u_int32_t spi));
int pfkey_send_get __P((int so, u_int satype, u_int mode,
struct sockaddr *src, struct sockaddr *dst,
u_int32_t spi));
int pfkey_send_register __P((int so, u_int satype));
int pfkey_recv_register __P((int so));
int pfkey_send_flush __P((int so, u_int satype));
int pfkey_send_dump __P((int so, u_int satype));
int pfkey_send_promisc_toggle __P((int so, int flag));
int pfkey_send_spdadd __P((int so, struct sockaddr *src, u_int prefs,
struct sockaddr *dst, u_int prefd, u_int proto,
caddr_t policy, int policylen, u_int32_t seq));
int pfkey_send_spddelete __P((int so, struct sockaddr *src, u_int prefs,
struct sockaddr *dst, u_int prefd, u_int proto, u_int32_t seq));
int pfkey_send_spdflush __P((int so));
int pfkey_send_spddump __P((int so));
int pfkey_open __P((void));
void pfkey_close __P((int so));
struct sadb_msg *pfkey_recv __P((int so));
int pfkey_send __P((int so, struct sadb_msg *msg, int len));
int pfkey_align __P((struct sadb_msg *msg, caddr_t *mhp));
int pfkey_check __P((caddr_t *mhp));
#endif /*!KERNEL*/
#endif /* __PFKEY_V2_H */
#endif /* _NET_PFKEYV2_H_ */

View file

@ -103,6 +103,16 @@ rtalloc_ign(ro, ignore)
ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore);
}
/* for INET6 */
void
rtcalloc(ro)
register struct route *ro;
{
if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
return; /* XXX */
ro->ro_rt = rtalloc1(&ro->ro_dst, RTF_CLONING, 0UL);
}
/*
* Look up the route that matches the address given
* Or, at least try.. Create a cloned route if needed.
@ -121,7 +131,7 @@ rtalloc1(dst, report, ignflags)
u_long nflags;
int s = splnet(), err = 0, msgtype = RTM_MISS;
/*
/*
* Look up the address in the table for that Address Family
*/
if (rnh && (rn = rnh->rnh_matchaddr((caddr_t)dst, rnh)) &&
@ -151,7 +161,7 @@ rtalloc1(dst, report, ignflags)
}
if ((rt = newrt) && (rt->rt_flags & RTF_XRESOLVE)) {
/*
* If the new route specifies it be
* If the new route specifies it be
* externally resolved, then go do that.
*/
msgtype = RTM_RESOLVE;
@ -216,7 +226,7 @@ rtfree(rt)
if (rt->rt_refcnt <= 0 && (rt->rt_flags & RTF_UP) == 0) {
if (rt->rt_nodes->rn_flags & (RNF_ACTIVE | RNF_ROOT))
panic ("rtfree 2");
/*
/*
* the rtentry must have been removed from the routing table
* so it is represented in rttrash.. remove that now.
*/
@ -229,7 +239,7 @@ rtfree(rt)
}
#endif
/*
/*
* release references on items we hold them on..
* e.g other routes and ifaddrs.
*/
@ -513,7 +523,7 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
*/
rt->rt_flags &= ~RTF_UP;
/*
/*
* give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
@ -593,6 +603,7 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
ifa->ifa_refcnt++;
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask,
rnh, rt->rt_nodes);
@ -607,7 +618,7 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
*/
rt2 = rtalloc1(dst, 0, RTF_PRCLONING);
if (rt2 && rt2->rt_parent) {
rtrequest(RTM_DELETE,
rtrequest(RTM_DELETE,
(struct sockaddr *)rt_key(rt2),
rt2->rt_gateway,
rt_mask(rt2), rt2->rt_flags, 0);
@ -638,9 +649,9 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
rt->rt_parent = 0;
/*
/*
* If we got here from RESOLVE, then we are cloning
* so clone the rest, and note that we
* so clone the rest, and note that we
* are a clone (and increment the parent's references)
*/
if (req == RTM_RESOLVE) {
@ -846,8 +857,8 @@ rt_setgate(rt0, dst, gate)
*/
Bcopy(gate, (rt->rt_gateway = (struct sockaddr *)(new + dlen)), glen);
/*
* if we are replacing the chunk (or it's new) we need to
/*
* if we are replacing the chunk (or it's new) we need to
* replace the dst as well
*/
if (old) {
@ -941,13 +952,15 @@ rtinit(ifa, cmd, flags)
* be confusing at best and possibly worse.
*/
if (cmd == RTM_DELETE) {
/*
/*
* It's a delete, so it should already exist..
* If it's a net, mask off the host bits
* (Assuming we have a mask)
*/
if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
m = m_get(M_WAIT, MT_SONAME);
m = m_get(M_DONTWAIT, MT_SONAME);
if (m == NULL)
return(ENOBUFS);
deldst = mtod(m, struct sockaddr *);
rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
dst = deldst;
@ -971,7 +984,7 @@ rtinit(ifa, cmd, flags)
* If the interface in the rtentry doesn't match
* the interface we are using, then we don't
* want to delete it, so return an error.
* This seems to be the only point of
* This seems to be the only point of
* this whole RTM_DELETE clause.
*/
if (m)
@ -983,7 +996,7 @@ rtinit(ifa, cmd, flags)
/* XXX */
#if 0
else {
/*
/*
* One would think that as we are deleting, and we know
* it doesn't exist, we could just return at this point
* with an "ELSE" clause, but apparently not..
@ -1025,7 +1038,7 @@ rtinit(ifa, cmd, flags)
*/
rt->rt_refcnt--;
/*
* If it came back with an unexpected interface, then it must
* If it came back with an unexpected interface, then it must
* have already existed or something. (XXX)
*/
if (rt->rt_ifa != ifa) {
@ -1038,7 +1051,7 @@ rtinit(ifa, cmd, flags)
*/
if (rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, SA(0));
/*
/*
* Remove the referenve to the it's ifaddr.
*/
IFAFREE(rt->rt_ifa);
@ -1048,6 +1061,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++;
/*
* Now ask the protocol to check if it needs

37
sys/netinet/icmp6.h Normal file
View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#ifndef _NETINET_ICMP6_H_
#define _NETINET_ICMP6_H_
#include <netinet6/icmp6.h>
#endif /* !_NETINET_ICMP6_H_ */

View file

@ -66,12 +66,12 @@ static void in_rtchange __P((struct inpcb *, int));
* These configure the range of local port addresses assigned to
* "unspecified" outgoing connections/packets/whatever.
*/
static int ipport_lowfirstauto = IPPORT_RESERVED - 1; /* 1023 */
static int ipport_lowlastauto = IPPORT_RESERVEDSTART; /* 600 */
static int ipport_firstauto = IPPORT_RESERVED; /* 1024 */
static int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */
static int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 49152 */
static int ipport_hilastauto = IPPORT_HILASTAUTO; /* 65535 */
int ipport_lowfirstauto = IPPORT_RESERVED - 1; /* 1023 */
int ipport_lowlastauto = IPPORT_RESERVEDSTART; /* 600 */
int ipport_firstauto = IPPORT_RESERVED; /* 1024 */
int ipport_lastauto = IPPORT_USERRESERVED; /* 5000 */
int ipport_hifirstauto = IPPORT_HIFIRSTAUTO; /* 49152 */
int ipport_hilastauto = IPPORT_HILASTAUTO; /* 65535 */
#define RANGECHK(var, min, max) \
if ((var) < (min)) { (var) = (min); } \
@ -204,7 +204,7 @@ in_pcbbind(inp, nam, p)
if (so->so_cred->cr_uid != 0 &&
!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
t = in_pcblookup_local(inp->inp_pcbinfo,
sin->sin_addr, lport,
sin->sin_addr, lport,
prison ? 0 : INPLOOKUP_WILDCARD);
if (t &&
(ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
@ -409,7 +409,7 @@ in_pcbladdr(inp, nam, plocal_sin)
imo = inp->inp_moptions;
if (imo->imo_multicast_ifp != NULL) {
ifp = imo->imo_multicast_ifp;
for (ia = in_ifaddrhead.tqh_first; ia;
for (ia = in_ifaddrhead.tqh_first; ia;
ia = ia->ia_link.tqe_next)
if (ia->ia_ifp == ifp)
break;

View file

@ -39,6 +39,12 @@
#include <sys/queue.h>
#include <netinet6/ipsec.h> /* for IPSEC */
#define in6pcb inpcb /* for KAME src sync over BSD*'s */
#define in6p_sp inp_sp /* for KAME src sync over BSD*'s */
/*
* Common structure pcb for internet protocol implementation.
* Here are stored pointers to local and foreign host table
@ -50,33 +56,112 @@ LIST_HEAD(inpcbhead, inpcb);
LIST_HEAD(inpcbporthead, inpcbport);
typedef u_quad_t inp_gen_t;
/*
* PCB with AF_INET6 null bind'ed laddr can receive AF_INET input packet.
* So, AF_INET6 null laddr is also used as AF_INET null laddr,
* by utilize following structure. (At last, same as INRIA)
*/
struct in_addr_4in6 {
u_int32_t ia46_pad32[3];
struct in_addr ia46_addr4;
};
/*
* NB: the zone allocator is type-stable EXCEPT FOR THE FIRST TWO LONGS
* of the structure. Therefore, it is important that the members in
* that position not contain any information which is required to be
* stable.
*/
struct icmp6_filter;
struct inpcb {
LIST_ENTRY(inpcb) inp_hash; /* hash list */
struct in_addr inp_faddr; /* foreign host table entry */
struct in_addr inp_laddr; /* local host table entry */
LIST_ENTRY(inpcb) inp_hash; /* hash list */
u_short inp_fport; /* foreign port */
u_short inp_lport; /* local port */
LIST_ENTRY(inpcb) inp_list; /* list for all PCBs of this proto */
LIST_ENTRY(inpcb) inp_list; /* list for all PCBs of this proto */
u_int32_t inp_flow;
/* protocol dependent part, local and foreign addr */
union {
/* foreign host table entry */
struct in_addr_4in6 inp46_foreign;
struct in6_addr inp6_foreign;
} inp_dependfaddr;
union {
/* local host table entry */
struct in_addr_4in6 inp46_local;
struct in6_addr inp6_local;
} inp_dependladdr;
caddr_t inp_ppcb; /* pointer to per-protocol pcb */
struct inpcbinfo *inp_pcbinfo; /* PCB list info */
struct socket *inp_socket; /* back pointer to socket */
struct mbuf *inp_options; /* IP options */
struct route inp_route; /* placeholder for routing entry */
/* list for this PCB's local port */
int inp_flags; /* generic IP/datagram flags */
u_char inp_ip_tos; /* type of service proto */
/* protocol dependent part; cached route */
union {
/* placeholder for routing entry */
struct route inp4_route;
struct route_in6 inp6_route;
} inp_dependroute;
struct inpcbpolicy *inp_sp; /* for IPSEC */
u_char inp_vflag;
#define INP_IPV4 0x1
#define INP_IPV6 0x2
u_char inp_ip_ttl; /* time to live proto */
u_char inp_ip_p; /* protocol proto */
u_char pad[1]; /* alignment */
struct ip_moptions *inp_moptions; /* IP multicast options */
LIST_ENTRY(inpcb) inp_portlist; /* list for this PCB's local port */
/* protocol dependent part; options */
struct {
u_char inp4_ip_tos; /* type of service proto */
struct mbuf *inp4_options; /* IP options */
struct ip_moptions *inp4_moptions; /* IP multicast options */
} inp_depend4;
#define inp_faddr inp_dependfaddr.inp46_foreign.ia46_addr4
#define inp_laddr inp_dependladdr.inp46_local.ia46_addr4
#define inp_route inp_dependroute.inp4_route
#define inp_ip_tos inp_depend4.inp4_ip_tos
#define inp_options inp_depend4.inp4_options
#define inp_moptions inp_depend4.inp4_moptions
struct {
/* IP options */
struct mbuf *inp6_options;
/* IP6 options for outgoing packets */
struct ip6_pktopts *inp6_outputopts;
/* IP multicast options */
struct ip6_moptions *inp6_moptions;
/* ICMPv6 code type filter */
struct icmp6_filter *inp6_icmp6filt;
/* IPV6_CHECKSUM setsockopt */
int inp6_cksum;
u_short inp6_ifindex;
short inp6_hops;
u_int8_t inp6_hlim;
} inp_depend6;
LIST_ENTRY(inpcb) inp_portlist;
struct inpcbport *inp_phd; /* head of this list */
inp_gen_t inp_gencnt; /* generation count of this instance */
inp_gen_t inp_gencnt; /* generation count of this instance */
#define in6p_faddr inp_dependfaddr.inp6_foreign
#define in6p_laddr inp_dependladdr.inp6_local
#define in6p_route inp_dependroute.inp6_route
#define in6p_ip6_hlim inp_depend6.inp6_hlim
#define in6p_hops inp_depend6.inp6_hops /* default hop limit */
#define in6p_ip6_nxt inp_ip_p
#define in6p_flowinfo inp_flow
#define in6p_vflag inp_vflag
#define in6p_options inp_depend6.inp6_options
#define in6p_outputopts inp_depend6.inp6_outputopts
#define in6p_moptions inp_depend6.inp6_moptions
#define in6p_icmp6filt inp_depend6.inp6_icmp6filt
#define in6p_cksum inp_depend6.inp6_cksum
#define inp6_ifindex inp_depend6.inp6_ifindex
#define in6p_flags inp_flags /* for KAME src sync over BSD*'s */
#define in6p_socket inp_socket /* for KAME src sync over BSD*'s */
#define in6p_lport inp_lport /* for KAME src sync over BSD*'s */
#define in6p_fport inp_fport /* for KAME src sync over BSD*'s */
#define in6p_ppcb inp_ppcb /* for KAME src sync over BSD*'s */
};
/*
* The range of the generation count, as used in this implementation,
@ -140,14 +225,54 @@ struct inpcbinfo { /* XXX documentation, prefixes */
#define INP_ANONPORT 0x40 /* port chosen for user */
#define INP_RECVIF 0x80 /* receive incoming interface */
#define INP_MTUDISC 0x100 /* user can do MTU discovery */
#define INP_FAITH 0x200 /* accept FAITH'ed connections */
#define IN6P_PKTINFO 0x010000
#define IN6P_HOPLIMIT 0x020000
#define IN6P_NEXTHOP 0x040000
#define IN6P_HOPOPTS 0x080000
#define IN6P_DSTOPTS 0x100000
#define IN6P_RTHDR 0x200000
#define IN6P_BINDV6ONLY 0x400000
#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\
INP_RECVIF)
INP_RECVIF|\
IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_NEXTHOP|\
IN6P_HOPOPTS|IN6P_DSTOPTS|IN6P_RTHDR)
#define INP_UNMAPPABLEOPTS (IN6P_HOPOPTS|IN6P_DSTOPTS|IN6P_RTHDR)
/* for KAME src sync over BSD*'s */
#define IN6P_RECVOPTS INP_RECVOPTS
#define IN6P_RECVRETOPTS INP_RECVRETOPTS
#define IN6P_RECVDSTADDR INP_RECVDSTADDR
#define IN6P_HDRINCL INP_HDRINCL
#define IN6P_HIGHPORT INP_HIGHPORT
#define IN6P_LOWPORT INP_LOWPORT
#define IN6P_ANONPORT INP_ANONPORT
#define IN6P_RECVIF INP_RECVIF
#define IN6P_MTUDISC INP_MTUDISC
#define IN6P_FAITH INP_FAITH
#define IN6P_CONTROLOPTS INP_CONTROLOPTS
/*
* socket AF version is {newer than,or include}
* actual datagram AF version
*/
#define INPLOOKUP_WILDCARD 1
#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
#define sotoin6pcb(so) sotoinpcb(so) /* for KAME src sync over BSD*'s */
#define INP_SOCKAF(so) so->so_proto->pr_domain->dom_family
#define INP_CHECK_SOCKAF(so, af) (INP_SOCKAF(so) == af)
#ifdef KERNEL
extern int ipport_lowfirstauto;
extern int ipport_lowlastauto;
extern int ipport_firstauto;
extern int ipport_lastauto;
extern int ipport_hifirstauto;
extern int ipport_hilastauto;
void in_losing __P((struct inpcb *));
int in_pcballoc __P((struct socket *, struct inpcbinfo *, struct proc *));
int in_pcbbind __P((struct inpcb *, struct sockaddr *, struct proc *));

32
sys/netinet/ip6.h Normal file
View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#include <netinet6/ip6.h>

View file

@ -66,8 +66,8 @@
#include <netinet/ip_dummynet.h>
#endif
static struct inpcbhead ripcb;
static struct inpcbinfo ripcbinfo;
struct inpcbhead ripcb;
struct inpcbinfo ripcbinfo;
/*
* Nominal space allocated to a raw ip socket.
@ -202,7 +202,7 @@ rip_output(m, so, dst)
ip = mtod(m, struct ip *);
/* don't allow both user specified and setsockopt options,
and don't allow packet length sizes that will crash */
if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
if (((IP_VHL_HL(ip->ip_vhl) != (sizeof (*ip) >> 2))
&& inp->inp_options)
|| (ip->ip_len > m->m_pkthdr.len)
|| (ip->ip_len < (IP_VHL_HL(ip->ip_vhl) << 2))) {
@ -411,12 +411,12 @@ rip_ctlinput(cmd, sa, vip)
}
}
static u_long rip_sendspace = RIPSNDQ;
static u_long rip_recvspace = RIPRCVQ;
u_long rip_sendspace = RIPSNDQ;
u_long rip_recvspace = RIPRCVQ;
SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,
SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,
&rip_sendspace, 0, "Maximum outgoing raw IP datagram size");
SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,
SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,
&rip_recvspace, 0, "Maximum incoming raw IP datagram size");
static int
@ -632,6 +632,6 @@ struct pr_usrreqs rip_usrreqs = {
rip_abort, pru_accept_notsupp, rip_attach, rip_bind, rip_connect,
pru_connect2_notsupp, in_control, rip_detach, rip_disconnect,
pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,
pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown,
pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown,
in_setsockaddr, sosend, soreceive, sopoll
};

View file

@ -35,6 +35,7 @@
*/
#include "opt_compat.h"
#include "opt_inet.h"
#include "opt_tcpdebug.h"
#include <sys/param.h>

View file

@ -35,6 +35,7 @@
*/
#include "opt_compat.h"
#include "opt_inet.h"
#include "opt_tcpdebug.h"
#include <sys/param.h>

108
sys/netinet6/dest6.c Normal file
View file

@ -0,0 +1,108 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/icmp6.h>
/*
* Destination options header processing.
*/
int
dest6_input(mp, offp, proto)
struct mbuf **mp;
int *offp, proto;
{
register struct mbuf *m = *mp;
int off = *offp, dstoptlen, optlen;
struct ip6_dest *dstopts;
u_int8_t *opt;
/* validation of the length of the header */
IP6_EXTHDR_CHECK(m, off, sizeof(*dstopts), IPPROTO_DONE);
dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
dstoptlen = (dstopts->ip6d_len + 1) << 3;
IP6_EXTHDR_CHECK(m, off, dstoptlen, IPPROTO_DONE);
dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
off += dstoptlen;
dstoptlen -= sizeof(struct ip6_dest);
opt = (u_int8_t *)dstopts + sizeof(struct ip6_dest);
/* search header for all options. */
for (optlen = 0; dstoptlen > 0; dstoptlen -= optlen, opt += optlen) {
switch(*opt) {
case IP6OPT_PAD1:
optlen = 1;
break;
case IP6OPT_PADN:
if (dstoptlen < IP6OPT_MINLEN) {
ip6stat.ip6s_toosmall++;
goto bad;
}
optlen = *(opt + 1) + 2;
break;
default: /* unknown option */
if (dstoptlen < IP6OPT_MINLEN) {
ip6stat.ip6s_toosmall++;
goto bad;
}
if ((optlen = ip6_unknown_opt(opt, m,
opt-mtod(m, u_int8_t *))) == -1)
return(IPPROTO_DONE);
optlen += 2;
break;
}
}
*offp = off;
return(dstopts->ip6d_nxt);
bad:
m_freem(m);
return(IPPROTO_DONE);
}

573
sys/netinet6/frag6.c Normal file
View file

@ -0,0 +1,573 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/syslog.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/icmp6.h>
#include <net/net_osdep.h>
/*
* Define it to get a correct behavior on per-interface statistics.
* You will need to perform an extra routing table lookup, per fragment,
* to do it. This may, or may not be, a performance hit.
*/
#define IN6_IFSTAT_STRICT
static void frag6_enq __P((struct ip6asfrag *, struct ip6asfrag *));
static void frag6_deq __P((struct ip6asfrag *));
static void frag6_insque __P((struct ip6q *, struct ip6q *));
static void frag6_remque __P((struct ip6q *));
static void frag6_freef __P((struct ip6q *));
int frag6_doing_reass;
u_int frag6_nfragpackets;
struct ip6q ip6q; /* ip6 reassemble queue */
#if !defined(M_FTABLE)
MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header");
#endif
/*
* Initialise reassembly queue and fragment identifier.
*/
void
frag6_init()
{
struct timeval tv;
/*
* in many cases, random() here does NOT return random number
* as initialization during bootstrap time occur in fixed order.
*/
microtime(&tv);
ip6q.ip6q_next = ip6q.ip6q_prev = &ip6q;
ip6_id = random() ^ tv.tv_usec;
}
/*
* Fragment input
*/
int
frag6_input(mp, offp, proto)
struct mbuf **mp;
int *offp, proto;
{
struct mbuf *m = *mp, *t;
struct ip6_hdr *ip6;
struct ip6_frag *ip6f;
struct ip6q *q6;
struct ip6asfrag *af6, *ip6af;
int offset = *offp, nxt, i, next;
int first_frag = 0;
u_short fragoff, frgpartlen;
struct ifnet *dstifp;
#ifdef IN6_IFSTAT_STRICT
static struct route_in6 ro;
struct sockaddr_in6 *dst;
#endif
IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), IPPROTO_DONE);
ip6 = mtod(m, struct ip6_hdr *);
ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset);
dstifp = NULL;
#ifdef IN6_IFSTAT_STRICT
/* find the destination interface of the packet. */
dst = (struct sockaddr_in6 *)&ro.ro_dst;
if (ro.ro_rt
&& ((ro.ro_rt->rt_flags & RTF_UP) == 0
|| !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst))) {
RTFREE(ro.ro_rt);
ro.ro_rt = (struct rtentry *)0;
}
if (ro.ro_rt == NULL) {
bzero(dst, sizeof(*dst));
dst->sin6_family = AF_INET6;
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_addr = ip6->ip6_dst;
}
rtcalloc((struct route *)&ro);
if (ro.ro_rt != NULL && ro.ro_rt->rt_ifa != NULL)
dstifp = ((struct in6_ifaddr *)ro.ro_rt->rt_ifa)->ia_ifp;
#else
/* we are violating the spec, this is not the destination interface */
if ((m->m_flags & M_PKTHDR) != 0)
dstifp = m->m_pkthdr.rcvif;
#endif
/* jumbo payload can't contain a fragment header */
if (ip6->ip6_plen == 0) {
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, offset);
in6_ifstat_inc(dstifp, ifs6_reass_fail);
return IPPROTO_DONE;
}
/*
* check whether fragment packet's fragment length is
* multiple of 8 octets.
* sizeof(struct ip6_frag) == 8
* sizeof(struct ip6_hdr) = 40
*/
if ((ip6f->ip6f_offlg & IP6F_MORE_FRAG) &&
(((ntohs(ip6->ip6_plen) - offset) & 0x7) != 0)) {
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER,
(caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
in6_ifstat_inc(dstifp, ifs6_reass_fail);
return IPPROTO_DONE;
}
ip6stat.ip6s_fragments++;
in6_ifstat_inc(dstifp, ifs6_reass_reqd);
/*
* Presence of header sizes in mbufs
* would confuse code below.
*/
offset += sizeof(struct ip6_frag);
m->m_data += offset;
m->m_len -= offset;
for (q6 = ip6q.ip6q_next; q6 != &ip6q; q6 = q6->ip6q_next)
if (ip6f->ip6f_ident == q6->ip6q_ident &&
IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &q6->ip6q_src) &&
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &q6->ip6q_dst))
break;
if (q6 == &ip6q) {
/*
* the first fragment to arrive, create a reassembly queue.
*/
first_frag = 1;
frag6_nfragpackets++;
/*
* Enforce upper bound on number of fragmented packets
* for which we attempt reassembly;
* If maxfrag is 0, never accept fragments.
* If maxfrag is -1, accept all fragments without limitation.
*/
if (frag6_nfragpackets >= (u_int)ip6_maxfragpackets) {
ip6stat.ip6s_fragoverflow++;
in6_ifstat_inc(dstifp, ifs6_reass_fail);
frag6_freef(ip6q.ip6q_prev);
}
q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE,
M_DONTWAIT);
if (q6 == NULL)
goto dropfrag;
frag6_insque(q6, &ip6q);
q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6;
q6->ip6q_ident = ip6f->ip6f_ident;
q6->ip6q_arrive = 0; /* Is it used anywhere? */
q6->ip6q_ttl = IPV6_FRAGTTL;
q6->ip6q_src = ip6->ip6_src;
q6->ip6q_dst = ip6->ip6_dst;
q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */
}
/*
* If it's the 1st fragment, record the length of the
* unfragmentable part and the next header of the fragment header.
*/
fragoff = ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK);
if (fragoff == 0) {
q6->ip6q_unfrglen = offset - sizeof(struct ip6_hdr)
- sizeof(struct ip6_frag);
q6->ip6q_nxt = ip6f->ip6f_nxt;
}
/*
* Check that the reassembled packet would not exceed 65535 bytes
* in size.
* If it would exceed, discard the fragment and return an ICMP error.
*/
frgpartlen = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) - offset;
if (q6->ip6q_unfrglen >= 0) {
/* The 1st fragment has already arrived. */
if (q6->ip6q_unfrglen + fragoff + frgpartlen > IPV6_MAXPACKET) {
m->m_data -= offset;
m->m_len += offset;
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) + 2);
return(IPPROTO_DONE);
}
}
else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
m->m_data -= offset;
m->m_len += offset;
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) + 2);
return(IPPROTO_DONE);
}
/*
* If it's the first fragment, do the above check for each
* fragment already stored in the reassembly queue.
*/
if (fragoff == 0) {
struct ip6asfrag *af6dwn;
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = af6dwn) {
af6dwn = af6->ip6af_down;
if (q6->ip6q_unfrglen + af6->ip6af_off + af6->ip6af_frglen >
IPV6_MAXPACKET) {
struct mbuf *merr = IP6_REASS_MBUF(af6);
struct ip6_hdr *ip6err;
int erroff = af6->ip6af_offset;
/* dequeue the fragment. */
frag6_deq(af6);
/* adjust pointer. */
merr->m_data -= af6->ip6af_offset;
merr->m_len += af6->ip6af_offset;
ip6err = mtod(merr, struct ip6_hdr *);
/*
* Restore source and destination addresses
* in the erroneous IPv6 header.
*/
ip6err->ip6_src = q6->ip6q_src;
ip6err->ip6_dst = q6->ip6q_dst;
icmp6_error(merr, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_HEADER,
erroff - sizeof(struct ip6_frag) + 2);
}
}
}
/* Override the IPv6 header */
ip6af = (struct ip6asfrag *)ip6;
ip6af->ip6af_mff = ip6f->ip6f_offlg & IP6F_MORE_FRAG;
ip6af->ip6af_off = fragoff;
ip6af->ip6af_frglen = frgpartlen;
ip6af->ip6af_offset = offset;
IP6_REASS_MBUF(ip6af) = m;
if (first_frag) {
af6 = (struct ip6asfrag *)q6;
goto insert;
}
/*
* Find a segment which begins after this one does.
*/
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = af6->ip6af_down)
if (af6->ip6af_off > ip6af->ip6af_off)
break;
/*
* If the incoming framgent overlaps some existing fragments in
* the reassembly queue, drop it, since it is dangerous to override
* existing fragments from a security point of view.
*/
if (af6->ip6af_up != (struct ip6asfrag *)q6) {
i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
- ip6af->ip6af_off;
if (i > 0) {
log(LOG_ERR, "%d bytes of a fragment from %s "
"overlaps the previous fragment\n",
i, ip6_sprintf(&q6->ip6q_src));
goto dropfrag;
}
}
if (af6 != (struct ip6asfrag *)q6) {
i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
if (i > 0) {
log(LOG_ERR, "%d bytes of a fragment from %s "
"overlaps the succeeding fragment",
i, ip6_sprintf(&q6->ip6q_src));
goto dropfrag;
}
}
insert:
/*
* Stick new segment in its place;
* check for complete reassembly.
* Move to front of packet queue, as we are
* the most recently active fragmented packet.
*/
frag6_enq(ip6af, af6->ip6af_up);
next = 0;
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = af6->ip6af_down) {
if (af6->ip6af_off != next) {
frag6_doing_reass = 0;
return IPPROTO_DONE;
}
next += af6->ip6af_frglen;
}
if (af6->ip6af_up->ip6af_mff) {
frag6_doing_reass = 0;
return IPPROTO_DONE;
}
/*
* Reassembly is complete; concatenate fragments.
*/
ip6af = q6->ip6q_down;
t = m = IP6_REASS_MBUF(ip6af);
af6 = ip6af->ip6af_down;
while (af6 != (struct ip6asfrag *)q6) {
while (t->m_next)
t = t->m_next;
t->m_next = IP6_REASS_MBUF(af6);
af6 = af6->ip6af_down;
}
/* adjust offset to point where the original next header starts */
offset = ip6af->ip6af_offset - sizeof(struct ip6_frag);
ip6 = (struct ip6_hdr *)ip6af;
ip6->ip6_plen = htons((u_short)next + offset - sizeof(struct ip6_hdr));
ip6->ip6_src = q6->ip6q_src;
ip6->ip6_dst = q6->ip6q_dst;
nxt = q6->ip6q_nxt;
/*
* Delete frag6 header with as a few cost as possible.
*/
if (offset < m->m_len)
ovbcopy((caddr_t)ip6, (caddr_t)ip6 + sizeof(struct ip6_frag),
offset);
else {
ovbcopy(mtod(m, caddr_t), (caddr_t)ip6 + offset, m->m_len);
m->m_data -= sizeof(struct ip6_frag);
}
m->m_data -= offset;
m->m_len += offset;
/*
* Store NXT to the original.
*/
{
char *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */
*prvnxtp = nxt;
}
frag6_remque(q6);
free(q6, M_FTABLE);
frag6_nfragpackets--;
if (m->m_flags & M_PKTHDR) { /* Isn't it always true? */
int plen = 0;
for (t = m; t; t = t->m_next)
plen += t->m_len;
m->m_pkthdr.len = plen;
}
ip6stat.ip6s_reassembled++;
in6_ifstat_inc(dstifp, ifs6_reass_ok);
/*
* Tell launch routine the next header
*/
*mp = m;
*offp = offset;
frag6_doing_reass = 0;
return nxt;
dropfrag:
in6_ifstat_inc(dstifp, ifs6_reass_fail);
ip6stat.ip6s_fragdropped++;
m_freem(m);
return IPPROTO_DONE;
}
/*
* Free a fragment reassembly header and all
* associated datagrams.
*/
void
frag6_freef(q6)
struct ip6q *q6;
{
struct ip6asfrag *af6, *down6;
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = down6) {
struct mbuf *m = IP6_REASS_MBUF(af6);
down6 = af6->ip6af_down;
frag6_deq(af6);
/*
* Return ICMP time exceeded error for the 1st fragment.
* Just free other fragments.
*/
if (af6->ip6af_off == 0) {
struct ip6_hdr *ip6;
/* adjust pointer */
m->m_data -= af6->ip6af_offset;
m->m_len += af6->ip6af_offset;
ip6 = mtod(m, struct ip6_hdr *);
/* restoure source and destination addresses */
ip6->ip6_src = q6->ip6q_src;
ip6->ip6_dst = q6->ip6q_dst;
icmp6_error(m, ICMP6_TIME_EXCEEDED,
ICMP6_TIME_EXCEED_REASSEMBLY, 0);
}
else
m_freem(m);
}
frag6_remque(q6);
free(q6, M_FTABLE);
frag6_nfragpackets--;
}
/*
* Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure.
*/
void
frag6_enq(af6, up6)
struct ip6asfrag *af6, *up6;
{
af6->ip6af_up = up6;
af6->ip6af_down = up6->ip6af_down;
up6->ip6af_down->ip6af_up = af6;
up6->ip6af_down = af6;
}
/*
* To frag6_enq as remque is to insque.
*/
void
frag6_deq(af6)
struct ip6asfrag *af6;
{
af6->ip6af_up->ip6af_down = af6->ip6af_down;
af6->ip6af_down->ip6af_up = af6->ip6af_up;
}
void
frag6_insque(new, old)
struct ip6q *new, *old;
{
new->ip6q_prev = old;
new->ip6q_next = old->ip6q_next;
old->ip6q_next->ip6q_prev= new;
old->ip6q_next = new;
}
void
frag6_remque(p6)
struct ip6q *p6;
{
p6->ip6q_prev->ip6q_next = p6->ip6q_next;
p6->ip6q_next->ip6q_prev = p6->ip6q_prev;
}
/*
* IP timer processing;
* if a timer expires on a reassembly
* queue, discard it.
*/
void
frag6_slowtimo()
{
struct ip6q *q6;
int s = splnet();
frag6_doing_reass = 1;
q6 = ip6q.ip6q_next;
if (q6)
while (q6 != &ip6q) {
--q6->ip6q_ttl;
q6 = q6->ip6q_next;
if (q6->ip6q_prev->ip6q_ttl == 0) {
ip6stat.ip6s_fragtimeout++;
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
frag6_freef(q6->ip6q_prev);
}
}
/*
* If we are over the maximum number of fragments
* (due to the limit being lowered), drain off
* enough to get down to the new limit.
*/
while (frag6_nfragpackets > (u_int)ip6_maxfragpackets) {
ip6stat.ip6s_fragoverflow++;
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
frag6_freef(ip6q.ip6q_prev);
}
frag6_doing_reass = 0;
splx(s);
}
/*
* Drain off all datagram fragments.
*/
void
frag6_drain()
{
if (frag6_doing_reass)
return;
while (ip6q.ip6q_next != &ip6q) {
ip6stat.ip6s_fragdropped++;
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
frag6_freef(ip6q.ip6q_next);
}
}

1868
sys/netinet6/icmp6.c Normal file

File diff suppressed because it is too large Load diff

602
sys/netinet6/icmp6.h Normal file
View file

@ -0,0 +1,602 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
*/
#ifndef _NETINET6_ICMPV6_H_
#define _NETINET6_ICMPV6_H_
#define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr)
- sizeof(struct icmp6_hdr) */
struct icmp6_hdr {
u_int8_t icmp6_type; /* type field */
u_int8_t icmp6_code; /* code field */
u_int16_t icmp6_cksum; /* checksum field */
union {
u_int32_t icmp6_un_data32[1]; /* type-specific field */
u_int16_t icmp6_un_data16[2]; /* type-specific field */
u_int8_t icmp6_un_data8[4]; /* type-specific field */
} icmp6_dataun;
};
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
#define icmp6_mtu icmp6_data32[0] /* packet too big */
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */
#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */
#define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */
#define ICMP6_PARAM_PROB 4 /* ip6 header bad */
#define ICMP6_ECHO_REQUEST 128 /* echo service */
#define ICMP6_ECHO_REPLY 129 /* echo reply */
#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */
#define MLD6_LISTENER_QUERY 130 /* multicast listener query */
#define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */
#define MLD6_LISTENER_REPORT 131 /* multicast listener report */
#define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */
#define MLD6_LISTENER_DONE 132 /* multicast listener done */
#define ND_ROUTER_SOLICIT 133 /* router solicitation */
#define ND_ROUTER_ADVERT 134 /* router advertisment */
#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */
#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisment */
#define ND_REDIRECT 137 /* redirect */
#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */
#define ICMP6_WRUREQUEST 139 /* who are you request */
#define ICMP6_WRUREPLY 140 /* who are you reply */
#define ICMP6_FQDN_QUERY 139 /* FQDN query */
#define ICMP6_FQDN_REPLY 140 /* FQDN reply */
#define ICMP6_NI_QUERY 139 /* node information request */
#define ICMP6_NI_REPLY 140 /* node information reply */
/* The definitions below are experimental. TBA */
#define MLD6_MTRACE_RESP 141 /* mtrace response(to sender) */
#define MLD6_MTRACE 142 /* mtrace messages */
#define ICMP6_MAXTYPE 142
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */
#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */
#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */
#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */
#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
#define ICMP6_NI_SUCESS 0 /* node information successful reply */
#define ICMP6_NI_REFUSED 1 /* node information request is refused */
#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */
#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */
#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */
#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */
/* Used in kernel only */
#define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */
#define ND_REDIRECT_ROUTER 1 /* redirect to a better router */
/*
* Multicast Listener Discovery
*/
struct mld6_hdr {
struct icmp6_hdr mld6_hdr;
struct in6_addr mld6_addr; /* multicast address */
};
#define mld6_type mld6_hdr.icmp6_type
#define mld6_code mld6_hdr.icmp6_code
#define mld6_cksum mld6_hdr.icmp6_cksum
#define mld6_maxdelay mld6_hdr.icmp6_data16[0]
#define mld6_reserved mld6_hdr.icmp6_data16[1]
/*
* Neighbor Discovery
*/
struct nd_router_solicit { /* router solicitation */
struct icmp6_hdr nd_rs_hdr;
/* could be followed by options */
};
#define nd_rs_type nd_rs_hdr.icmp6_type
#define nd_rs_code nd_rs_hdr.icmp6_code
#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
struct nd_router_advert { /* router advertisement */
struct icmp6_hdr nd_ra_hdr;
u_int32_t nd_ra_reachable; /* reachable time */
u_int32_t nd_ra_retransmit; /* retransmit timer */
/* could be followed by options */
};
#define nd_ra_type nd_ra_hdr.icmp6_type
#define nd_ra_code nd_ra_hdr.icmp6_code
#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
#define ND_RA_FLAG_MANAGED 0x80
#define ND_RA_FLAG_OTHER 0x40
#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
struct nd_neighbor_solicit { /* neighbor solicitation */
struct icmp6_hdr nd_ns_hdr;
struct in6_addr nd_ns_target; /*target address */
/* could be followed by options */
};
#define nd_ns_type nd_ns_hdr.icmp6_type
#define nd_ns_code nd_ns_hdr.icmp6_code
#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
struct nd_neighbor_advert { /* neighbor advertisement */
struct icmp6_hdr nd_na_hdr;
struct in6_addr nd_na_target; /* target address */
/* could be followed by options */
};
#define nd_na_type nd_na_hdr.icmp6_type
#define nd_na_code nd_na_hdr.icmp6_code
#define nd_na_cksum nd_na_hdr.icmp6_cksum
#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
#if BYTE_ORDER == BIG_ENDIAN
#define ND_NA_FLAG_ROUTER 0x80000000
#define ND_NA_FLAG_SOLICITED 0x40000000
#define ND_NA_FLAG_OVERRIDE 0x20000000
#elif BYTE_ORDER == LITTLE_ENDIAN
#define ND_NA_FLAG_ROUTER 0x80
#define ND_NA_FLAG_SOLICITED 0x40
#define ND_NA_FLAG_OVERRIDE 0x20
#endif
struct nd_redirect { /* redirect */
struct icmp6_hdr nd_rd_hdr;
struct in6_addr nd_rd_target; /* target address */
struct in6_addr nd_rd_dst; /* destination address */
/* could be followed by options */
};
#define nd_rd_type nd_rd_hdr.icmp6_type
#define nd_rd_code nd_rd_hdr.icmp6_code
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
struct nd_opt_hdr { /* Neighbor discovery option header */
u_int8_t nd_opt_type;
u_int8_t nd_opt_len;
/* followed by option specific data*/
};
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#define ND_OPT_PREFIX_INFORMATION 3
#define ND_OPT_REDIRECTED_HEADER 4
#define ND_OPT_MTU 5
struct nd_opt_prefix_info { /* prefix information */
u_int8_t nd_opt_pi_type;
u_int8_t nd_opt_pi_len;
u_int8_t nd_opt_pi_prefix_len;
u_int8_t nd_opt_pi_flags_reserved;
u_int32_t nd_opt_pi_valid_time;
u_int32_t nd_opt_pi_preferred_time;
u_int32_t nd_opt_pi_reserved2;
struct in6_addr nd_opt_pi_prefix;
};
#define ND_OPT_PI_FLAG_ONLINK 0x80
#define ND_OPT_PI_FLAG_AUTO 0x40
struct nd_opt_rd_hdr { /* redirected header */
u_int8_t nd_opt_rh_type;
u_int8_t nd_opt_rh_len;
u_int16_t nd_opt_rh_reserved1;
u_int32_t nd_opt_rh_reserved2;
/* followed by IP header and data */
};
struct nd_opt_mtu { /* MTU option */
u_int8_t nd_opt_mtu_type;
u_int8_t nd_opt_mtu_len;
u_int16_t nd_opt_mtu_reserved;
u_int32_t nd_opt_mtu_mtu;
};
/*
* icmp6 namelookup
*/
struct icmp6_namelookup {
struct icmp6_hdr icmp6_nl_hdr;
u_int64_t icmp6_nl_nonce;
u_int32_t icmp6_nl_ttl;
/* could be followed by options */
};
/*
* icmp6 node information
*/
struct icmp6_nodeinfo {
struct icmp6_hdr icmp6_ni_hdr;
u_int64_t icmp6_ni_nonce;
/* could be followed by reply data */
};
#define ni_type icmp6_ni_hdr.icmp6_type
#define ni_code icmp6_ni_hdr.icmp6_code
#define ni_cksum icmp6_ni_hdr.icmp6_cksum
#define ni_qtype icmp6_ni_hdr.icmp6_data16[0]
#define ni_flags icmp6_ni_hdr.icmp6_data16[1]
#define NI_QTYPE_NOOP 0 /* NOOP */
#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */
#define NI_QTYPE_FQDN 2 /* FQDN */
#define NI_QTYPE_NODEADDR 3 /* Node Addresses. XXX: spec says 2, but it may be a typo... */
#if BYTE_ORDER == BIG_ENDIAN
#define NI_SUPTYPE_FLAG_COMPRESS 0x1
#define NI_FQDN_FLAG_VALIDTTL 0x1
#define NI_NODEADDR_FLAG_LINKLOCAL 0x1
#define NI_NODEADDR_FLAG_SITELOCAL 0x2
#define NI_NODEADDR_FLAG_GLOBAL 0x4
#define NI_NODEADDR_FLAG_ALL 0x8
#define NI_NODEADDR_FLAG_TRUNCATE 0x10
#define NI_NODEADDR_FLAG_ANYCAST 0x20 /* just experimental. not in spec */
#elif BYTE_ORDER == LITTLE_ENDIAN
#define NI_SUPTYPE_FLAG_COMPRESS 0x0100
#define NI_FQDN_FLAG_VALIDTTL 0x0100
#define NI_NODEADDR_FLAG_LINKLOCAL 0x0100
#define NI_NODEADDR_FLAG_SITELOCAL 0x0200
#define NI_NODEADDR_FLAG_GLOBAL 0x0400
#define NI_NODEADDR_FLAG_ALL 0x0800
#define NI_NODEADDR_FLAG_TRUNCATE 0x1000
#define NI_NODEADDR_FLAG_ANYCAST 0x2000 /* just experimental. not in spec */
#endif
struct ni_reply_fqdn {
u_int32_t ni_fqdn_ttl; /* TTL */
u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */
u_int8_t ni_fqdn_name[3]; /* XXX: alignment */
};
/*
* Router Renumbering. as router-renum-08.txt
*/
struct icmp6_router_renum { /* router renumbering header */
struct icmp6_hdr rr_hdr;
u_int8_t rr_segnum;
u_int8_t rr_flags;
u_int16_t rr_maxdelay;
u_int32_t rr_reserved;
};
#define ICMP6_RR_FLAGS_SEGNUM 0x80
#define ICMP6_RR_FLAGS_TEST 0x40
#define ICMP6_RR_FLAGS_REQRESULT 0x20
#define ICMP6_RR_FLAGS_FORCEAPPLY 0x10
#define ICMP6_RR_FLAGS_SPECSITE 0x08
#define ICMP6_RR_FLAGS_PREVDONE 0x04
#define rr_type rr_hdr.icmp6_type
#define rr_code rr_hdr.icmp6_code
#define rr_cksum rr_hdr.icmp6_cksum
#define rr_seqnum rr_hdr.icmp6_data32[0]
struct rr_pco_match { /* match prefix part */
u_int8_t rpm_code;
u_int8_t rpm_len;
u_int8_t rpm_ordinal;
u_int8_t rpm_matchlen;
u_int8_t rpm_minlen;
u_int8_t rpm_maxlen;
u_int16_t rpm_reserved;
struct in6_addr rpm_prefix;
};
#define RPM_PCO_ADD 1
#define RPM_PCO_CHANGE 2
#define RPM_PCO_SETGLOBAL 3
struct rr_pco_use { /* use prefix part */
u_int8_t rpu_uselen;
u_int8_t rpu_keeplen;
u_int8_t rpu_ramask;
u_int8_t rpu_raflags;
u_int32_t rpu_vltime;
u_int32_t rpu_pltime;
u_int32_t rpu_flags;
struct in6_addr rpu_prefix;
};
#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x20
#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x10
#if BYTE_ORDER == BIG_ENDIAN
#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000
#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000
#elif BYTE_ORDER == LITTLE_ENDIAN
#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80
#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40
#endif
struct rr_result { /* router renumbering result message */
u_int16_t rrr_flags;
u_int8_t rrr_ordinal;
u_int8_t rrr_matchedlen;
u_int32_t rrr_ifid;
struct in6_addr rrr_prefix;
};
#if BYTE_ORDER == BIG_ENDIAN
#define ICMP6_RR_RESULT_FLAGS_OOB 0x0002
#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001
#elif BYTE_ORDER == LITTLE_ENDIAN
#define ICMP6_RR_RESULT_FLAGS_OOB 0x02
#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x01
#endif
/*
* icmp6 filter structures.
*/
struct icmp6_filter {
u_int32_t icmp6_filter[8];
};
#ifdef _KERNEL
#define ICMP6_FILTER_SETPASSALL(filterp) \
{ \
int i; u_char *p; \
p = (u_char *)filterp; \
for (i = 0; i < sizeof(struct icmp6_filter); i++) \
p[i] = 0xff; \
}
#define ICMP6_FILTER_SETBLOCKALL(filterp) \
bzero(filterp, sizeof(struct icmp6_filter))
#else /* _KERNEL */
#define ICMP6_FILTER_SETPASSALL(filterp) \
memset(filterp, 0xff, sizeof(struct icmp6_filter))
#define ICMP6_FILTER_SETBLOCKALL(filterp) \
memset(filterp, 0x00, sizeof(struct icmp6_filter))
#endif /* _KERNEL */
#define ICMP6_FILTER_SETPASS(type, filterp) \
(((filterp)->icmp6_filter[(type) >> 5]) |= (1 << ((type) & 31)))
#define ICMP6_FILTER_SETBLOCK(type, filterp) \
(((filterp)->icmp6_filter[(type) >> 5]) &= ~(1 << ((type) & 31)))
#define ICMP6_FILTER_WILLPASS(type, filterp) \
((((filterp)->icmp6_filter[(type) >> 5]) & (1 << ((type) & 31))) != 0)
#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
((((filterp)->icmp6_filter[(type) >> 5]) & (1 << ((type) & 31))) == 0)
/*
* Variables related to this implementation
* of the internet control message protocol version 6.
*/
struct icmp6stat {
/* statistics related to icmp6 packets generated */
u_long icp6s_error; /* # of calls to icmp6_error */
u_long icp6s_canterror; /* no error 'cuz old was icmp */
u_long icp6s_toofreq; /* no error 'cuz rate limitation */
u_long icp6s_outhist[256];
/* statistics related to input messages proccesed */
u_long icp6s_badcode; /* icmp6_code out of range */
u_long icp6s_tooshort; /* packet < sizeof(struct icmp6_hdr) */
u_long icp6s_checksum; /* bad checksum */
u_long icp6s_badlen; /* calculated bound mismatch */
u_long icp6s_reflect; /* number of responses */
u_long icp6s_inhist[256];
};
/*
* Names for ICMP sysctl objects
*/
#define ICMPV6CTL_STATS 1
#define ICMPV6CTL_REDIRACCEPT 2 /* accept/process redirects */
#define ICMPV6CTL_REDIRTIMEOUT 3 /* redirect cache time */
#define ICMPV6CTL_ERRRATELIMIT 5 /* ICMPv6 error rate limitation */
#define ICMPV6CTL_ND6_PRUNE 6
#define ICMPV6CTL_ND6_DELAY 8
#define ICMPV6CTL_ND6_UMAXTRIES 9
#define ICMPV6CTL_ND6_MMAXTRIES 10
#define ICMPV6CTL_ND6_USELOOPBACK 11
#define ICMPV6CTL_ND6_PROXYALL 12
#define ICMPV6CTL_MAXID 13
#define ICMPV6CTL_NAMES { \
{ 0, 0 }, \
{ 0, 0 }, \
{ "rediraccept", CTLTYPE_INT }, \
{ "redirtimeout", CTLTYPE_INT }, \
{ 0, 0 }, \
{ "errratelimit", CTLTYPE_INT }, \
{ "nd6_prune", CTLTYPE_INT }, \
{ 0, 0 }, \
{ "nd6_delay", CTLTYPE_INT }, \
{ "nd6_umaxtries", CTLTYPE_INT }, \
{ "nd6_mmaxtries", CTLTYPE_INT }, \
{ "nd6_useloopback", CTLTYPE_INT }, \
{ "nd6_proxyall", CTLTYPE_INT }, \
}
#define ICMPV6CTL_VARS { \
0, \
0, \
&icmp6_rediraccept, \
&icmp6_redirtimeout, \
0, \
0, \
&icmp6errratelim, \
&nd6_prune, \
0, \
&nd6_delay, \
&nd6_umaxtries, \
&nd6_mmaxtries, \
&nd6_useloopback, \
&nd6_proxyall, \
}
#define RTF_PROBEMTU RTF_PROTO1
#ifdef _KERNEL
# ifdef __STDC__
struct rtentry;
struct rttimer;
struct in6_multi;
# endif
void icmp6_init __P((void));
void icmp6_paramerror __P((struct mbuf *, int));
void icmp6_error __P((struct mbuf *, int, int, int));
int icmp6_input __P((struct mbuf **, int *, int));
void icmp6_fasttimo __P((void));
void icmp6_reflect __P((struct mbuf *, size_t));
void icmp6_prepare __P((struct mbuf *));
void icmp6_redirect_input __P((struct mbuf *, int));
void icmp6_redirect_output __P((struct mbuf *, struct rtentry *));
/* XXX: is this the right place for these macros? */
#define icmp6_ifstat_inc(ifp, tag) \
do { \
if ((ifp) && (ifp)->if_index <= if_index \
&& (ifp)->if_index < icmp6_ifstatmax \
&& icmp6_ifstat && icmp6_ifstat[(ifp)->if_index]) { \
icmp6_ifstat[(ifp)->if_index]->tag++; \
} \
} while (0)
#define icmp6_ifoutstat_inc(ifp, type, code) \
do { \
icmp6_ifstat_inc(ifp, ifs6_out_msg); \
if (type < ICMP6_INFOMSG_MASK) \
icmp6_ifstat_inc(ifp, ifs6_out_error); \
switch(type) { \
case ICMP6_DST_UNREACH: \
icmp6_ifstat_inc(ifp, ifs6_out_dstunreach); \
if (code == ICMP6_DST_UNREACH_ADMIN) \
icmp6_ifstat_inc(ifp, ifs6_out_adminprohib); \
break; \
case ICMP6_PACKET_TOO_BIG: \
icmp6_ifstat_inc(ifp, ifs6_out_pkttoobig); \
break; \
case ICMP6_TIME_EXCEEDED: \
icmp6_ifstat_inc(ifp, ifs6_out_timeexceed); \
break; \
case ICMP6_PARAM_PROB: \
icmp6_ifstat_inc(ifp, ifs6_out_paramprob); \
break; \
case ICMP6_ECHO_REQUEST: \
icmp6_ifstat_inc(ifp, ifs6_out_echo); \
break; \
case ICMP6_ECHO_REPLY: \
icmp6_ifstat_inc(ifp, ifs6_out_echoreply); \
break; \
case MLD6_LISTENER_QUERY: \
icmp6_ifstat_inc(ifp, ifs6_out_mldquery); \
break; \
case MLD6_LISTENER_REPORT: \
icmp6_ifstat_inc(ifp, ifs6_out_mldreport); \
break; \
case MLD6_LISTENER_DONE: \
icmp6_ifstat_inc(ifp, ifs6_out_mlddone); \
break; \
case ND_ROUTER_SOLICIT: \
icmp6_ifstat_inc(ifp, ifs6_out_routersolicit); \
break; \
case ND_ROUTER_ADVERT: \
icmp6_ifstat_inc(ifp, ifs6_out_routeradvert); \
break; \
case ND_NEIGHBOR_SOLICIT: \
icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); \
break; \
case ND_NEIGHBOR_ADVERT: \
icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); \
break; \
case ND_REDIRECT: \
icmp6_ifstat_inc(ifp, ifs6_out_redirect); \
break; \
} \
} while (0)
extern int icmp6_rediraccept; /* accept/process redirects */
extern int icmp6_redirtimeout; /* cache time for redirect routes */
#endif /* _KERNEL */
#endif /* not _NETINET6_ICMPV6_H_ */

1879
sys/netinet6/in6.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@ -13,7 +13,7 @@
* 3. Neither the name of the project 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 PROJECT 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
@ -516,22 +516,10 @@ struct in6_pktinfo {
#define IPV6CTL_GIF_HLIM 19 /* default HLIM for gif encap packet */
#define IPV6CTL_USE_DEPRECATED 21 /* use deprecated addr (RFC2462 5.5.4) */
#define IPV6CTL_RR_PRUNE 22 /* walk timer for router renumbering */
#ifdef MAPPED_ADDR_ENABLED
#define IPV6CTL_MAPPED_ADDR 23
#endif /* MAPPED_ADDR_ENABLED */
/* New entries should be added here from current IPV6CTL_MAXID value. */
#define IPV6CTL_MAXID 24
#ifdef MAPPED_ADDR_ENABLED
#define IPV6CTL_NAMES_MAPPED_ADDR "mapped_addr"
#define IPV6CTL_TYPE_MAPPED_ADDR CTLTYPE_INT
#define IPV6CTL_VARS_MAPPED_ADDR &ip6_mapped_addr_on
#else /* MAPPED_ADDR_ENABLED */
#define IPV6CTL_NAMES_MAPPED_ADDR 0
#define IPV6CTL_TYPE_MAPPED_ADDR 0
#define IPV6CTL_VARS_MAPPED_ADDR 0
#endif /* MAPPED_ADDR_ENABLED */
#define IPV6CTL_NAMES { \
{ 0, 0 }, \
{ "forwarding", CTLTYPE_INT }, \
@ -556,7 +544,7 @@ struct in6_pktinfo {
{ 0, 0 }, \
{ "use_deprecated", CTLTYPE_INT }, \
{ "rr_prune", CTLTYPE_INT }, \
{ IPV6CTL_NAMES_MAPPED_ADDR, IPV6CTL_TYPE_MAPPED_ADDR }, \
{ "mapped_addr", CTLTYPE_INT }, \
}
#define IPV6CTL_VARS { \
@ -583,12 +571,23 @@ struct in6_pktinfo {
0, \
&ip6_use_deprecated, \
&ip6_rr_prune, \
IPV6CTL_VARS_MAPPED_ADDR, \
&ip6_mapped_addr_on, \
}
#endif /* !_XOPEN_SOURCE */
/*
* Redefinition of mbuf flags
*/
#define M_ANYCAST6 M_PROTO1
#define M_AUTHIPHDR M_PROTO2
#define M_DECRYPTED M_PROTO3
#define M_LOOP M_PROTO4
#define M_AUTHIPDGM M_PROTO5
#ifdef _KERNEL
struct cmsghdr;
struct cmsghdr;
struct mbuf;
struct ifnet;
int in6_canforward __P((struct in6_addr *, struct in6_addr *));
int in6_cksum __P((struct mbuf *, u_int8_t, int, int));
@ -597,7 +596,6 @@ int in6_addrscope __P((struct in6_addr *));
struct in6_ifaddr *in6_ifawithscope __P((struct ifnet *, struct in6_addr *));
struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *));
extern void in6_if_up __P((struct ifnet *));
#ifdef MAPPED_ADDR_ENABLED
struct sockaddr;
void in6_sin6_2_sin __P((struct sockaddr_in *sin,
@ -606,7 +604,6 @@ void in6_sin_2_v4mapsin6 __P((struct sockaddr_in *sin,
struct sockaddr_in6 *sin6));
void in6_sin6_2_sin_in_sock __P((struct sockaddr *nam));
void in6_sin_2_v4mapsin6_in_sock __P((struct sockaddr **nam));
#endif /* MAPPED_ADDR_ENABLED */
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))

301
sys/netinet6/in6_cksum.c Normal file
View file

@ -0,0 +1,301 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1988, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
*/
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/systm.h>
#include <netinet/in.h>
#include <netinet6/ip6.h>
#include <net/net_osdep.h>
/*
* Checksum routine for Internet Protocol family headers (Portable Version).
*
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
*/
#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
static union {
u_int16_t phs[4];
struct {
u_int32_t ph_len;
u_int8_t ph_zero[3];
u_int8_t ph_nxt;
} ph;
} uph;
/*
* m MUST contain a continuous IP6 header.
* off is a offset where TCP/UDP/ICMP6 header starts.
* len is a total length of a transport segment.
* (e.g. TCP header + TCP payload)
*/
int
in6_cksum(m, nxt, off, len)
register struct mbuf *m;
u_int8_t nxt;
register int off, len;
{
register u_int16_t *w;
register int sum = 0;
register int mlen = 0;
int byte_swapped = 0;
struct ip6_hdr *ip6;
union {
u_int8_t c[2];
u_int16_t s;
} s_util;
union {
u_int16_t s[2];
u_int32_t l;
} l_util;
/* sanity check */
if (m->m_pkthdr.len < off + len) {
panic("in6_cksum: mbuf len (%d) < off+len (%d+%d)\n",
m->m_pkthdr.len, off, len);
}
/*
* First create IP6 pseudo header and calculate a summary.
*/
ip6 = mtod(m, struct ip6_hdr *);
w = (u_int16_t *)&ip6->ip6_src;
uph.ph.ph_len = htonl(len);
uph.ph.ph_nxt = nxt;
/* IPv6 source address */
sum += w[0];
if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
sum += w[1];
sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
sum += w[6]; sum += w[7];
/* IPv6 destination address */
sum += w[8];
if (!IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
sum += w[9];
sum += w[10]; sum += w[11]; sum += w[12]; sum += w[13];
sum += w[14]; sum += w[15];
/* Payload length and upper layer identifier */
sum += uph.phs[0]; sum += uph.phs[1];
sum += uph.phs[2]; sum += uph.phs[3];
/*
* Secondly calculate a summary of the first mbuf excluding offset.
*/
while (m != NULL && off > 0) {
if (m->m_len <= off)
off -= m->m_len;
else
break;
m = m->m_next;
}
w = (u_int16_t *)(mtod(m, u_char *) + off);
mlen = m->m_len - off;
if (len < mlen)
mlen = len;
len -= mlen;
/*
* Force to even boundary.
*/
if ((1 & (long) w) && (mlen > 0)) {
REDUCE;
sum <<= 8;
s_util.c[0] = *(u_char *)w;
w = (u_int16_t *)((char *)w + 1);
mlen--;
byte_swapped = 1;
}
/*
* Unroll the loop to make overhead from
* branches &c small.
*/
while ((mlen -= 32) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
w += 16;
}
mlen += 32;
while ((mlen -= 8) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
w += 4;
}
mlen += 8;
if (mlen == 0 && byte_swapped == 0)
goto next;
REDUCE;
while ((mlen -= 2) >= 0) {
sum += *w++;
}
if (byte_swapped) {
REDUCE;
sum <<= 8;
byte_swapped = 0;
if (mlen == -1) {
s_util.c[1] = *(char *)w;
sum += s_util.s;
mlen = 0;
} else
mlen = -1;
} else if (mlen == -1)
s_util.c[0] = *(char *)w;
next:
m = m->m_next;
/*
* Lastly calculate a summary of the rest of mbufs.
*/
for (;m && len; m = m->m_next) {
if (m->m_len == 0)
continue;
w = mtod(m, u_int16_t *);
if (mlen == -1) {
/*
* The first byte of this mbuf is the continuation
* of a word spanning between this mbuf and the
* last mbuf.
*
* s_util.c[0] is already saved when scanning previous
* mbuf.
*/
s_util.c[1] = *(char *)w;
sum += s_util.s;
w = (u_int16_t *)((char *)w + 1);
mlen = m->m_len - 1;
len--;
} else
mlen = m->m_len;
if (len < mlen)
mlen = len;
len -= mlen;
/*
* Force to even boundary.
*/
if ((1 & (long) w) && (mlen > 0)) {
REDUCE;
sum <<= 8;
s_util.c[0] = *(u_char *)w;
w = (u_int16_t *)((char *)w + 1);
mlen--;
byte_swapped = 1;
}
/*
* Unroll the loop to make overhead from
* branches &c small.
*/
while ((mlen -= 32) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
w += 16;
}
mlen += 32;
while ((mlen -= 8) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
w += 4;
}
mlen += 8;
if (mlen == 0 && byte_swapped == 0)
continue;
REDUCE;
while ((mlen -= 2) >= 0) {
sum += *w++;
}
if (byte_swapped) {
REDUCE;
sum <<= 8;
byte_swapped = 0;
if (mlen == -1) {
s_util.c[1] = *(char *)w;
sum += s_util.s;
mlen = 0;
} else
mlen = -1;
} else if (mlen == -1)
s_util.c[0] = *(char *)w;
}
if (len)
panic("in6_cksum: out of data\n");
if (mlen == -1) {
/* The last mbuf has odd # of bytes. Follow the
standard (the odd byte may be shifted left by 8 bits
or not as determined by endian-ness of the machine) */
s_util.c[1] = 0;
sum += s_util.s;
}
REDUCE;
return (~sum & 0xffff);
}

690
sys/netinet6/in6_ifattach.c Normal file
View file

@ -0,0 +1,690 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/kernel.h>
#include <sys/md5.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/if_ether.h>
#include <netinet6/in6.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_ifattach.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
#include <net/net_osdep.h>
static struct in6_addr llsol;
struct in6_ifstat **in6_ifstat = NULL;
struct icmp6_ifstat **icmp6_ifstat = NULL;
size_t in6_ifstatmax = 0;
size_t icmp6_ifstatmax = 0;
unsigned long in6_maxmtu = 0;
int found_first_ifid = 0;
#define IFID_LEN 8
static char first_ifid[IFID_LEN];
static int laddr_to_eui64 __P((u_int8_t *, u_int8_t *, size_t));
static int gen_rand_eui64 __P((u_int8_t *));
static int
laddr_to_eui64(dst, src, len)
u_int8_t *dst;
u_int8_t *src;
size_t len;
{
static u_int8_t zero[8];
bzero(zero, sizeof(zero));
switch (len) {
case 6:
if (bcmp(zero, src, 6) == 0)
return EINVAL;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = 0xff;
dst[4] = 0xfe;
dst[5] = src[3];
dst[6] = src[4];
dst[7] = src[5];
break;
case 8:
if (bcmp(zero, src, 8) == 0)
return EINVAL;
bcopy(src, dst, len);
break;
default:
return EINVAL;
}
return 0;
}
/*
* Generate a last-resort interface identifier, when the machine has no
* IEEE802/EUI64 address sources.
* The address should be random, and should not change across reboot.
*/
static int
gen_rand_eui64(dst)
u_int8_t *dst;
{
MD5_CTX ctxt;
u_int8_t digest[16];
int hostnamelen = strlen(hostname);
/* generate 8bytes of pseudo-random value. */
bzero(&ctxt, sizeof(ctxt));
MD5Init(&ctxt);
MD5Update(&ctxt, hostname, hostnamelen);
MD5Final(digest, &ctxt);
/* assumes sizeof(digest) > sizeof(first_ifid) */
bcopy(digest, dst, 8);
/* make sure to set "u" bit to local, and "g" bit to individual. */
dst[0] &= 0xfe;
dst[0] |= 0x02; /* EUI64 "local" */
return 0;
}
/*
* Find first ifid on list of interfaces.
* This is assumed that ifp0's interface token (for example, IEEE802 MAC)
* is globally unique. We may need to have a flag parameter in the future.
*/
int
in6_ifattach_getifid(ifp0)
struct ifnet *ifp0;
{
struct ifnet *ifp;
struct ifaddr *ifa;
u_int8_t *addr = NULL;
int addrlen = 0;
struct sockaddr_dl *sdl;
if (found_first_ifid)
return 0;
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
{
if (ifp0 != NULL && ifp0 != ifp)
continue;
for (ifa = ifp->if_addrlist.tqh_first;
ifa;
ifa = ifa->ifa_list.tqe_next)
{
if (ifa->ifa_addr->sa_family != AF_LINK)
continue;
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
if (sdl == NULL)
continue;
if (sdl->sdl_alen == 0)
continue;
switch (ifp->if_type) {
case IFT_ETHER:
case IFT_FDDI:
case IFT_ATM:
/* IEEE802/EUI64 cases - what others? */
addr = LLADDR(sdl);
addrlen = sdl->sdl_alen;
/*
* to copy ifid from IEEE802/EUI64 interface,
* u bit of the source needs to be 0.
*/
if ((addr[0] & 0x02) != 0)
break;
goto found;
case IFT_ARCNET:
/*
* ARCnet interface token cannot be used as
* globally unique identifier due to its
* small bitwidth.
*/
break;
default:
break;
}
}
}
#ifdef DEBUG
printf("in6_ifattach_getifid: failed to get EUI64");
#endif
return EADDRNOTAVAIL;
found:
if (laddr_to_eui64(first_ifid, addr, addrlen) == 0)
found_first_ifid = 1;
if (found_first_ifid) {
printf("%s: supplying EUI64: "
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
if_name(ifp),
first_ifid[0] & 0xff, first_ifid[1] & 0xff,
first_ifid[2] & 0xff, first_ifid[3] & 0xff,
first_ifid[4] & 0xff, first_ifid[5] & 0xff,
first_ifid[6] & 0xff, first_ifid[7] & 0xff);
/* invert u bit to convert EUI64 to RFC2373 interface ID. */
first_ifid[0] ^= 0x02;
return 0;
} else {
#ifdef DEBUG
printf("in6_ifattach_getifid: failed to get EUI64");
#endif
return EADDRNOTAVAIL;
}
}
/*
* add link-local address to *pseudo* p2p interfaces.
* get called when the first MAC address is made available in in6_ifattach().
*
* XXX I start considering this loop as a bad idea. (itojun)
*/
void
in6_ifattach_p2p()
{
struct ifnet *ifp;
/* prevent infinite loop. just in case. */
if (found_first_ifid == 0)
return;
for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
{
switch (ifp->if_type) {
case IFT_GIF:
/* pseudo interfaces - safe to initialize here */
in6_ifattach(ifp, IN6_IFT_P2P, 0, 0);
break;
#ifdef IFT_DUMMY
case IFT_DUMMY:
#endif
case IFT_FAITH:
/* this mistakingly becomes IFF_UP */
break;
case IFT_SLIP:
/* IPv6 is not supported */
break;
case IFT_PPP:
/* this is not a pseudo interface, skip it */
break;
default:
break;
}
}
}
void
in6_ifattach(ifp, type, laddr, noloop)
struct ifnet *ifp;
u_int type;
caddr_t laddr;
/* size_t laddrlen; */
int noloop;
{
static size_t if_indexlim = 8;
struct sockaddr_in6 mltaddr;
struct sockaddr_in6 mltmask;
struct sockaddr_in6 gate;
struct sockaddr_in6 mask;
struct in6_ifaddr *ia, *ib, *oia;
struct ifaddr *ifa;
int rtflag = 0;
if (type == IN6_IFT_P2P && found_first_ifid == 0) {
printf("%s: no ifid available for IPv6 link-local address\n",
if_name(ifp));
/* last resort */
if (gen_rand_eui64(first_ifid) == 0) {
printf("%s: using random value as EUI64: "
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
if_name(ifp),
first_ifid[0] & 0xff, first_ifid[1] & 0xff,
first_ifid[2] & 0xff, first_ifid[3] & 0xff,
first_ifid[4] & 0xff, first_ifid[5] & 0xff,
first_ifid[6] & 0xff, first_ifid[7] & 0xff);
/*
* invert u bit to convert EUI64 to RFC2373 interface
* ID.
*/
first_ifid[0] ^= 0x02;
found_first_ifid = 1;
}
}
if ((ifp->if_flags & IFF_MULTICAST) == 0) {
printf("%s: not multicast capable, IPv6 not enabled\n",
if_name(ifp));
return;
}
/*
* We have some arrays that should be indexed by if_index.
* since if_index will grow dynamically, they should grow too.
* struct in6_ifstat **in6_ifstat
* struct icmp6_ifstat **icmp6_ifstat
*/
if (in6_ifstat == NULL || icmp6_ifstat == NULL
|| if_index >= if_indexlim) {
size_t n;
caddr_t q;
size_t olim;
olim = if_indexlim;
while (if_index >= if_indexlim)
if_indexlim <<= 1;
/* grow in6_ifstat */
n = if_indexlim * sizeof(struct in6_ifstat *);
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
bzero(q, n);
if (in6_ifstat) {
bcopy((caddr_t)in6_ifstat, q,
olim * sizeof(struct in6_ifstat *));
free((caddr_t)in6_ifstat, M_IFADDR);
}
in6_ifstat = (struct in6_ifstat **)q;
in6_ifstatmax = if_indexlim;
/* grow icmp6_ifstat */
n = if_indexlim * sizeof(struct icmp6_ifstat *);
q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
bzero(q, n);
if (icmp6_ifstat) {
bcopy((caddr_t)icmp6_ifstat, q,
olim * sizeof(struct icmp6_ifstat *));
free((caddr_t)icmp6_ifstat, M_IFADDR);
}
icmp6_ifstat = (struct icmp6_ifstat **)q;
icmp6_ifstatmax = if_indexlim;
}
/*
* To prevent to assign link-local address to PnP network
* cards multiple times.
* This is lengthy for P2P and LOOP but works.
*/
ifa = TAILQ_FIRST(&ifp->if_addrlist);
if (ifa != NULL) {
for ( ; ifa; ifa = TAILQ_NEXT(ifa, ifa_list)) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
if (IN6_IS_ADDR_LINKLOCAL(&satosin6(ifa->ifa_addr)->sin6_addr))
return;
}
} else {
TAILQ_INIT(&ifp->if_addrlist);
}
/*
* link-local address
*/
ia = (struct in6_ifaddr *)malloc(sizeof(*ia), M_IFADDR, M_WAITOK);
bzero((caddr_t)ia, sizeof(*ia));
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
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);
/*
* Also link into the IPv6 address chain beginning with in6_ifaddr.
* kazu opposed it, but itojun & jinmei wanted.
*/
if ((oia = in6_ifaddr) != NULL) {
for (; oia->ia_next; oia = oia->ia_next)
continue;
oia->ia_next = ia;
} else
in6_ifaddr = ia;
ia->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
ia->ia_prefixmask.sin6_family = AF_INET6;
ia->ia_prefixmask.sin6_addr = in6mask64;
bzero(&ia->ia_addr, sizeof(struct sockaddr_in6));
ia->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
ia->ia_addr.sin6_family = AF_INET6;
ia->ia_addr.sin6_addr.s6_addr16[0] = htons(0xfe80);
ia->ia_addr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
ia->ia_addr.sin6_addr.s6_addr32[1] = 0;
switch (type) {
case IN6_IFT_LOOP:
ia->ia_addr.sin6_addr.s6_addr32[2] = 0;
ia->ia_addr.sin6_addr.s6_addr32[3] = htonl(1);
break;
case IN6_IFT_802:
ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
ia->ia_ifa.ifa_flags |= RTF_CLONING;
rtflag = RTF_CLONING;
/* fall through */
case IN6_IFT_P2P802:
if (laddr == NULL)
break;
/* XXX use laddrlen */
if (laddr_to_eui64(&ia->ia_addr.sin6_addr.s6_addr8[8],
laddr, 6) != 0) {
break;
}
/* invert u bit to convert EUI64 to RFC2373 interface ID. */
ia->ia_addr.sin6_addr.s6_addr8[8] ^= 0x02;
if (found_first_ifid == 0) {
if (in6_ifattach_getifid(ifp) == 0)
in6_ifattach_p2p();
}
break;
case IN6_IFT_P2P:
bcopy((caddr_t)first_ifid,
(caddr_t)&ia->ia_addr.sin6_addr.s6_addr8[8],
IFID_LEN);
break;
case IN6_IFT_ARCNET:
ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
ia->ia_ifa.ifa_flags |= RTF_CLONING;
rtflag = RTF_CLONING;
if (laddr == NULL)
break;
/* make non-global IF id out of link-level address */
bzero(&ia->ia_addr.sin6_addr.s6_addr8[8], 7);
ia->ia_addr.sin6_addr.s6_addr8[15] = *laddr;
}
ia->ia_ifa.ifa_metric = ifp->if_metric;
if (ifp->if_ioctl != NULL) {
int s;
int error;
/*
* give the interface a chance to initialize, in case this
* is the first address to be added.
*/
s = splimp();
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
splx(s);
if (error) {
switch (error) {
case EAFNOSUPPORT:
printf("%s: IPv6 not supported\n",
if_name(ifp));
break;
default:
printf("%s: SIOCSIFADDR error %d\n",
if_name(ifp), error);
break;
}
/* undo changes */
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
if (oia)
oia->ia_next = ia->ia_next;
else
in6_ifaddr = ia->ia_next;
free(ia, M_IFADDR);
return;
}
}
/* add route to the interface. */
rtrequest(RTM_ADD,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&ia->ia_prefixmask,
RTF_UP|rtflag,
(struct rtentry **)0);
ia->ia_flags |= IFA_ROUTE;
if (type == IN6_IFT_P2P || type == IN6_IFT_P2P802) {
/*
* route local address to loopback
*/
bzero(&gate, sizeof(gate));
gate.sin6_len = sizeof(struct sockaddr_in6);
gate.sin6_family = AF_INET6;
gate.sin6_addr = in6addr_loopback;
bzero(&mask, sizeof(mask));
mask.sin6_len = sizeof(struct sockaddr_in6);
mask.sin6_family = AF_INET6;
mask.sin6_addr = in6mask64;
rtrequest(RTM_ADD,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&gate,
(struct sockaddr *)&mask,
RTF_UP|RTF_HOST,
(struct rtentry **)0);
}
/*
* loopback address
*/
ib = (struct in6_ifaddr *)NULL;
if (type == IN6_IFT_LOOP) {
ib = (struct in6_ifaddr *)
malloc(sizeof(*ib), M_IFADDR, M_WAITOK);
bzero((caddr_t)ib, sizeof(*ib));
ib->ia_ifa.ifa_addr = (struct sockaddr *)&ib->ia_addr;
ib->ia_ifa.ifa_dstaddr = (struct sockaddr *)&ib->ia_dstaddr;
ib->ia_ifa.ifa_netmask = (struct sockaddr *)&ib->ia_prefixmask;
ib->ia_ifp = ifp;
ia->ia_next = ib;
TAILQ_INSERT_TAIL(&ifp->if_addrlist, (struct ifaddr *)ib,
ifa_list);
ib->ia_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
ib->ia_prefixmask.sin6_family = AF_INET6;
ib->ia_prefixmask.sin6_addr = in6mask128;
ib->ia_addr.sin6_len = sizeof(struct sockaddr_in6);
ib->ia_addr.sin6_family = AF_INET6;
ib->ia_addr.sin6_addr = in6addr_loopback;
ib->ia_ifa.ifa_metric = ifp->if_metric;
rtrequest(RTM_ADD,
(struct sockaddr *)&ib->ia_addr,
(struct sockaddr *)&ib->ia_addr,
(struct sockaddr *)&ib->ia_prefixmask,
RTF_UP|RTF_HOST,
(struct rtentry **)0);
ib->ia_flags |= IFA_ROUTE;
}
/*
* join multicast
*/
if (ifp->if_flags & IFF_MULTICAST) {
int error; /* not used */
bzero(&mltmask, sizeof(mltmask));
mltmask.sin6_len = sizeof(struct sockaddr_in6);
mltmask.sin6_family = AF_INET6;
mltmask.sin6_addr = in6mask32;
/*
* join link-local all-nodes address
*/
bzero(&mltaddr, sizeof(mltaddr));
mltaddr.sin6_len = sizeof(struct sockaddr_in6);
mltaddr.sin6_family = AF_INET6;
mltaddr.sin6_addr = in6addr_linklocal_allnodes;
mltaddr.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
rtrequest(RTM_ADD,
(struct sockaddr *)&mltaddr,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&mltmask,
RTF_UP|RTF_CLONING, /* xxx */
(struct rtentry **)0);
(void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
if (type == IN6_IFT_LOOP) {
/*
* join node-local all-nodes address
*/
mltaddr.sin6_addr = in6addr_nodelocal_allnodes;
rtrequest(RTM_ADD,
(struct sockaddr *)&mltaddr,
(struct sockaddr *)&ib->ia_addr,
(struct sockaddr *)&mltmask,
RTF_UP,
(struct rtentry **)0);
(void)in6_addmulti(&mltaddr.sin6_addr, ifp, &error);
} else {
/*
* join solicited multicast address
*/
bzero(&llsol, sizeof(llsol));
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;
(void)in6_addmulti(&llsol, ifp, &error);
}
}
/* update dynamically. */
if (in6_maxmtu < ifp->if_mtu)
in6_maxmtu = ifp->if_mtu;
if (in6_ifstat[ifp->if_index] == NULL) {
in6_ifstat[ifp->if_index] = (struct in6_ifstat *)
malloc(sizeof(struct in6_ifstat), M_IFADDR, M_WAITOK);
bzero(in6_ifstat[ifp->if_index], sizeof(struct in6_ifstat));
}
if (icmp6_ifstat[ifp->if_index] == NULL) {
icmp6_ifstat[ifp->if_index] = (struct icmp6_ifstat *)
malloc(sizeof(struct icmp6_ifstat), M_IFADDR, M_WAITOK);
bzero(icmp6_ifstat[ifp->if_index], sizeof(struct icmp6_ifstat));
}
/* initialize NDP variables */
nd6_ifattach(ifp);
/* mark the address TENTATIVE, if needed. */
switch (ifp->if_type) {
case IFT_ARCNET:
case IFT_ETHER:
case IFT_FDDI:
ia->ia6_flags |= IN6_IFF_TENTATIVE;
/* nd6_dad_start() will be called in in6_if_up */
break;
#ifdef IFT_DUMMY
case IFT_DUMMY:
#endif
case IFT_GIF: /*XXX*/
case IFT_LOOP:
case IFT_FAITH:
default:
break;
}
return;
}
void
in6_ifdetach(ifp)
struct ifnet *ifp;
{
struct in6_ifaddr *ia, *oia;
struct ifaddr *ifa;
struct rtentry *rt;
short rtflags;
for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next)
{
if (ifa->ifa_addr->sa_family != AF_INET6
|| !IN6_IS_ADDR_LINKLOCAL(&satosin6(&ifa->ifa_addr)->sin6_addr)) {
continue;
}
ia = (struct in6_ifaddr *)ifa;
/* remove from the routing table */
if ((ia->ia_flags & IFA_ROUTE)
&& (rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {
rtflags = rt->rt_flags;
rtfree(rt);
rtrequest(RTM_DELETE,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&ia->ia_addr,
(struct sockaddr *)&ia->ia_prefixmask,
rtflags, (struct rtentry **)0);
}
/* remove from the linked list */
TAILQ_REMOVE(&ifp->if_addrlist, (struct ifaddr *)ia, ifa_list);
/* also remove from the IPv6 address chain(itojun&jinmei) */
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;
#ifdef DEBUG
else
printf("%s: didn't unlink in6ifaddr from "
"list\n", if_name(ifp));
#endif
}
free(ia, M_IFADDR);
}
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#ifndef _NETINET6_IN6_IFATTACH_H_
#define _NETINET6_IN6_IFATTACH_H_
#ifdef _KERNEL
extern int found_first_ifid;
int in6_ifattach_getifid __P((struct ifnet *));
void in6_ifattach_p2p __P((void));
void in6_ifattach __P((struct ifnet *, u_int, caddr_t, int));
void in6_ifdetach __P((struct ifnet *));
#endif /* _KERNEL */
#define IN6_IFT_LOOP 1
#define IN6_IFT_P2P 2
#define IN6_IFT_802 3
#define IN6_IFT_P2P802 4
#define IN6_IFT_ARCNET 5
#endif /* _NETINET6_IN6_IFATTACH_H_ */

1131
sys/netinet6/in6_pcb.c Normal file

File diff suppressed because it is too large Load diff

108
sys/netinet6/in6_pcb.h Normal file
View file

@ -0,0 +1,108 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)in_pcb.h 8.1 (Berkeley) 6/10/93
*/
#ifndef _NETINET6_IN6_PCB_H_
#define _NETINET6_IN6_PCB_H_
#ifdef KERNEL
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
void in6_losing __P((struct inpcb *));
int in6_pcballoc __P((struct socket *, struct inpcbinfo *, struct proc *));
int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct proc *));
int in6_pcbconnect __P((struct inpcb *, struct sockaddr *, struct proc *));
void in6_pcbdetach __P((struct inpcb *));
void in6_pcbdisconnect __P((struct inpcb *));
int in6_pcbladdr __P((struct inpcb *, struct sockaddr *,
struct in6_addr **));
struct inpcb *
in6_pcblookup_local __P((struct inpcbinfo *,
struct in6_addr *, u_int, int));
struct inpcb *
in6_pcblookup_hash __P((struct inpcbinfo *,
struct in6_addr *, u_int, struct in6_addr *,
u_int, int, struct ifnet *));
void in6_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
u_int, struct in6_addr *, u_int, int,
void (*)(struct inpcb *, int)));
void in6_rtchange __P((struct inpcb *, int));
int in6_setpeeraddr __P((struct socket *so, struct sockaddr **nam));
int in6_setsockaddr __P((struct socket *so, struct sockaddr **nam));
int in6_mapped_sockaddr __P((struct socket *so, struct sockaddr **nam));
int in6_mapped_peeraddr __P((struct socket *so, struct sockaddr **nam));
struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *,
struct ip6_pktopts *,
struct ip6_moptions *,
struct route_in6 *,
struct in6_addr *, int *));
int in6_selecthlim __P((struct inpcb *, struct ifnet *));
void init_sin6 __P((struct sockaddr_in6 *sin6, struct mbuf *m));
#endif /* KERNEL */
#endif /* !_NETINET6_IN6_PCB_H_ */

1106
sys/netinet6/in6_prefix.c Normal file

File diff suppressed because it is too large Load diff

88
sys/netinet6/in6_prefix.h Normal file
View file

@ -0,0 +1,88 @@
/*
* Copyright (C) 1995, 1996, 1997, 1998 and 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
struct rr_prefix {
struct ifprefix rp_ifpr;
LIST_ENTRY(rr_prefix) rp_entry;
LIST_HEAD(rp_addrhead, rp_addr) rp_addrhead;
struct sockaddr_in6 rp_prefix; /* prefix */
u_int32_t rp_vltime; /* advertised valid lifetime */
u_int32_t rp_pltime; /* advertised preferred lifetime */
time_t rp_expire; /* expiration time of the prefix */
time_t rp_preferred; /* preferred time of the prefix */
struct in6_prflags rp_flags;
u_char rp_origin; /* from where this prefix info is obtained */
struct rp_stateflags {
/* if some prefix should be added to this prefix */
u_char addmark : 1;
u_char delmark : 1; /* if this prefix will be deleted */
} rp_stateflags;
};
#define rp_type rp_ifpr.ifpr_type
#define rp_ifp rp_ifpr.ifpr_ifp
#define rp_plen rp_ifpr.ifpr_plen
#define rp_raf rp_flags.prf_ra
#define rp_raf_onlink rp_flags.prf_ra.onlink
#define rp_raf_auto rp_flags.prf_ra.autonomous
#define rp_statef_addmark rp_stateflags.addmark
#define rp_statef_delmark rp_stateflags.delmark
#define rp_rrf rp_flags.prf_rr
#define rp_rrf_decrvalid rp_flags.prf_rr.decrvalid
#define rp_rrf_decrprefd rp_flags.prf_rr.decrprefd
struct rp_addr {
LIST_ENTRY(rp_addr) ra_entry;
struct in6_addr ra_ifid;
struct in6_ifaddr *ra_addr;
struct ra_flags {
u_char anycast : 1;
} ra_flags;
};
#define ifpr2rp(ifpr) ((struct rr_prefix *)(ifpr))
#define rp2ifpr(rp) ((struct ifprefix *)(rp))
#define RP_IN6(rp) (&(rp)->rp_prefix.sin6_addr)
#define RR_INFINITE_LIFETIME 0xffffffff
LIST_HEAD(rr_prhead, rr_prefix);
extern struct rr_prhead rr_prefix;
void in6_rr_timer __P((void *));
int delete_each_prefix __P((struct socket *so, struct rr_prefix *rpp,
u_char origin));

410
sys/netinet6/in6_proto.c Normal file
View file

@ -0,0 +1,410 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)in_proto.c 8.1 (Berkeley) 6/10/93
*/
#include "opt_inet.h"
#include "opt_ipsec.h"
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <sys/kernel.h>
#include <sys/domain.h>
#include <sys/mbuf.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/radix.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/icmp6.h>
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet6/tcp6_var.h>
#include <netinet6/udp6_var.h>
#include <netinet6/pim6_var.h>
#include <netinet6/nd6.h>
#include <netinet6/in6_prefix.h>
#ifdef IPSEC
#include <netinet6/ipsec.h>
#ifdef INET6
#include <netinet6/ipsec6.h>
#endif /* INET6 */
#include <netinet6/ah.h>
#ifdef IPSEC_ESP
#include <netinet6/esp.h>
#endif
#include <netinet6/ipcomp.h>
#endif /*IPSEC*/
#include <netinet6/ip6protosw.h>
/* #include "gif.h" */
#if NGIF > 0
#include <netinet6/in6_gif.h>
#endif
#include <net/net_osdep.h>
#define offsetof(type, member) ((size_t)(&((type *)0)->member))
/*
* TCP/IP protocol family: IP6, ICMP6, UDP, TCP.
*/
extern struct domain inet6domain;
static struct pr_usrreqs nousrreqs;
struct ip6protosw inet6sw[] = {
{ 0, &inet6domain, IPPROTO_IPV6, 0,
0, 0, 0, 0,
0,
ip6_init, 0, frag6_slowtimo, frag6_drain,
&nousrreqs,
},
{ SOCK_RAW, &inet6domain, IPPROTO_RAW, PR_ATOMIC | PR_ADDR,
rip6_input, rip6_output, 0, rip6_ctloutput,
0,
0, 0, 0, 0,
&rip6_usrreqs
},
{ SOCK_RAW, &inet6domain, IPPROTO_ICMPV6, PR_ATOMIC | PR_ADDR,
icmp6_input, rip6_output, 0, rip6_ctloutput,
0,
icmp6_init, icmp6_fasttimo, 0, 0,
&rip6_usrreqs
},
{ SOCK_RAW, &inet6domain, IPPROTO_DSTOPTS,PR_ATOMIC|PR_ADDR,
dest6_input, 0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs
},
{ SOCK_RAW, &inet6domain, IPPROTO_ROUTING,PR_ATOMIC|PR_ADDR,
route6_input, 0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs
},
{ SOCK_RAW, &inet6domain, IPPROTO_FRAGMENT,PR_ATOMIC|PR_ADDR,
frag6_input, 0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs
},
#ifdef IPSEC
{ SOCK_RAW, &inet6domain, IPPROTO_AH, PR_ATOMIC|PR_ADDR,
ah6_input, 0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs,
},
#ifdef IPSEC_ESP
{ SOCK_RAW, &inet6domain, IPPROTO_ESP, PR_ATOMIC|PR_ADDR,
esp6_input, 0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs,
},
#endif
{ SOCK_RAW, &inet6domain, IPPROTO_IPCOMP, PR_ATOMIC|PR_ADDR,
ipcomp6_input, 0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs,
},
#endif /* IPSEC */
#if NGIF > 0
{ SOCK_RAW, &inet6domain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
in6_gif_input,0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs
},
#ifdef INET6
{ SOCK_RAW, &inet6domain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
in6_gif_input,0, 0, 0,
0,
0, 0, 0, 0,
&nousrreqs
},
#endif /* INET6 */
#endif /* GIF */
/* raw wildcard */
{ SOCK_RAW, &inet6domain, 0, PR_ATOMIC | PR_ADDR,
rip6_input, rip6_output, 0, rip6_ctloutput,
0,
0, 0, 0, 0,
&rip6_usrreqs
},
};
extern int in6_inithead __P((void **, int));
struct domain inet6domain =
{ AF_INET6, "internet6", 0, 0, 0,
(struct protosw *)inet6sw,
(struct protosw *)&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])], 0,
in6_inithead,
offsetof(struct sockaddr_in6, sin6_addr) << 3,
sizeof(struct sockaddr_in6) };
DOMAIN_SET(inet6);
/*
* Internet configuration info
*/
#ifndef IPV6FORWARDING
#ifdef GATEWAY6
#define IPV6FORWARDING 1 /* forward IP6 packets not for us */
#else
#define IPV6FORWARDING 0 /* don't forward IP6 packets not for us */
#endif /* GATEWAY6 */
#endif /* !IPV6FORWARDING */
#ifndef IPV6_SENDREDIRECTS
#define IPV6_SENDREDIRECTS 1
#endif
int ip6_forwarding = IPV6FORWARDING; /* act as router? */
int ip6_sendredirects = IPV6_SENDREDIRECTS;
int ip6_defhlim = IPV6_DEFHLIM;
int ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
int ip6_accept_rtadv = 0; /* "IPV6FORWARDING ? 0 : 1" is dangerous */
int ip6_maxfragpackets = 200;
int ip6_log_interval = 5;
int ip6_hdrnestlimit = 50; /* appropriate? */
int ip6_dad_count = 1; /* DupAddrDetectionTransmits */
u_int32_t ip6_flow_seq;
int ip6_auto_flowlabel = 1;
#if NGIF > 0
int ip6_gif_hlim = GIF_HLIM;
#else
int ip6_gif_hlim = 0;
#endif
int ip6_use_deprecated = 1; /* allow deprecated addr (RFC2462 5.5.4) */
int ip6_rr_prune = 5; /* router renumbering prefix
* walk list every 5 sec. */
int ip6_mapped_addr_on = 1;
u_int32_t ip6_id = 0UL;
int ip6_keepfaith = 0;
time_t ip6_log_time = (time_t)0L;
/* icmp6 */
/*
* BSDI4 defines these variables in in_proto.c...
* XXX: what if we don't define INET? Should we define pmtu6_expire
* or so? (jinmei@kame.net 19990310)
*/
int pmtu_expire = 60*10;
int pmtu_probe = 60*2;
/* raw IP6 parameters */
/*
* Nominal space allocated to a raw ip socket.
*/
#define RIPV6SNDQ 8192
#define RIPV6RCVQ 8192
u_long rip6_sendspace = RIPV6SNDQ;
u_long rip6_recvspace = RIPV6RCVQ;
/* ICMPV6 parameters */
int icmp6_rediraccept = 1; /* accept and process redirects */
int icmp6_redirtimeout = 10 * 60; /* 10 minutes */
u_int icmp6errratelim = 1000; /* 1000usec = 1msec */
/* UDP on IP6 parameters */
int udp6_sendspace = 9216; /* really max datagram size */
int udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
/* 40 1K datagrams */
/*
* sysctl related items.
*/
SYSCTL_NODE(_net, PF_INET6, inet6, CTLFLAG_RW, 0,
"Internet6 Family");
/* net.inet6 */
SYSCTL_NODE(_net_inet6, IPPROTO_IPV6, ip6, CTLFLAG_RW, 0, "IP6");
SYSCTL_NODE(_net_inet6, IPPROTO_ICMPV6, icmp6, CTLFLAG_RW, 0, "ICMP6");
SYSCTL_NODE(_net_inet6, IPPROTO_UDP, udp6, CTLFLAG_RW, 0, "UDP6");
SYSCTL_NODE(_net_inet6, IPPROTO_TCP, tcp6, CTLFLAG_RW, 0, "TCP6");
#ifdef IPSEC
SYSCTL_NODE(_net_inet6, IPPROTO_ESP, ipsec6, CTLFLAG_RW, 0, "IPSEC6");
#endif /* IPSEC */
/* net.inet6.ip6 */
static int
sysctl_ip6_forwarding SYSCTL_HANDLER_ARGS
{
int error = 0;
int old_ip6_forwarding;
int changed;
error = SYSCTL_OUT(req, arg1, sizeof(int));
if (error || !req->newptr)
return (error);
old_ip6_forwarding = ip6_forwarding;
error = SYSCTL_IN(req, arg1, sizeof(int));
if (error != 0)
return (error);
changed = (ip6_forwarding ? 1 : 0) ^ (old_ip6_forwarding ? 1 : 0);
if (changed == 0)
return (error);
if (ip6_forwarding != 0) { /* host becomes router */
int s = splnet();
struct nd_prefix *pr, *next;
for (pr = nd_prefix.lh_first; pr; pr = next) {
next = pr->ndpr_next;
if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
prelist_remove(pr);
}
splx(s);
} else { /* router becomes host */
struct socket so;
/* XXX: init dummy so */
bzero(&so, sizeof(so));
while(!LIST_EMPTY(&rr_prefix))
delete_each_prefix(&so, LIST_FIRST(&rr_prefix),
PR_ORIG_KERNEL);
}
return (error);
}
SYSCTL_OID(_net_inet6_ip6, IPV6CTL_FORWARDING, forwarding,
CTLTYPE_INT|CTLFLAG_RW, &ip6_forwarding, 0, sysctl_ip6_forwarding,
"I", "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_SENDREDIRECTS,
redirect, CTLFLAG_RW, &ip6_sendredirects, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFHLIM,
hlim, CTLFLAG_RW, &ip6_defhlim, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS,
maxfragpackets, CTLFLAG_RW, &ip6_maxfragpackets, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_ACCEPT_RTADV,
accept_rtadv, CTLFLAG_RW, &ip6_accept_rtadv, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH,
keepfaith, CTLFLAG_RW, &ip6_keepfaith, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL,
log_interval, CTLFLAG_RW, &ip6_log_interval, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_HDRNESTLIMIT,
hdrnestlimit, CTLFLAG_RW, &ip6_hdrnestlimit, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DAD_COUNT,
dad_count, CTLFLAG_RW, &ip6_dad_count, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_AUTO_FLOWLABEL,
auto_flowlabel, CTLFLAG_RW, &ip6_auto_flowlabel, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFMCASTHLIM,
defmcasthlim, CTLFLAG_RW, &ip6_defmcasthlim, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM,
gifhlim, CTLFLAG_RW, &ip6_gif_hlim, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_USE_DEPRECATED,
use_deprecated, CTLFLAG_RW, &ip6_use_deprecated, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE,
rr_prune, CTLFLAG_RW, &ip6_rr_prune, 0, "");
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAPPED_ADDR,
mapped_addr, CTLFLAG_RW, &ip6_mapped_addr_on, 0, "");
/* net.inet6.icmp6 */
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRACCEPT,
rediraccept, CTLFLAG_RW, &icmp6_rediraccept, 0, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT,
redirtimeout, CTLFLAG_RW, &icmp6_redirtimeout, 0, "");
SYSCTL_STRUCT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats, CTLFLAG_RD,
&icmp6stat, icmp6stat, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ERRRATELIMIT,
errratelimit, CTLFLAG_RW, &icmp6errratelim, 0, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PRUNE,
nd6_prune, CTLFLAG_RW, &nd6_prune, 0, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DELAY,
nd6_delay, CTLFLAG_RW, &nd6_delay, 0, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_UMAXTRIES,
nd6_umaxtries, CTLFLAG_RW, &nd6_umaxtries, 0, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MMAXTRIES,
nd6_mmaxtries, CTLFLAG_RW, &nd6_mmaxtries, 0, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_USELOOPBACK,
nd6_useloopback, CTLFLAG_RW, &nd6_useloopback, 0, "");
SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PROXYALL,
nd6_proxyall, CTLFLAG_RW, &nd6_proxyall, 0, "");

477
sys/netinet6/in6_rmx.c Normal file
View file

@ -0,0 +1,477 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright 1994, 1995 Massachusetts Institute of Technology
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
* granted, provided that both the above copyright notice and this
* permission notice appear in all copies, that both the above
* copyright notice and this permission notice appear in all
* supporting documentation, and that the name of M.I.T. not be used
* in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission. M.I.T. makes
* no representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied
* warranty.
*
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
* SHALL M.I.T. 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.
*
* $Id: in6_rmx.c,v 1.3 1999/08/16 13:42:53 itojun Exp $
*/
/*
* This code does two things necessary for the enhanced TCP metrics to
* function in a useful manner:
* 1) It marks all non-host routes as `cloning', thus ensuring that
* every actual reference to such a route actually gets turned
* into a reference to a host route to the specific destination
* requested.
* 2) When such routes lose all their references, it arranges for them
* to be deleted in some random collection of circumstances, so that
* a large quantity of stale routing data is not kept in kernel memory
* indefinitely. See in6_rtqtimo() below for the exact mechanism.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/syslog.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/ip_var.h>
#include <netinet/in_var.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/icmp6.h>
#include <netinet/tcp.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
extern int in6_inithead __P((void **head, int off));
#define RTPRF_OURS RTF_PROTO3 /* set on routes we manage */
/*
* Do what we need to do when inserting a route.
*/
static struct radix_node *
in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
struct radix_node *treenodes)
{
struct rtentry *rt = (struct rtentry *)treenodes;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt);
struct radix_node *ret;
/*
* For IPv6, all unicast non-host routes are automatically cloning.
*/
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
rt->rt_flags |= RTF_MULTICAST;
if (!(rt->rt_flags & (RTF_HOST | RTF_CLONING | RTF_MULTICAST))) {
rt->rt_flags |= RTF_PRCLONING;
}
/*
* A little bit of help for both IPv6 output and input:
* For local addresses, we make sure that RTF_LOCAL is set,
* with the thought that this might one day be used to speed up
* ip_input().
*
* We also mark routes to multicast addresses as such, because
* it's easy to do and might be useful (but this is much more
* dubious since it's so easy to inspect the address). (This
* is done above.)
*
* XXX
* should elaborate the code.
*/
if (rt->rt_flags & RTF_HOST) {
if (IN6_ARE_ADDR_EQUAL(&satosin6(rt->rt_ifa->ifa_addr)
->sin6_addr,
&sin6->sin6_addr)) {
rt->rt_flags |= RTF_LOCAL;
}
}
/*
* We also specify a send and receive pipe size for every
* route added, to help TCP a bit. TCP doesn't actually
* want a true pipe size, which would be prohibitive in memory
* costs and is hard to compute anyway; it simply uses these
* values to size its buffers. So, we fill them in with the
* same values that TCP would have used anyway, and allow the
* installing program or the link layer to override these values
* as it sees fit. This will hopefully allow TCP more
* opportunities to save its ssthresh value.
*/
if (!rt->rt_rmx.rmx_sendpipe && !(rt->rt_rmx.rmx_locks & RTV_SPIPE))
rt->rt_rmx.rmx_sendpipe = tcp_sendspace;
if (!rt->rt_rmx.rmx_recvpipe && !(rt->rt_rmx.rmx_locks & RTV_RPIPE))
rt->rt_rmx.rmx_recvpipe = tcp_recvspace;
if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU)
&& rt->rt_ifp)
rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
ret = rn_addroute(v_arg, n_arg, head, treenodes);
if (ret == NULL && rt->rt_flags & RTF_HOST) {
struct rtentry *rt2;
/*
* We are trying to add a host route, but can't.
* Find out if it is because of an
* ARP entry and delete it if so.
*/
rt2 = rtalloc1((struct sockaddr *)sin6, 0,
RTF_CLONING | RTF_PRCLONING);
if (rt2) {
if (rt2->rt_flags & RTF_LLINFO &&
rt2->rt_flags & RTF_HOST &&
rt2->rt_gateway &&
rt2->rt_gateway->sa_family == AF_LINK) {
rtrequest(RTM_DELETE,
(struct sockaddr *)rt_key(rt2),
rt2->rt_gateway,
rt_mask(rt2), rt2->rt_flags, 0);
ret = rn_addroute(v_arg, n_arg, head,
treenodes);
}
RTFREE(rt2);
}
} else if (ret == NULL && rt->rt_flags & RTF_CLONING) {
struct rtentry *rt2;
/*
* We are trying to add a net route, but can't.
* The following case should be allowed, so we'll make a
* special check for this:
* Two IPv6 addresses with the same prefix is assigned
* to a single interrface.
* # ifconfig if0 inet6 3ffe:0501::1 prefix 64 alias (*1)
* # ifconfig if0 inet6 3ffe:0501::2 prefix 64 alias (*2)
* In this case, (*1) and (*2) want to add the same
* net route entry, 3ffe:0501:: -> if0.
* This case should not raise an error.
*/
rt2 = rtalloc1((struct sockaddr *)sin6, 0,
RTF_CLONING | RTF_PRCLONING);
if (rt2) {
if ((rt2->rt_flags & (RTF_CLONING|RTF_HOST|RTF_GATEWAY))
== RTF_CLONING
&& rt2->rt_gateway
&& rt2->rt_gateway->sa_family == AF_LINK
&& rt2->rt_ifp == rt->rt_ifp) {
ret = rt2->rt_nodes;
}
RTFREE(rt2);
}
}
return ret;
}
/*
* This code is the inverse of in6_clsroute: on first reference, if we
* were managing the route, stop doing so and set the expiration timer
* back off again.
*/
static struct radix_node *
in6_matroute(void *v_arg, struct radix_node_head *head)
{
struct radix_node *rn = rn_match(v_arg, head);
struct rtentry *rt = (struct rtentry *)rn;
if (rt && rt->rt_refcnt == 0) { /* this is first reference */
if (rt->rt_flags & RTPRF_OURS) {
rt->rt_flags &= ~RTPRF_OURS;
rt->rt_rmx.rmx_expire = 0;
}
}
return rn;
}
static int rtq_reallyold = 60*60;
/* one hour is ``really old'' */
SYSCTL_INT(_net_inet_ip, IPCTL_RTEXPIRE, rtexpire,
CTLFLAG_RW, &rtq_reallyold , 0, "");
static int rtq_minreallyold = 10;
/* never automatically crank down to less */
SYSCTL_INT(_net_inet_ip, IPCTL_RTMINEXPIRE, rtminexpire,
CTLFLAG_RW, &rtq_minreallyold , 0, "");
static int rtq_toomany = 128;
/* 128 cached routes is ``too many'' */
SYSCTL_INT(_net_inet_ip, IPCTL_RTMAXCACHE, rtmaxcache,
CTLFLAG_RW, &rtq_toomany , 0, "");
/*
* On last reference drop, mark the route as belong to us so that it can be
* timed out.
*/
static void
in6_clsroute(struct radix_node *rn, struct radix_node_head *head)
{
struct rtentry *rt = (struct rtentry *)rn;
if (!(rt->rt_flags & RTF_UP))
return; /* prophylactic measures */
if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
return;
if ((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS))
!= RTF_WASCLONED)
return;
/*
* As requested by David Greenman:
* If rtq_reallyold is 0, just delete the route without
* waiting for a timeout cycle to kill it.
*/
if (rtq_reallyold != 0) {
rt->rt_flags |= RTPRF_OURS;
rt->rt_rmx.rmx_expire = time_second + rtq_reallyold;
} else {
rtrequest(RTM_DELETE,
(struct sockaddr *)rt_key(rt),
rt->rt_gateway, rt_mask(rt),
rt->rt_flags, 0);
}
}
struct rtqk_arg {
struct radix_node_head *rnh;
int mode;
int updating;
int draining;
int killed;
int found;
time_t nextstop;
};
/*
* Get rid of old routes. When draining, this deletes everything, even when
* the timeout is not expired yet. When updating, this makes sure that
* nothing has a timeout longer than the current value of rtq_reallyold.
*/
static int
in6_rtqkill(struct radix_node *rn, void *rock)
{
struct rtqk_arg *ap = rock;
struct rtentry *rt = (struct rtentry *)rn;
int err;
if (rt->rt_flags & RTPRF_OURS) {
ap->found++;
if (ap->draining || rt->rt_rmx.rmx_expire <= time_second) {
if (rt->rt_refcnt > 0)
panic("rtqkill route really not free");
err = rtrequest(RTM_DELETE,
(struct sockaddr *)rt_key(rt),
rt->rt_gateway, rt_mask(rt),
rt->rt_flags, 0);
if (err) {
log(LOG_WARNING, "in6_rtqkill: error %d", err);
} else {
ap->killed++;
}
} else {
if (ap->updating
&& (rt->rt_rmx.rmx_expire - time_second
> rtq_reallyold)) {
rt->rt_rmx.rmx_expire = time_second
+ rtq_reallyold;
}
ap->nextstop = lmin(ap->nextstop,
rt->rt_rmx.rmx_expire);
}
}
return 0;
}
#define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */
static int rtq_timeout = RTQ_TIMEOUT;
static void
in6_rtqtimo(void *rock)
{
struct radix_node_head *rnh = rock;
struct rtqk_arg arg;
struct timeval atv;
static time_t last_adjusted_timeout = 0;
int s;
arg.found = arg.killed = 0;
arg.rnh = rnh;
arg.nextstop = time_second + rtq_timeout;
arg.draining = arg.updating = 0;
s = splnet();
rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
splx(s);
/*
* Attempt to be somewhat dynamic about this:
* If there are ``too many'' routes sitting around taking up space,
* then crank down the timeout, and see if we can't make some more
* go away. However, we make sure that we will never adjust more
* than once in rtq_timeout seconds, to keep from cranking down too
* hard.
*/
if ((arg.found - arg.killed > rtq_toomany)
&& (time_second - last_adjusted_timeout >= rtq_timeout)
&& rtq_reallyold > rtq_minreallyold) {
rtq_reallyold = 2*rtq_reallyold / 3;
if (rtq_reallyold < rtq_minreallyold) {
rtq_reallyold = rtq_minreallyold;
}
last_adjusted_timeout = time_second;
#ifdef DIAGNOSTIC
log(LOG_DEBUG, "in6_rtqtimo: adjusted rtq_reallyold to %d",
rtq_reallyold);
#endif
arg.found = arg.killed = 0;
arg.updating = 1;
s = splnet();
rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
splx(s);
}
atv.tv_usec = 0;
atv.tv_sec = arg.nextstop;
timeout(in6_rtqtimo, rock, tvtohz(&atv));
}
/*
* Age old PMTUs.
*/
struct mtuex_arg {
struct radix_node_head *rnh;
time_t nextstop;
};
static int
in6_mtuexpire(struct radix_node *rn, void *rock)
{
struct rtentry *rt = (struct rtentry *)rn;
struct mtuex_arg *ap = rock;
/* sanity */
if (!rt)
panic("rt == NULL in in6_mtuexpire");
if (rt->rt_rmx.rmx_expire && !(rt->rt_flags & RTF_PROBEMTU)) {
if (rt->rt_rmx.rmx_expire <= time_second) {
rt->rt_flags |= RTF_PROBEMTU;
} else {
ap->nextstop = lmin(ap->nextstop,
rt->rt_rmx.rmx_expire);
}
}
return 0;
}
#define MTUTIMO_DEFAULT (60*1)
static void
in6_mtutimo(void *rock)
{
struct radix_node_head *rnh = rock;
struct mtuex_arg arg;
struct timeval atv;
int s;
arg.rnh = rnh;
arg.nextstop = time_second + MTUTIMO_DEFAULT;
s = splnet();
rnh->rnh_walktree(rnh, in6_mtuexpire, &arg);
splx(s);
atv.tv_usec = 0;
atv.tv_sec = arg.nextstop;
if (atv.tv_sec < time_second) {
printf("invalid mtu expiration time on routing table\n");
arg.nextstop = time_second + 30; /*last resort*/
}
timeout(in6_mtutimo, rock, tvtohz(&atv));
}
/*
* Initialize our routing tree.
*/
int
in6_inithead(void **head, int off)
{
struct radix_node_head *rnh;
if (!rn_inithead(head, off))
return 0;
if (head != (void **)&rt_tables[AF_INET6]) /* BOGUS! */
return 1; /* only do this for the real routing table */
rnh = *head;
rnh->rnh_addaddr = in6_addroute;
rnh->rnh_matchaddr = in6_matroute;
rnh->rnh_close = in6_clsroute;
in6_rtqtimo(rnh); /* kick off timeout first time */
in6_mtutimo(rnh); /* kick off timeout first time */
return 1;
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@ -13,7 +13,7 @@
* 3. Neither the name of the project 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 PROJECT 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
@ -98,10 +98,6 @@ struct in6_ifaddr {
struct sockaddr_in6 ia_prefixmask; /* prefix mask */
u_int32_t ia_plen; /* prefix length */
struct in6_ifaddr *ia_next; /* next in6 list of IP6 addresses */
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
LIST_HEAD(in6_multihead, in6_multi) ia6_multiaddrs;
/* list of multicast addresses */
#endif
int ia6_flags;
struct in6_addrlifetime ia6_lifetime; /* NULL = infty */
@ -189,7 +185,7 @@ struct icmp6_ifstat {
u_int64_t ifs6_in_mlddone;
/*
* Output statistics. We should solve unresolved routing problem...
* Output statistics. We should solve unresolved routing problem...
*/
/* ipv6IfIcmpOutMsgs, total # of output messages */
u_int64_t ifs6_out_msg;
@ -428,34 +424,14 @@ extern struct ifqueue ip6intrq; /* IP6 packet input queue */
extern struct in6_addr zeroin6_addr;
extern u_char inet6ctlerrmap[];
extern u_long in6_maxmtu;
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_IPMADDR);
#endif /* MALLOC_DECLARE */
#endif
/*
* Macro for finding the internet address structure (in6_ifaddr) corresponding
* to a given interface (ifnet structure).
*/
#if defined(__bsdi__) || (defined(__FreeBSD__) && __FreeBSD__ < 3)
#define IFP_TO_IA6(ifp, ia) \
/* struct ifnet *ifp; */ \
/* struct in6_ifaddr *ia; */ \
do { \
struct ifaddr *ifa; \
for (ifa = (ifp)->if_addrlist; ifa; ifa = ifa->ifa_next) { \
if (!ifa->ifa_addr) \
continue; \
if (ifa->ifa_addr->sa_family == AF_INET6) \
break; \
} \
(ia) = (struct in6_ifaddr *)ifa; \
} while (0)
#else
#define IFP_TO_IA6(ifp, ia) \
/* struct ifnet *ifp; */ \
/* struct in6_ifaddr *ia; */ \
@ -471,8 +447,6 @@ do { \
} while (0)
#endif /* _KERNEL */
#endif
/*
* Multi-cast membership entry. One for each group/ifp that a PCB
* belongs to.
@ -486,20 +460,14 @@ struct in6_multi {
LIST_ENTRY(in6_multi) in6m_entry; /* list glue */
struct in6_addr in6m_addr; /* IP6 multicast address */
struct ifnet *in6m_ifp; /* back pointer to ifnet */
#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
struct in6_ifaddr *in6m_ia; /* back pointer to in6_ifaddr */
#else
struct ifmultiaddr *in6m_ifma; /* back pointer to ifmultiaddr */
#endif
u_int in6m_refcount; /* # membership claims by sockets */
u_int in6m_state; /* state of the membership */
u_int in6m_timer; /* MLD6 listener report timer */
};
#ifdef _KERNEL
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
extern LIST_HEAD(in6_multihead, in6_multi) in6_multihead;
#endif
/*
* Structure used by macros below to remember position when stepping through
@ -516,8 +484,6 @@ struct in6_multistep {
* returns NLL.
*/
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#define IN6_LOOKUP_MULTI(addr, ifp, in6m) \
/* struct in6_addr addr; */ \
/* struct ifnet *ifp; */ \
@ -557,61 +523,6 @@ do { \
IN6_NEXT_MULTI((step), (in6m)); \
} while(0)
#else /* not FreeBSD3 */
#define IN6_LOOKUP_MULTI(addr, ifp, in6m) \
/* struct in6_addr addr; */ \
/* struct ifnet *ifp; */ \
/* struct in6_multi *in6m; */ \
do { \
register struct in6_ifaddr *ia; \
\
IFP_TO_IA6((ifp), ia); \
if (ia == NULL) \
(in6m) = NULL; \
else \
for ((in6m) = ia->ia6_multiaddrs.lh_first; \
(in6m) != NULL && \
!IN6_ARE_ADDR_EQUAL(&(in6m)->in6m_addr, &(addr)); \
(in6m) = in6m->in6m_entry.le_next) \
continue; \
} while (0)
/*
* Macro to step through all of the in6_multi records, one at a time.
* The current position is remembered in "step", which the caller must
* provide. IN6_FIRST_MULTI(), below, must be called to initialize "step"
* and get the first record. Both macros return a NULL "in6m" when there
* are no remaining records.
*/
#define IN6_NEXT_MULTI(step, in6m) \
/* struct in6_multistep step; */ \
/* struct in6_multi *in6m; */ \
do { \
if (((in6m) = (step).i_in6m) != NULL) \
(step).i_in6m = (in6m)->in6m_entry.le_next; \
else \
while ((step).i_ia != NULL) { \
(in6m) = (step).i_ia->ia6_multiaddrs.lh_first; \
(step).i_ia = (step).i_ia->ia_next; \
if ((in6m) != NULL) { \
(step).i_in6m = (in6m)->in6m_entry.le_next; \
break; \
} \
} \
} while (0)
#define IN6_FIRST_MULTI(step, in6m) \
/* struct in6_multistep step; */ \
/* struct in6_multi *in6m */ \
do { \
(step).i_ia = in6_ifaddr; \
(step).i_in6m = NULL; \
IN6_NEXT_MULTI((step), (in6m)); \
} while (0)
#endif /* not FreeBSD3 */
int in6_ifinit __P((struct ifnet *,
struct in6_ifaddr *, struct sockaddr_in6 *, int));
struct in6_multi *in6_addmulti __P((struct in6_addr *, struct ifnet *,
@ -621,12 +532,8 @@ void in6_ifscrub __P((struct ifnet *, struct in6_ifaddr *));
extern int in6_ifindex2scopeid __P((int));
extern int in6_mask2len __P((struct in6_addr *));
extern void in6_len2mask __P((struct in6_addr *, int));
#if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
int in6_control __P((struct socket *,
u_long, caddr_t, struct ifnet *, struct proc *));
#else
int in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *));
#endif
u_long, caddr_t, struct ifnet *, struct proc *));
void in6_savemkludge __P((struct in6_ifaddr *));
void in6_setmaxmtu __P((void));
void in6_restoremkludge __P((struct in6_ifaddr *, struct ifnet *));

245
sys/netinet6/ip6.h Normal file
View file

@ -0,0 +1,245 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)ip.h 8.1 (Berkeley) 6/10/93
*/
#ifndef _NETINET6_IPV6_H_
#define _NETINET6_IPV6_H_
/*
* Definition for internet protocol version 6.
* RFC 2460
*/
struct ip6_hdr {
union {
struct ip6_hdrctl {
u_int32_t ip6_un1_flow; /* 20 bits of flow-ID */
u_int16_t ip6_un1_plen; /* payload length */
u_int8_t ip6_un1_nxt; /* next header */
u_int8_t ip6_un1_hlim; /* hop limit */
} ip6_un1;
u_int8_t ip6_un2_vfc; /* 4 bits version, 4 bits class */
} ip6_ctlun;
struct in6_addr ip6_src; /* source address */
struct in6_addr ip6_dst; /* destination address */
};
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
#define IPV6_VERSION 0x60
#define IPV6_VERSION_MASK 0xf0
#if BYTE_ORDER == BIG_ENDIAN
#define IPV6_FLOWINFO_MASK 0x0fffffff /* flow info (28 bits) */
#define IPV6_FLOWLABEL_MASK 0x000fffff /* flow label (20 bits) */
#endif /* BIG_ENDIAN */
#if BYTE_ORDER == LITTLE_ENDIAN
#define IPV6_FLOWINFO_MASK 0xffffff0f /* flow info (28 bits) */
#define IPV6_FLOWLABEL_MASK 0xffff0f00 /* flow label (20 bits) */
#endif /* LITTLE_ENDIAN */
/* ECN bits proposed by Sally Floyd */
#define IP6TOS_CE 0x01 /* congestion experienced */
#define IP6TOS_ECT 0x02 /* ECN-capable transport */
/*
* Extension Headers
*/
struct ip6_ext {
u_char ip6e_nxt;
u_char ip6e_len;
};
/* Hop-by-Hop options header */
/* XXX should we pad it to force alignment on an 8-byte boundary? */
struct ip6_hbh {
u_int8_t ip6h_nxt; /* next header */
u_int8_t ip6h_len; /* length in units of 8 octets */
/* followed by options */
};
/* Destination options header */
/* XXX should we pad it to force alignment on an 8-byte boundary? */
struct ip6_dest {
u_int8_t ip6d_nxt; /* next header */
u_int8_t ip6d_len; /* length in units of 8 octets */
/* followed by options */
};
/* Option types and related macros */
#define IP6OPT_PAD1 0x00 /* 00 0 00000 */
#define IP6OPT_PADN 0x01 /* 00 0 00001 */
#define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */
#define IP6OPT_JUMBO_LEN 6
#define IP6OPT_RTALERT 0x05 /* 00 0 00101 */
#define IP6OPT_RTALERT_LEN 4
#define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */
#define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */
#define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */
#define IP6OPT_MINLEN 2
#define IP6OPT_TYPE(o) ((o) & 0xC0)
#define IP6OPT_TYPE_SKIP 0x00
#define IP6OPT_TYPE_DISCARD 0x40
#define IP6OPT_TYPE_FORCEICMP 0x80
#define IP6OPT_TYPE_ICMP 0xC0
#define IP6OPT_MUTABLE 0x20
/* Routing header */
struct ip6_rthdr {
u_int8_t ip6r_nxt; /* next header */
u_int8_t ip6r_len; /* length in units of 8 octets */
u_int8_t ip6r_type; /* routing type */
u_int8_t ip6r_segleft; /* segments left */
/* followed by routing type specific data */
};
/* Type 0 Routing header */
struct ip6_rthdr0 {
u_int8_t ip6r0_nxt; /* next header */
u_int8_t ip6r0_len; /* length in units of 8 octets */
u_int8_t ip6r0_type; /* always zero */
u_int8_t ip6r0_segleft; /* segments left */
u_int8_t ip6r0_reserved; /* reserved field */
u_int8_t ip6r0_slmap[3]; /* strict/loose bit map */
struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */
};
/* Fragment header */
struct ip6_frag {
u_int8_t ip6f_nxt; /* next header */
u_int8_t ip6f_reserved; /* reserved field */
u_int16_t ip6f_offlg; /* offset, reserved, and flag */
u_int32_t ip6f_ident; /* identification */
};
#if BYTE_ORDER == BIG_ENDIAN
#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */
#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */
#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
/*
* Internet implementation parameters.
*/
#define IPV6_MAXHLIM 255 /* maximun hoplimit */
#define IPV6_DEFHLIM 64 /* default hlim */
#define IPV6_FRAGTTL 120 /* ttl for fragment packets, in slowtimo tick */
#define IPV6_HLIMDEC 1 /* subtracted when forwaeding */
#define IPV6_MMTU 1280 /* minimal MTU and reassembly. 1024 + 256 */
#define IPV6_MAXPACKET 65535 /* ip6 max packet size without Jumbo payload*/
/*
* IP6_EXTHDR_CHECK ensures that region between the IP6 header and the
* target header (including IPv6 itself, extension headers and
* TCP/UDP/ICMP6 headers) are continuous. KAME requires drivers
* to store incoming data into one internal mbuf or one or more external
* mbufs(never into two or more internal mbufs). Thus, the third case is
* supposed to never be matched but is prepared just in case.
*/
#define IP6_EXTHDR_CHECK(m, off, hlen, ret) \
do { \
if ((m)->m_next != NULL) { \
if (((m)->m_flags & M_LOOP) && \
((m)->m_len < (off) + (hlen)) && \
(((m) = m_pullup((m), (off) + (hlen))) == NULL)) { \
ip6stat.ip6s_exthdrtoolong++; \
return ret; \
} else if ((m)->m_flags & M_EXT) { \
if ((m)->m_len < (off) + (hlen)) { \
ip6stat.ip6s_exthdrtoolong++; \
m_freem(m); \
return ret; \
} \
} else { \
if ((m)->m_len < (off) + (hlen)) { \
ip6stat.ip6s_exthdrtoolong++; \
m_freem(m); \
return ret; \
} \
} \
} else { \
if ((m)->m_len < (off) + (hlen)) { \
ip6stat.ip6s_tooshort++; \
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); \
m_freem(m); \
return ret; \
} \
} \
} while (0)
#endif /* not _NETINET_IPV6_H_ */

391
sys/netinet6/ip6_forward.c Normal file
View file

@ -0,0 +1,391 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#include "opt_ip6fw.h"
#include "opt_inet.h"
#include "opt_ipsec.h"
#include "opt_key.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/syslog.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/icmp6.h>
#include <netinet6/nd6.h>
#ifdef IPSEC_IPV6FWD
#include <netinet6/ipsec.h>
#ifdef INET6
#include <netinet6/ipsec6.h>
#endif /* INET6 */
#include <netkey/key.h>
#ifdef KEY_DEBUG
#include <netkey/key_debug.h>
#ifdef INET6
#include <netkey/key_debug6.h>
#endif /* INET6 */
#else
#define DPRINTF(lev,arg)
#define DDO(lev, stmt)
#define DP(x, y, z)
#endif /* KEY_DEBUG */
#endif /* IPSEC_IPV6FWD */
#ifdef IPV6FIREWALL
#include <netinet6/ip6_fw.h>
#endif
#include <net/net_osdep.h>
struct route_in6 ip6_forward_rt;
/*
* Forward a packet. If some error occurs return the sender
* an icmp packet. Note we can't always generate a meaningful
* icmp message because icmp doesn't have a large enough repertoire
* of codes and types.
*
* If not forwarding, just drop the packet. This could be confusing
* if ipforwarding was zero but some routing protocol was advancing
* us as a gateway to somewhere. However, we must let the routing
* protocol deal with that.
*
*/
void
ip6_forward(m, srcrt)
struct mbuf *m;
int srcrt;
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
register struct sockaddr_in6 *dst;
register struct rtentry *rt;
int error, type = 0, code = 0;
struct mbuf *mcopy;
#ifdef IPSEC_IPV6FWD
struct secpolicy *sp = NULL;
#endif
#ifdef IPSEC_IPV6FWD
/*
* Check AH/ESP integrity.
*/
/*
* Don't increment ip6s_cantforward because this is the check
* before forwarding packet actually.
*/
if (ipsec6_in_reject(m, NULL)) {
ipsec6stat.in_polvio++;
m_freem(m);
return;
}
#endif /*IPSEC_IPV6FWD*/
if (m->m_flags & (M_BCAST|M_MCAST) ||
in6_canforward(&ip6->ip6_src, &ip6->ip6_dst) == 0) {
ip6stat.ip6s_cantforward++;
ip6stat.ip6s_badscope++;
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
if (ip6_log_time + ip6_log_interval < time_second) {
char addr[INET6_ADDRSTRLEN];
ip6_log_time = time_second;
strncpy(addr, ip6_sprintf(&ip6->ip6_src), sizeof(addr));
log(LOG_DEBUG,
"cannot forward "
"from %s to %s nxt %d received on %s\n",
addr, ip6_sprintf(&ip6->ip6_dst),
ip6->ip6_nxt,
if_name(m->m_pkthdr.rcvif));
}
m_freem(m);
return;
}
if (ip6->ip6_hlim <= IPV6_HLIMDEC) {
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
icmp6_error(m, ICMP6_TIME_EXCEEDED,
ICMP6_TIME_EXCEED_TRANSIT, 0);
return;
}
ip6->ip6_hlim -= IPV6_HLIMDEC;
#ifdef IPSEC_IPV6FWD
/* get a security policy for this packet */
sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
if (sp == NULL) {
ipsec6stat.out_inval++;
ip6stat.ip6s_cantforward++;
/* XXX: any icmp ? */
m_freem(m);
return;
}
error = 0;
/* check policy */
switch (sp->policy) {
case IPSEC_POLICY_DISCARD:
/*
* This packet is just discarded.
*/
ipsec6stat.out_polvio++;
ip6stat.ip6s_cantforward++;
key_freesp(sp);
/* XXX: any icmp ? */
m_freem(m);
return;
case IPSEC_POLICY_BYPASS:
case IPSEC_POLICY_NONE:
/* no need to do IPsec. */
key_freesp(sp);
goto skip_ipsec;
case IPSEC_POLICY_IPSEC:
if (sp->req == NULL) {
/* XXX should be panic ? */
printf("ip6_forward: No IPsec request specified.\n");
ip6stat.ip6s_cantforward++;
key_freesp(sp);
/* XXX: any icmp ? */
m_freem(m);
return;
}
/* do IPsec */
break;
case IPSEC_POLICY_ENTRUST:
default:
/* should be panic ?? */
printf("ip6_forward: Invalid policy found. %d\n", sp->policy);
key_freesp(sp);
goto skip_ipsec;
}
{
struct ipsec_output_state state;
/*
* All the extension headers will become inaccessible
* (since they can be encrypted).
* Don't panic, we need no more updates to extension headers
* on inner IPv6 packet (since they are now encapsulated).
*
* IPv6 [ESP|AH] IPv6 [extension headers] payload
*/
bzero(&state, sizeof(state));
state.m = m;
state.ro = NULL; /* update at ipsec6_output_tunnel() */
state.dst = NULL; /* update at ipsec6_output_tunnel() */
error = ipsec6_output_tunnel(&state, sp, 0);
m = state.m;
/* XXX allocate a route (ro, dst) again later */
key_freesp(sp);
if (error) {
/* mbuf is already reclaimed in ipsec6_output_tunnel. */
switch (error) {
case EHOSTUNREACH:
case ENETUNREACH:
case EMSGSIZE:
case ENOBUFS:
case ENOMEM:
break;
default:
printf("ip6_output (ipsec): error code %d\n", error);
/*fall through*/
case ENOENT:
/* don't show these error codes to the user */
break;
}
ip6stat.ip6s_cantforward++;
/* XXX: any icmp ? */
m_freem(m);
return;
}
}
skip_ipsec:
#endif /* IPSEC_IPV6FWD */
dst = &ip6_forward_rt.ro_dst;
if (!srcrt) {
/*
* ip6_forward_rt.ro_dst.sin6_addr is equal to ip6->ip6_dst
*/
if (ip6_forward_rt.ro_rt == 0 ||
(ip6_forward_rt.ro_rt->rt_flags & RTF_UP) == 0) {
if (ip6_forward_rt.ro_rt) {
RTFREE(ip6_forward_rt.ro_rt);
ip6_forward_rt.ro_rt = 0;
}
/* this probably fails but give it a try again */
rtalloc_ign((struct route *)&ip6_forward_rt,
RTF_PRCLONING);
}
if (ip6_forward_rt.ro_rt == 0) {
ip6stat.ip6s_noroute++;
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
icmp6_error(m, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
return;
}
} else if ((rt = ip6_forward_rt.ro_rt) == 0 ||
!IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &dst->sin6_addr)) {
if (ip6_forward_rt.ro_rt) {
RTFREE(ip6_forward_rt.ro_rt);
ip6_forward_rt.ro_rt = 0;
}
bzero(dst, sizeof(*dst));
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_family = AF_INET6;
dst->sin6_addr = ip6->ip6_dst;
rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
if (ip6_forward_rt.ro_rt == 0) {
ip6stat.ip6s_noroute++;
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_noroute) */
icmp6_error(m, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
return;
}
}
rt = ip6_forward_rt.ro_rt;
if (m->m_pkthdr.len > rt->rt_ifp->if_mtu){
in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
icmp6_error(m, ICMP6_PACKET_TOO_BIG, 0, rt->rt_ifp->if_mtu);
return;
}
if (rt->rt_flags & RTF_GATEWAY)
dst = (struct sockaddr_in6 *)rt->rt_gateway;
/*
* Save at most 528 bytes of the packet in case
* we need to generate an ICMP6 message to the src.
* Thanks to M_EXT, in most cases copy will not occur.
*/
mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
/*
* If we are to forward the packet using the same interface
* as one we got the packet from, perhaps we should send a redirect
* to sender to shortcut a hop.
* Only send redirect if source is sending directly to us,
* and if packet was not source routed (or has any options).
* Also, don't send redirect if forwarding using a route
* modified by a redirect.
*/
if (rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0)
type = ND_REDIRECT;
#ifdef IPV6FIREWALL
/*
* Check with the firewall...
*/
if (ip6_fw_chk_ptr) {
u_short port = 0;
/* If ipfw says divert, we have to just drop packet */
if ((*ip6_fw_chk_ptr)(&ip6, rt->rt_ifp, &port, &m)) {
m_freem(m);
goto freecopy;
}
if (!m)
goto freecopy;
}
#endif
error = nd6_output(rt->rt_ifp, m, dst, rt);
if (error) {
in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
ip6stat.ip6s_cantforward++;
} else {
ip6stat.ip6s_forward++;
in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward);
if (type)
ip6stat.ip6s_redirectsent++;
else {
if (mcopy)
goto freecopy;
}
}
if (mcopy == NULL)
return;
switch (error) {
case 0:
if (type == ND_REDIRECT) {
icmp6_redirect_output(mcopy, rt);
return;
}
goto freecopy;
case EMSGSIZE:
/* xxx MTU is constant in PPP? */
goto freecopy;
case ENOBUFS:
/* Tell source to slow down like source quench in IP? */
goto freecopy;
case ENETUNREACH: /* shouldn't happen, checked above */
case EHOSTUNREACH:
case ENETDOWN:
case EHOSTDOWN:
default:
type = ICMP6_DST_UNREACH;
code = ICMP6_DST_UNREACH_ADDR;
break;
}
icmp6_error(mcopy, type, code, 0);
return;
freecopy:
m_freem(mcopy);
return;
}

202
sys/netinet6/ip6_fw.h Normal file
View file

@ -0,0 +1,202 @@
/*
* Copyright (c) 1993 Daniel Boulet
* Copyright (c) 1994 Ugen J.S.Antsilevich
*
* Redistribution and use in source forms, with and without modification,
* are permitted provided that this entire comment appears intact.
*
* Redistribution in binary form may occur without any restrictions.
* Obviously, it would be nice if you gave credit where credit is due
* but requiring it would be too onerous.
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
* $Id: ip6_fw.h,v 1.1 1999/08/06 14:10:09 itojun Exp $
* $FreeBSD$
*/
#ifndef _IP6_FW_H
#define _IP6_FW_H
#include <net/if.h>
/*
* This union structure identifies an interface, either explicitly
* by name or implicitly by IP address. The flags IP_FW_F_IIFNAME
* and IP_FW_F_OIFNAME say how to interpret this structure. An
* interface unit number of -1 matches any unit number, while an
* IP address of 0.0.0.0 indicates matches any interface.
*
* The receive and transmit interfaces are only compared against the
* the packet if the corresponding bit (IP_FW_F_IIFACE or IP_FW_F_OIFACE)
* is set. Note some packets lack a receive or transmit interface
* (in which case the missing "interface" never matches).
*/
union ip6_fw_if {
struct in6_addr fu_via_ip6; /* Specified by IPv6 address */
struct { /* Specified by interface name */
#define FW_IFNLEN IFNAMSIZ
char name[FW_IFNLEN];
short unit; /* -1 means match any unit */
} fu_via_if;
};
/*
* Format of an IP firewall descriptor
*
* fw_src, fw_dst, fw_smsk, fw_dmsk are always stored in network byte order.
* fw_flg and fw_n*p are stored in host byte order (of course).
* Port numbers are stored in HOST byte order.
* Warning: setsockopt() will fail if sizeof(struct ip_fw) > MLEN (108)
*/
struct ip6_fw {
u_long fw_pcnt,fw_bcnt; /* Packet and byte counters */
struct in6_addr fw_src, fw_dst; /* Source and destination IPv6 addr */
/* Mask for src and dest IPv6 addr */
struct in6_addr fw_smsk, fw_dmsk;
u_short fw_number; /* Rule number */
u_short fw_flg; /* Flags word */
#define IPV6_FW_MAX_PORTS 10 /* A reasonable maximum */
/* Array of port numbers to match */
u_short fw_pts[IPV6_FW_MAX_PORTS];
u_char fw_ip6opt,fw_ip6nopt; /* IPv6 options set/unset */
u_char fw_tcpf,fw_tcpnf; /* TCP flags set/unset */
#define IPV6_FW_ICMPTYPES_DIM (32 / (sizeof(unsigned) * 8))
/* ICMP types bitmap */
unsigned fw_icmp6types[IPV6_FW_ICMPTYPES_DIM];
long timestamp; /* timestamp (tv_sec) of last match */
/* Incoming and outgoing interfaces */
union ip6_fw_if fw_in_if, fw_out_if;
union {
u_short fu_divert_port; /* Divert/tee port (options IP6DIVERT) */
u_short fu_skipto_rule; /* SKIPTO command rule number */
u_short fu_reject_code; /* REJECT response code */
} fw_un;
u_char fw_prot; /* IPv6 protocol */
u_char fw_nports; /* N'of src ports and # of dst ports */
/* in ports array (dst ports follow */
/* src ports; max of 10 ports in all; */
/* count of 0 means match all ports) */
};
#define IPV6_FW_GETNSRCP(rule) ((rule)->fw_nports & 0x0f)
#define IPV6_FW_SETNSRCP(rule, n) do { \
(rule)->fw_nports &= ~0x0f; \
(rule)->fw_nports |= (n); \
} while (0)
#define IPV6_FW_GETNDSTP(rule) ((rule)->fw_nports >> 4)
#define IPV6_FW_SETNDSTP(rule, n) do { \
(rule)->fw_nports &= ~0xf0; \
(rule)->fw_nports |= (n) << 4;\
} while (0)
#define fw_divert_port fw_un.fu_divert_port
#define fw_skipto_rule fw_un.fu_skipto_rule
#define fw_reject_code fw_un.fu_reject_code
struct ip6_fw_chain {
LIST_ENTRY(ip6_fw_chain) chain;
struct ip6_fw *rule;
};
/*
* Values for "flags" field .
*/
#define IPV6_FW_F_IN 0x0001 /* Check inbound packets */
#define IPV6_FW_F_OUT 0x0002 /* Check outbound packets */
#define IPV6_FW_F_IIFACE 0x0004 /* Apply inbound interface test */
#define IPV6_FW_F_OIFACE 0x0008 /* Apply outbound interface test */
#define IPV6_FW_F_COMMAND 0x0070 /* Mask for type of chain entry: */
#define IPV6_FW_F_DENY 0x0000 /* This is a deny rule */
#define IPV6_FW_F_REJECT 0x0010 /* Deny and send a response packet */
#define IPV6_FW_F_ACCEPT 0x0020 /* This is an accept rule */
#define IPV6_FW_F_COUNT 0x0030 /* This is a count rule */
#define IPV6_FW_F_DIVERT 0x0040 /* This is a divert rule */
#define IPV6_FW_F_TEE 0x0050 /* This is a tee rule */
#define IPV6_FW_F_SKIPTO 0x0060 /* This is a skipto rule */
#define IPV6_FW_F_PRN 0x0080 /* Print if this rule matches */
#define IPV6_FW_F_SRNG 0x0100 /* The first two src ports are a min *
* and max range (stored in host byte *
* order). */
#define IPV6_FW_F_DRNG 0x0200 /* The first two dst ports are a min *
* and max range (stored in host byte *
* order). */
/* In interface by name/unit (not IP) */
#define IPV6_FW_F_IIFNAME 0x0400
/* Out interface by name/unit (not IP) */
#define IPV6_FW_F_OIFNAME 0x0800
#define IPV6_FW_F_INVSRC 0x1000 /* Invert sense of src check */
#define IPV6_FW_F_INVDST 0x2000 /* Invert sense of dst check */
#define IPV6_FW_F_FRAG 0x4000 /* Fragment */
#define IPV6_FW_F_ICMPBIT 0x8000 /* ICMP type bitmap is valid */
#define IPV6_FW_F_MASK 0xFFFF /* All possible flag bits mask */
/*
* For backwards compatibility with rules specifying "via iface" but
* not restricted to only "in" or "out" packets, we define this combination
* of bits to represent this configuration.
*/
#define IF6_FW_F_VIAHACK (IPV6_FW_F_IN|IPV6_FW_F_OUT|IPV6_FW_F_IIFACE|\
IPV6_FW_F_OIFACE)
/*
* Definitions for REJECT response codes.
* Values less than 256 correspond to ICMP unreachable codes.
*/
#define IPV6_FW_REJECT_RST 0x0100 /* TCP packets: send RST */
/*
* Definitions for IPv6 option names.
*/
#define IPV6_FW_IP6OPT_HOPOPT 0x01
#define IPV6_FW_IP6OPT_ROUTE 0x02
#define IPV6_FW_IP6OPT_FRAG 0x04
#define IPV6_FW_IP6OPT_ESP 0x08
#define IPV6_FW_IP6OPT_AH 0x10
#define IPV6_FW_IP6OPT_NONXT 0x20
#define IPV6_FW_IP6OPT_OPTS 0x40
/*
* Definitions for TCP flags.
*/
#define IPV6_FW_TCPF_FIN TH_FIN
#define IPV6_FW_TCPF_SYN TH_SYN
#define IPV6_FW_TCPF_RST TH_RST
#define IPV6_FW_TCPF_PSH TH_PUSH
#define IPV6_FW_TCPF_ACK TH_ACK
#define IPV6_FW_TCPF_URG TH_URG
#define IPV6_FW_TCPF_ESTAB 0x40
/*
* Main firewall chains definitions and global var's definitions.
*/
#ifdef _KERNEL
/*
* Function definitions.
*/
void ip6_fw_init(void);
/* Firewall hooks */
struct ip6_hdr;
typedef int ip6_fw_chk_t __P((struct ip6_hdr**, struct ifnet*,
u_short *, struct mbuf**));
typedef int ip6_fw_ctl_t __P((int, struct mbuf**));
extern ip6_fw_chk_t *ip6_fw_chk_ptr;
extern ip6_fw_ctl_t *ip6_fw_ctl_ptr;
#endif /* _KERNEL */
#endif /* _IP6_FW_H */

1016
sys/netinet6/ip6_input.c Normal file

File diff suppressed because it is too large Load diff

2176
sys/netinet6/ip6_output.c Normal file

File diff suppressed because it is too large Load diff

251
sys/netinet6/ip6_var.h Normal file
View file

@ -0,0 +1,251 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)ip_var.h 8.1 (Berkeley) 6/10/93
*/
#ifndef _NETINET6_IP6_VAR_H_
#define _NETINET6_IP6_VAR_H_
/*
* IP6 reassembly queue structure. Each fragment
* being reassembled is attached to one of these structures.
*/
struct ip6q {
u_long ip6q_head;
u_short ip6q_len;
u_char ip6q_nxt;
u_char ip6q_hlim;
struct ip6asfrag *ip6q_down;
struct ip6asfrag *ip6q_up;
u_long ip6q_ident;
u_char ip6q_arrive;
u_char ip6q_ttl;
struct in6_addr ip6q_src, ip6q_dst;
struct ip6q *ip6q_next;
struct ip6q *ip6q_prev;
int ip6q_unfrglen;
};
struct ip6asfrag {
u_long ip6af_head;
u_short ip6af_len;
u_char ip6af_nxt;
u_char ip6af_hlim;
/* must not override the above members during reassembling */
struct ip6asfrag *ip6af_down;
struct ip6asfrag *ip6af_up;
u_short ip6af_mff;
u_short ip6af_off;
struct mbuf *ip6af_m;
u_long ip6af_offset; /* offset where next header starts */
u_short ip6af_frglen; /* fragmentable part length */
u_char ip6af_x1[10];
};
#define IP6_REASS_MBUF(ip6af) (*(struct mbuf **)&((ip6af)->ip6af_m))
struct ip6_moptions {
struct ifnet *im6o_multicast_ifp; /* ifp for outgoing multicasts */
u_char im6o_multicast_hlim; /* hoplimit for outgoing multicasts */
u_char im6o_multicast_loop; /* 1 >= hear sends if a member */
LIST_HEAD(, in6_multi_mship) im6o_memberships;
};
/*
* Control options for outgoing packets
*/
/* Routing header related info */
struct ip6po_rhinfo {
struct ip6_rthdr *ip6po_rhi_rthdr; /* Routing header */
struct route_in6 ip6po_rhi_route; /* Route to the 1st hop */
};
#define ip6po_rthdr ip6po_rhinfo.ip6po_rhi_rthdr
#define ip6po_route ip6po_rhinfo.ip6po_rhi_route
struct ip6_pktopts {
struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */
int ip6po_hlim; /* Hoplimit for outgoing packets */
struct in6_pktinfo *ip6po_pktinfo; /* Outgoing IF/address information */
struct sockaddr *ip6po_nexthop; /* Next-hop address */
struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */
struct ip6_dest *ip6po_dest1; /* Destination options header(1st part) */
struct ip6po_rhinfo ip6po_rhinfo; /* Routing header related info. */
struct ip6_dest *ip6po_dest2; /* Destination options header(2nd part) */
};
struct ip6stat {
u_long ip6s_total; /* total packets received */
u_long ip6s_tooshort; /* packet too short */
u_long ip6s_toosmall; /* not enough data */
u_long ip6s_fragments; /* fragments received */
u_long ip6s_fragdropped; /* frags dropped(dups, out of space) */
u_long ip6s_fragtimeout; /* fragments timed out */
u_long ip6s_fragoverflow; /* fragments that exceeded limit */
u_long ip6s_forward; /* packets forwarded */
u_long ip6s_cantforward; /* packets rcvd for unreachable dest */
u_long ip6s_redirectsent; /* packets forwarded on same net */
u_long ip6s_delivered; /* datagrams delivered to upper level*/
u_long ip6s_localout; /* total ip packets generated here */
u_long ip6s_odropped; /* lost packets due to nobufs, etc. */
u_long ip6s_reassembled; /* total packets reassembled ok */
u_long ip6s_fragmented; /* datagrams sucessfully fragmented */
u_long ip6s_ofragments; /* output fragments created */
u_long ip6s_cantfrag; /* don't fragment flag was set, etc. */
u_long ip6s_badoptions; /* error in option processing */
u_long ip6s_noroute; /* packets discarded due to no route */
u_long ip6s_badvers; /* ip6 version != 6 */
u_long ip6s_rawout; /* total raw ip packets generated */
u_long ip6s_badscope; /* scope error */
u_long ip6s_notmember; /* don't join this multicast group */
u_long ip6s_nxthist[256]; /* next header history */
u_long ip6s_m1; /* one mbuf */
u_long ip6s_m2m[32]; /* two or more mbuf */
u_long ip6s_mext1; /* one ext mbuf */
u_long ip6s_mext2m; /* two or more ext mbuf */
u_long ip6s_exthdrtoolong; /* ext hdr are not continuous */
u_long ip6s_nogif; /* no match gif found */
u_long ip6s_toomanyhdr; /* discarded due to too many headers */
};
#ifdef _KERNEL
/* flags passed to ip6_output as last parameter */
#define IPV6_DADOUTPUT 0x01 /* DAD */
#define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */
extern struct ip6stat ip6stat; /* statistics */
extern u_int32_t ip6_id; /* fragment identifier */
extern int ip6_defhlim; /* default hop limit */
extern int ip6_defmcasthlim; /* default multicast hop limit */
extern int ip6_forwarding; /* act as router? */
extern int ip6_forward_srcrt; /* forward src-routed? */
extern int ip6_gif_hlim; /* Hop limit for gif encap packet */
extern int ip6_use_deprecated; /* allow deprecated addr as source */
extern int ip6_rr_prune; /* router renumbering prefix
* walk list every 5 sec. */
extern int ip6_mapped_addr_on;
extern struct socket *ip6_mrouter; /* multicast routing daemon */
extern int ip6_sendredirects; /* send IP redirects when forwarding? */
extern int ip6_maxfragpackets; /* Maximum packets in reassembly queue */
extern int ip6_sourcecheck; /* Verify source interface */
extern int ip6_sourcecheck_interval; /* Interval between log messages */
extern int ip6_accept_rtadv; /* Acts as a host not a router */
extern int ip6_keepfaith; /* Firewall Aided Internet Translator */
extern int ip6_log_interval;
extern time_t ip6_log_time;
extern int ip6_hdrnestlimit; /* upper limit of # of extension headers */
extern int ip6_dad_count; /* DupAddrDetectionTransmits */
extern u_int32_t ip6_flow_seq;
extern int ip6_auto_flowlabel;
extern struct pr_usrreqs rip6_usrreqs;
struct sockopt;
struct inpcb;
int icmp6_ctloutput __P((struct socket *, struct sockopt *sopt));
void ip6_init __P((void));
void ip6intr __P((void));
void ip6_input __P((struct mbuf *));
void ip6_freemoptions __P((struct ip6_moptions *));
int ip6_unknown_opt __P((u_int8_t *, struct mbuf *, int));
char * ip6_get_prevhdr __P((struct mbuf *, int));
int ip6_mforward __P((struct ip6_hdr *, struct ifnet *, struct mbuf *));
int ip6_process_hopopts __P((struct mbuf *, u_int8_t *, int, u_int32_t *,
u_int32_t *));
void ip6_savecontrol __P((struct inpcb *, struct mbuf **, struct ip6_hdr *,
struct mbuf *));
int ip6_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
void ip6_forward __P((struct mbuf *, int));
void ip6_mloopback __P((struct ifnet *, struct mbuf *, struct sockaddr_in6 *));
int ip6_output __P((struct mbuf *, struct ip6_pktopts *,
struct route_in6 *, int,
struct ip6_moptions *, struct ifnet **));
int ip6_ctloutput __P((struct socket *, struct sockopt *sopt));
int ip6_setpktoptions __P((struct mbuf *, struct ip6_pktopts *, int));
int ip6_optlen __P((struct inpcb *));
int route6_input __P((struct mbuf **, int *, int));
void frag6_init __P((void));
int frag6_input __P((struct mbuf **, int *, int));
void frag6_slowtimo __P((void));
void frag6_drain __P((void));
void rip6_init __P((void));
int rip6_input __P((struct mbuf **mp, int *offp, int proto));
int rip6_ctloutput __P((struct socket *so, struct sockopt *sopt));
int rip6_output __P((struct mbuf *, ...));
int rip6_usrreq __P((struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *));
int dest6_input __P((struct mbuf **, int *, int));
int none_input __P((struct mbuf **, int *, int));
#endif /* _KERNEL */
#endif /* !_NETINET6_IP6_VAR_H_ */

129
sys/netinet6/ip6protosw.h Normal file
View file

@ -0,0 +1,129 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/* BSDI protosw.h,v 2.3 1996/10/11 16:02:40 pjd Exp */
/*-
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)protosw.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _NETINET6_IP6PROTOSW_H_
#define _NETINET6_IP6PROTOSW_H_
/*
* Protocol switch table for IPv6.
* All other definitions should refer to sys/protosw.h
*/
struct mbuf;
struct sockaddr;
struct socket;
struct domain;
struct proc;
struct ip6_hdr;
struct pr_usrreqs;
/*
* argument type for the last arg of pr_ctlinput().
* should be consulted only with AF_INET6 family.
*/
struct ip6ctlparam {
struct mbuf *ip6c_m; /* start of mbuf chain */
struct ip6_hdr *ip6c_ip6; /* ip6 header of target packet */
int ip6c_off; /* offset of the target proto header */
};
struct ip6protosw {
int pr_type; /* socket type used for */
struct domain *pr_domain; /* domain protocol a member of */
short pr_protocol; /* protocol number */
short pr_flags; /* see below */
/* protocol-protocol hooks */
int (*pr_input) /* input to protocol (from below) */
__P((struct mbuf **, int *, int));
int (*pr_output) /* output to protocol (from above) */
__P((struct mbuf *, ...));
void (*pr_ctlinput) /* control input (from below) */
__P((int, struct sockaddr *, void *));
int (*pr_ctloutput) /* control output (from above) */
__P((struct socket *, struct sockopt *));
/* user-protocol hook */
int (*pr_usrreq) /* user request: see list below */
__P((struct socket *, int, struct mbuf *,
struct mbuf *, struct mbuf *, struct proc *));
/* utility hooks */
void (*pr_init) /* initialization hook */
__P((void));
void (*pr_fasttimo) /* fast timeout (200ms) */
__P((void));
void (*pr_slowtimo) /* slow timeout (500ms) */
__P((void));
void (*pr_drain) /* flush any excess space possible */
__P((void));
struct pr_usrreqs *pr_usrreqs; /* supersedes pr_usrreq() */
};
#endif /* !_NETINET6_IP6PROTOSW_H_ */

314
sys/netinet6/ipsec.h Normal file
View file

@ -0,0 +1,314 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* IPsec controller part.
*/
#ifndef _NETINET6_IPSEC_H_
#define _NETINET6_IPSEC_H_
#include <net/pfkeyv2.h>
#include <netkey/keydb.h>
#ifdef KERNEL
/*
* Security Policy Index
* NOTE: Encure to be same address family and upper layer protocol.
* NOTE: ul_proto, port number, uid, gid:
* ANY: reserved for waldcard.
* 0 to (~0 - 1): is one of the number of each value.
*/
struct secpolicyindex {
u_int8_t dir; /* direction of packet flow, see blow */
struct sockaddr_storage src; /* IP src address for SP */
struct sockaddr_storage dst; /* IP dst address for SP */
u_int8_t prefs; /* prefix length in bits for src */
u_int8_t prefd; /* prefix length in bits for dst */
u_int16_t ul_proto; /* upper layer Protocol */
};
/* Security Policy Data Base */
struct secpolicy {
LIST_ENTRY(secpolicy) chain;
int refcnt; /* reference count */
struct secpolicyindex spidx; /* selector */
u_int state; /* 0: dead, others: alive */
#define IPSEC_SPSTATE_DEAD 0
#define IPSEC_SPSTATE_ALIVE 1
u_int policy; /* DISCARD, NONE or IPSEC, see keyv2.h */
struct ipsecrequest *req;
/* pointer to the ipsec request tree, */
/* if policy == IPSEC else this value == NULL.*/
};
/* Request for IPsec */
struct ipsecrequest {
struct ipsecrequest *next;
/* pointer to next structure */
/* If NULL, it means the end of chain. */
struct secasindex saidx;
u_int level; /* IPsec level defined below. */
struct secasvar *sav; /* place holder of SA for use */
struct secpolicy *sp; /* back pointer to SP */
};
/* security policy in PCB */
struct inpcbpolicy {
struct secpolicy *sp_in;
struct secpolicy *sp_out;
int priv; /* privileged socket ? */
};
#endif /*KERNEL*/
#define IPSEC_PORT_ANY 65535
#define IPSEC_ULPROTO_ANY 255
#define IPSEC_PROTO_ANY 65535
/* mode of security protocol */
/* NOTE: DON'T use IPSEC_MODE_ANY at SPD. It's only use in SAD */
#define IPSEC_MODE_ANY 0 /* i.e. wildcard. */
#define IPSEC_MODE_TRANSPORT 1
#define IPSEC_MODE_TUNNEL 2
/*
* Direction of security policy.
* NOTE: Since INVALID is used just as flag.
* The other are used for loop counter too.
*/
#define IPSEC_DIR_ANY 0
#define IPSEC_DIR_INBOUND 1
#define IPSEC_DIR_OUTBOUND 2
#define IPSEC_DIR_MAX 3
#define IPSEC_DIR_INVALID 4
/* Policy level */
/*
* IPSEC, ENTRUST and BYPASS are allowd for setsockopt() in PCB,
* DISCARD, IPSEC and NONE are allowd for setkey() in SPD.
* DISCARD and NONE are allowd for system default.
*/
#define IPSEC_POLICY_DISCARD 0 /* discarding packet */
#define IPSEC_POLICY_NONE 1 /* through IPsec engine */
#define IPSEC_POLICY_IPSEC 2 /* do IPsec */
#define IPSEC_POLICY_ENTRUST 3 /* consulting SPD if present. */
#define IPSEC_POLICY_BYPASS 4 /* only for privileged socket. */
/* Security protocol level */
#define IPSEC_LEVEL_DEFAULT 0 /* reference to system default */
#define IPSEC_LEVEL_USE 1 /* use SA if present. */
#define IPSEC_LEVEL_REQUIRE 2 /* require SA. */
#define IPSEC_LEVEL_UNIQUE 3 /* unique SA. */
#define IPSEC_REPLAYWSIZE 32
/* statistics for ipsec processing */
struct ipsecstat {
u_long in_success; /* succeeded inbound process */
u_long in_polvio; /* security policy violation for inbound process */
u_long in_nosa; /* inbound SA is unavailable */
u_long in_inval; /* inbound processing failed due to EINVAL */
u_long in_badspi; /* failed getting a SPI */
u_long in_ahreplay; /* AH replay check failed */
u_long in_espreplay; /* ESP replay check failed */
u_long in_ahauthsucc; /* AH authentication success */
u_long in_ahauthfail; /* AH authentication failure */
u_long in_espauthsucc; /* ESP authentication success */
u_long in_espauthfail; /* ESP authentication failure */
u_long in_esphist[SADB_EALG_MAX];
u_long in_ahhist[SADB_AALG_MAX];
u_long out_success; /* succeeded outbound process */
u_long out_polvio; /* security policy violation for outbound process */
u_long out_nosa; /* outbound SA is unavailable */
u_long out_inval; /* outbound process failed due to EINVAL */
u_long out_noroute; /* there is no route */
u_long out_esphist[SADB_EALG_MAX];
u_long out_ahhist[SADB_AALG_MAX];
};
/*
* Definitions for IPsec & Key sysctl operations.
*/
/*
* Names for IPsec & Key sysctl objects
*/
#define IPSECCTL_STATS 1 /* stats */
#define IPSECCTL_DEF_POLICY 2
#define IPSECCTL_DEF_ESP_TRANSLEV 3 /* int; ESP transport mode */
#define IPSECCTL_DEF_ESP_NETLEV 4 /* int; ESP tunnel mode */
#define IPSECCTL_DEF_AH_TRANSLEV 5 /* int; AH transport mode */
#define IPSECCTL_DEF_AH_NETLEV 6 /* int; AH tunnel mode */
#define IPSECCTL_INBOUND_CALL_IKE 7
#define IPSECCTL_AH_CLEARTOS 8
#define IPSECCTL_AH_OFFSETMASK 9
#define IPSECCTL_DFBIT 10
#define IPSECCTL_ECN 11
#define IPSECCTL_MAXID 12
#define IPSECCTL_NAMES { \
{ 0, 0 }, \
{ 0, 0 }, \
{ "def_policy", CTLTYPE_INT }, \
{ "esp_trans_deflev", CTLTYPE_INT }, \
{ "esp_net_deflev", CTLTYPE_INT }, \
{ "ah_trans_deflev", CTLTYPE_INT }, \
{ "ah_net_deflev", CTLTYPE_INT }, \
{ "inbound_call_ike", CTLTYPE_INT }, \
{ "ah_cleartos", CTLTYPE_INT }, \
{ "ah_offsetmask", CTLTYPE_INT }, \
{ "dfbit", CTLTYPE_INT }, \
{ "ecn", CTLTYPE_INT }, \
}
#define IPSEC6CTL_NAMES { \
{ 0, 0 }, \
{ 0, 0 }, \
{ "def_policy", CTLTYPE_INT }, \
{ "esp_trans_deflev", CTLTYPE_INT }, \
{ "esp_net_deflev", CTLTYPE_INT }, \
{ "ah_trans_deflev", CTLTYPE_INT }, \
{ "ah_net_deflev", CTLTYPE_INT }, \
{ "inbound_call_ike", CTLTYPE_INT }, \
{ 0, 0 }, \
{ 0, 0 }, \
{ 0, 0 }, \
{ "ecn", CTLTYPE_INT }, \
}
#define IPSECCTL_VARS { \
0, \
0, \
&ip4_def_policy.policy, \
&ip4_esp_trans_deflev, \
&ip4_esp_net_deflev, \
&ip4_ah_trans_deflev, \
&ip4_ah_net_deflev, \
&ip4_inbound_call_ike, \
&ip4_ah_cleartos, \
&ip4_ah_offsetmask, \
&ip4_ipsec_dfbit, \
&ip4_ipsec_ecn, \
}
#define IPSEC6CTL_VARS { \
0, \
0, \
&ip6_def_policy.policy, \
&ip6_esp_trans_deflev, \
&ip6_esp_net_deflev, \
&ip6_ah_trans_deflev, \
&ip6_ah_net_deflev, \
&ip6_inbound_call_ike, \
0, \
0, \
0, \
&ip6_ipsec_ecn, \
}
#ifdef KERNEL
struct ipsec_output_state {
struct mbuf *m;
struct route *ro;
struct sockaddr *dst;
};
extern struct ipsecstat ipsecstat;
extern struct secpolicy ip4_def_policy;
extern int ip4_esp_trans_deflev;
extern int ip4_esp_net_deflev;
extern int ip4_ah_trans_deflev;
extern int ip4_ah_net_deflev;
extern int ip4_inbound_call_ike;
extern int ip4_ah_cleartos;
extern int ip4_ah_offsetmask;
extern int ip4_ipsec_dfbit;
extern int ip4_ipsec_ecn;
extern struct secpolicy *ipsec4_getpolicybysock
__P((struct mbuf *, u_int, struct socket *, int *));
extern struct secpolicy *ipsec4_getpolicybyaddr
__P((struct mbuf *, u_int, int, int *));
struct inpcb;
extern int ipsec_init_policy __P((struct socket *so, struct inpcbpolicy **));
extern int ipsec_copy_policy
__P((struct inpcbpolicy *, struct inpcbpolicy *));
extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *));
extern int ipsec4_set_policy __P((struct inpcb *inp, int optname,
caddr_t request, int priv));
extern int ipsec4_get_policy
__P((struct inpcb *inpcb, caddr_t request, struct mbuf **mp));
extern int ipsec4_delete_pcbpolicy __P((struct inpcb *));
extern int ipsec4_in_reject_so __P((struct mbuf *, struct socket *));
extern int ipsec4_in_reject __P((struct mbuf *, struct inpcb *));
struct secas;
struct tcpcb;
struct tcp6cb;
extern int ipsec_chkreplay __P((u_int32_t, struct secasvar *));
extern int ipsec_updatereplay __P((u_int32_t, struct secasvar *));
extern size_t ipsec4_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
extern size_t ipsec_hdrsiz_tcp __P((struct tcpcb *, int));
struct ip;
extern const char *ipsec4_logpacketstr __P((struct ip *, u_int32_t));
extern const char *ipsec_logsastr __P((struct secasvar *));
extern void ipsec_dumpmbuf __P((struct mbuf *));
extern int ipsec4_output __P((struct ipsec_output_state *, struct secpolicy *,
int));
extern int ipsec4_tunnel_validate __P((struct ip *, u_int,
struct secasvar *));
extern struct mbuf *ipsec_copypkt __P((struct mbuf *));
#endif /*KERNEL*/
#ifndef KERNEL
extern caddr_t ipsec_set_policy __P((char *policy, int buflen));
extern int ipsec_get_policylen __P((caddr_t buf));
extern char *ipsec_dump_policy __P((caddr_t buf, char *delimiter));
extern char *ipsec_strerror __P((void));
#endif /*!KERNEL*/
#endif /*_NETINET6_IPSEC_H_*/

77
sys/netinet6/ipsec6.h Normal file
View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* IPsec controller part, only IPv6 related
*/
#ifndef _NETINET6_IPSEC6_H_
#define _NETINET6_IPSEC6_H_
#ifdef KERNEL
extern struct ipsecstat ipsec6stat;
extern struct secpolicy ip6_def_policy;
extern int ip6_esp_trans_deflev;
extern int ip6_esp_net_deflev;
extern int ip6_ah_trans_deflev;
extern int ip6_ah_net_deflev;
extern int ip6_inbound_call_ike;
extern int ip6_ipsec_ecn;
extern struct secpolicy *ipsec6_getpolicybysock
__P((struct mbuf *, u_int, struct socket *, int *));
extern struct secpolicy *ipsec6_getpolicybyaddr
__P((struct mbuf *, u_int, int, int *));
extern int ipsec6_in_reject_so __P((struct mbuf *, struct socket *));
extern int ipsec6_delete_pcbpolicy __P((struct inpcb *));
extern int ipsec6_set_policy __P((struct inpcb *inp, int optname,
caddr_t request, int priv));
extern int ipsec6_get_policy
__P((struct inpcb *inp, caddr_t request, struct mbuf **mp));
extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *));
extern size_t ipsec6_hdrsiz __P((struct mbuf *, u_int, struct inpcb *));
struct ip6_hdr;
extern const char *ipsec6_logpacketstr __P((struct ip6_hdr *, u_int32_t));
extern int ipsec6_output_trans __P((struct ipsec_output_state *, u_char *,
struct mbuf *, struct secpolicy *,
int, int *));
extern int ipsec6_output_tunnel __P((struct ipsec_output_state *,
struct secpolicy *, int));
extern int ipsec6_tunnel_validate __P((struct ip6_hdr *, u_int,
struct secasvar *));
#endif /*KERNEL*/
#endif /* _NETINET6_IPSEC6_H_ */

459
sys/netinet6/mld6.c Normal file
View file

@ -0,0 +1,459 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1988 Stephen Deering.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Stephen Deering of Stanford University.
*
* 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 University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)igmp.c 8.1 (Berkeley) 7/19/93
*/
#include "opt_inet.h"
#include "opt_ipsec.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/syslog.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet6/in6.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/icmp6.h>
#include <netinet6/mld6_var.h>
#include <net/net_osdep.h>
/*
* Protocol constants
*/
/* denotes that the MLD max response delay field specifies time in milliseconds */
#define MLD6_TIMER_SCALE 1000
/*
* time between repetitions of a node's initial report of interest in a
* multicast address(in seconds)
*/
#define MLD6_UNSOLICITED_REPORT_INTERVAL 10
static struct ip6_pktopts ip6_opts;
static int mld6_timers_are_running;
/* XXX: These are necessary for KAME's link-local hack */
static struct in6_addr mld6_all_nodes_linklocal =
IN6ADDR_LINKLOCAL_ALLNODES_INIT;
static struct in6_addr mld6_all_routers_linklocal =
IN6ADDR_LINKLOCAL_ALLROUTERS_INIT;
static void mld6_sendpkt __P((struct in6_multi *, int,
const struct in6_addr *));
void
mld6_init()
{
static u_int8_t hbh_buf[8];
struct ip6_hbh *hbh = (struct ip6_hbh *)hbh_buf;
u_int16_t rtalert_code = htons((u_int16_t)IP6OPT_RTALERT_MLD);
mld6_timers_are_running = 0;
/* ip6h_nxt will be fill in later */
hbh->ip6h_len = 0; /* (8 >> 3) - 1*/
/* XXX: grotty hard coding... */
hbh_buf[2] = IP6OPT_PADN; /* 2 byte padding */
hbh_buf[3] = 0;
hbh_buf[4] = IP6OPT_RTALERT;
hbh_buf[5] = IP6OPT_RTALERT_LEN - 2;
bcopy((caddr_t)&rtalert_code, &hbh_buf[6], sizeof(u_int16_t));
ip6_opts.ip6po_hbh = hbh;
/* We will specify the hoplimit by a multicast option. */
ip6_opts.ip6po_hlim = -1;
}
void
mld6_start_listening(in6m)
struct in6_multi *in6m;
{
int s = splnet();
/*
* (draft-ietf-ipngwg-mld, page 10)
* The node never sends a Report or Done for the link-scope all-nodes
* address.
* MLD messages are never sent for multicast addresses whose scope is 0
* (reserved) or 1 (node-local).
*/
mld6_all_nodes_linklocal.s6_addr16[1] =
htons(in6m->in6m_ifp->if_index); /* XXX */
if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal) ||
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) {
in6m->in6m_timer = 0;
in6m->in6m_state = MLD6_OTHERLISTENER;
} else {
mld6_sendpkt(in6m, MLD6_LISTENER_REPORT, NULL);
in6m->in6m_timer = MLD6_RANDOM_DELAY(
MLD6_UNSOLICITED_REPORT_INTERVAL * PR_FASTHZ);
in6m->in6m_state = MLD6_IREPORTEDLAST;
mld6_timers_are_running = 1;
}
splx(s);
}
void
mld6_stop_listening(in6m)
struct in6_multi *in6m;
{
mld6_all_nodes_linklocal.s6_addr16[1] =
htons(in6m->in6m_ifp->if_index); /* XXX */
mld6_all_routers_linklocal.s6_addr16[1] =
htons(in6m->in6m_ifp->if_index); /* XXX: necessary when mrouting */
if (in6m->in6m_state == MLD6_IREPORTEDLAST &&
(!IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &mld6_all_nodes_linklocal)) &&
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) > IPV6_ADDR_SCOPE_NODELOCAL)
mld6_sendpkt(in6m, MLD6_LISTENER_DONE,
&mld6_all_routers_linklocal);
}
void
mld6_input(m, off)
struct mbuf *m;
int off;
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct mld6_hdr *mldh = (struct mld6_hdr *)(mtod(m, caddr_t) + off);
struct ifnet *ifp = m->m_pkthdr.rcvif;
struct in6_multi *in6m;
struct in6_ifaddr *ia;
struct ifmultiaddr *ifma;
int timer; /* timer value in the MLD query header */
/* source address validation */
if (!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
log(LOG_ERR,
"mld6_input: src %s is not link-local\n",
ip6_sprintf(&ip6->ip6_src));
/*
* spec(draft-ietf-ipngwg-mld) does not explicitly
* specify to discard the packet from a non link-local
* source address. But we believe it's expected to do so.
*/
return;
}
/*
* In the MLD6 specification, there are 3 states and a flag.
*
* In Non-Listener state, we simply don't have a membership record.
* In Delaying Listener state, our timer is running (in6m->in6m_timer)
* In Idle Listener state, our timer is not running (in6m->in6m_timer==0)
*
* The flag is in6m->in6m_state, it is set to MLD6_OTHERLISTENER if
* we have heard a report from another member, or MLD6_IREPORTEDLAST
* if we sent the last report.
*/
switch(mldh->mld6_type) {
case MLD6_LISTENER_QUERY:
if (ifp->if_flags & IFF_LOOPBACK)
break;
if (!IN6_IS_ADDR_UNSPECIFIED(&mldh->mld6_addr) &&
!IN6_IS_ADDR_MULTICAST(&mldh->mld6_addr))
break; /* print error or log stat? */
if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld6_addr))
mldh->mld6_addr.s6_addr16[1] =
htons(ifp->if_index); /* XXX */
/*
* - Start the timers in all of our membership records
* that the query applies to for the interface on
* which the query arrived excl. those that belong
* to the "all-nodes" group (ff02::1).
* - Restart any timer that is already running but has
* A value longer than the requested timeout.
* - Use the value specified in the query message as
* the maximum timeout.
*/
IFP_TO_IA6(ifp, ia);
if (ia == NULL)
break;
/*
* XXX: System timer resolution is too low to handle Max
* Response Delay, so set 1 to the internal timer even if
* the calculated value equals to zero when Max Response
* Delay is positive.
*/
timer = ntohs(mldh->mld6_maxdelay)*PR_FASTHZ/MLD6_TIMER_SCALE;
if (timer == 0 && mldh->mld6_maxdelay)
timer = 1;
mld6_all_nodes_linklocal.s6_addr16[1] =
htons(ifp->if_index); /* XXX */
LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link)
{
if (ifma->ifma_addr->sa_family != AF_INET6)
continue;
in6m = (struct in6_multi *)ifma->ifma_protospec;
if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr,
&mld6_all_nodes_linklocal) ||
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) <
IPV6_ADDR_SCOPE_LINKLOCAL)
continue;
if (IN6_IS_ADDR_UNSPECIFIED(&mldh->mld6_addr) ||
IN6_ARE_ADDR_EQUAL(&mldh->mld6_addr,
&in6m->in6m_addr))
{
if (timer == 0) {
/* send a report immediately */
mld6_sendpkt(in6m, MLD6_LISTENER_REPORT,
NULL);
in6m->in6m_timer = 0; /* reset timer */
in6m->in6m_state = MLD6_IREPORTEDLAST;
} else if (in6m->in6m_timer == 0 || /*idle state*/
in6m->in6m_timer > timer) {
in6m->in6m_timer =
MLD6_RANDOM_DELAY(timer);
mld6_timers_are_running = 1;
}
}
}
if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld6_addr))
mldh->mld6_addr.s6_addr16[1] = 0; /* XXX */
break;
case MLD6_LISTENER_REPORT:
/*
* For fast leave to work, we have to know that we are the
* last person to send a report for this group. Reports
* can potentially get looped back if we are a multicast
* router, so discard reports sourced by me.
* Note that it is impossible to check IFF_LOOPBACK flag of
* ifp for this purpose, since ip6_mloopback pass the physical
* interface to looutput.
*/
if (m->m_flags & M_LOOP) /* XXX: grotty flag, but efficient */
break;
if (!IN6_IS_ADDR_MULTICAST(&mldh->mld6_addr))
break;
if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld6_addr))
mldh->mld6_addr.s6_addr16[1] =
htons(ifp->if_index); /* XXX */
/*
* If we belong to the group being reported, stop
* our timer for that group.
*/
IN6_LOOKUP_MULTI(mldh->mld6_addr, ifp, in6m);
if (in6m) {
in6m->in6m_timer = 0; /* transit to idle state */
in6m->in6m_state = MLD6_OTHERLISTENER; /* clear flag */
}
if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld6_addr))
mldh->mld6_addr.s6_addr16[1] = 0; /* XXX */
break;
default: /* this is impossible */
log(LOG_ERR, "mld6_input: illegal type(%d)", mldh->mld6_type);
break;
}
}
void
mld6_fasttimeo()
{
register struct in6_multi *in6m;
struct in6_multistep step;
int s;
/*
* Quick check to see if any work needs to be done, in order
* to minimize the overhead of fasttimo processing.
*/
if (!mld6_timers_are_running)
return;
s = splnet();
mld6_timers_are_running = 0;
IN6_FIRST_MULTI(step, in6m);
while (in6m != NULL) {
if (in6m->in6m_timer == 0) {
/* do nothing */
} else if (--in6m->in6m_timer == 0) {
mld6_sendpkt(in6m, MLD6_LISTENER_REPORT, NULL);
in6m->in6m_state = MLD6_IREPORTEDLAST;
} else {
mld6_timers_are_running = 1;
}
IN6_NEXT_MULTI(step, in6m);
}
splx(s);
}
static void
mld6_sendpkt(in6m, type, dst)
struct in6_multi *in6m;
int type;
const struct in6_addr *dst;
{
struct mbuf *mh, *md;
struct mld6_hdr *mldh;
struct ip6_hdr *ip6;
struct ip6_moptions im6o;
struct in6_ifaddr *ia;
struct ifnet *ifp = in6m->in6m_ifp;
struct ifnet *outif = NULL;
/*
* At first, find a link local address on the outgoing interface
* to use as the source address of the MLD packet.
*/
if ((ia = in6ifa_ifpforlinklocal(ifp)) == NULL)
return;
/*
* Allocate mbufs to store ip6 header and MLD header.
* We allocate 2 mbufs and make chain in advance because
* it is more convenient when inserting the hop-by-hop option later.
*/
MGETHDR(mh, M_DONTWAIT, MT_HEADER);
if (mh == NULL)
return;
MGET(md, M_DONTWAIT, MT_DATA);
if (md == NULL) {
m_free(mh);
return;
}
mh->m_next = md;
#ifdef IPSEC
mh->m_pkthdr.rcvif = NULL;
#endif
mh->m_pkthdr.len = sizeof(struct ip6_hdr) + sizeof(struct mld6_hdr);
mh->m_len = sizeof(struct ip6_hdr);
MH_ALIGN(mh, sizeof(struct ip6_hdr));
/* fill in the ip6 header */
ip6 = mtod(mh, struct ip6_hdr *);
ip6->ip6_flow = 0;
ip6->ip6_vfc = IPV6_VERSION;
/* ip6_plen will be set later */
ip6->ip6_nxt = IPPROTO_ICMPV6;
/* ip6_hlim will be set by im6o.im6o_multicast_hlim */
ip6->ip6_src = ia->ia_addr.sin6_addr;
ip6->ip6_dst = dst ? *dst : in6m->in6m_addr;
/* fill in the MLD header */
md->m_len = sizeof(struct mld6_hdr);
mldh = mtod(md, struct mld6_hdr *);
mldh->mld6_type = type;
mldh->mld6_code = 0;
mldh->mld6_cksum = 0;
/* XXX: we assume the function will not be called for query messages */
mldh->mld6_maxdelay = 0;
mldh->mld6_reserved = 0;
mldh->mld6_addr = in6m->in6m_addr;
if (IN6_IS_ADDR_MC_LINKLOCAL(&mldh->mld6_addr))
mldh->mld6_addr.s6_addr16[1] = 0; /* XXX */
mldh->mld6_cksum = in6_cksum(mh, IPPROTO_ICMPV6, sizeof(struct ip6_hdr),
sizeof(struct mld6_hdr));
/* construct multicast option */
bzero(&im6o, sizeof(im6o));
im6o.im6o_multicast_ifp = ifp;
im6o.im6o_multicast_hlim = 1;
/*
* Request loopback of the report if we are acting as a multicast
* router, so that the process-level routing daemon can hear it.
*/
im6o.im6o_multicast_loop = 0;
/* increment output statictics */
icmp6stat.icp6s_outhist[type]++;
ip6_output(mh, &ip6_opts, NULL, 0, &im6o, &outif);
if (outif) {
icmp6_ifstat_inc(outif, ifs6_out_msg);
switch(type) {
case MLD6_LISTENER_QUERY:
icmp6_ifstat_inc(outif, ifs6_out_mldquery);
break;
case MLD6_LISTENER_REPORT:
icmp6_ifstat_inc(outif, ifs6_out_mldreport);
break;
case MLD6_LISTENER_DONE:
icmp6_ifstat_inc(outif, ifs6_out_mlddone);
break;
}
}
}

52
sys/netinet6/mld6_var.h Normal file
View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#ifndef _NETINET6_MLD6_VAR_H_
#define _NETINET6_MLD6_VAR_H_
#ifdef _KERNEL
#define MLD6_RANDOM_DELAY(X) (random() % (X) + 1)
/*
* States for MLD stop-listening processing
*/
#define MLD6_OTHERLISTENER 0
#define MLD6_IREPORTEDLAST 1
void mld6_init __P((void));
void mld6_input __P((struct mbuf *, int));
void mld6_start_listening __P((struct in6_multi *));
void mld6_stop_listening __P((struct in6_multi *));
void mld6_fasttimeo __P((void));
#endif /* _KERNEL */
#endif /* _NETINET6_MLD6_VAR_H_ */

1531
sys/netinet6/nd6.c Normal file

File diff suppressed because it is too large Load diff

302
sys/netinet6/nd6.h Normal file
View file

@ -0,0 +1,302 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#ifndef _NETINET6_ND6_H_
#define _NETINET6_ND6_H_
#include <sys/queue.h>
struct llinfo_nd6 {
struct llinfo_nd6 *ln_next;
struct llinfo_nd6 *ln_prev;
struct rtentry *ln_rt;
struct mbuf *ln_hold; /* last packet until resolved/timeout */
long ln_asked; /* number of queries already sent for this addr */
u_long ln_expire; /* lifetime for NDP state transition */
short ln_state; /* reachability state */
short ln_router; /* 2^0: ND6 router bit */
};
#define ND6_LLINFO_NOSTATE -2
#define ND6_LLINFO_WAITDELETE -1
#define ND6_LLINFO_INCOMPLETE 0
#define ND6_LLINFO_REACHABLE 1
#define ND6_LLINFO_STALE 2
#define ND6_LLINFO_DELAY 3
#define ND6_LLINFO_PROBE 4
struct nd_ifinfo {
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 */
int recalctm; /* BaseReacable re-calculation timer */
u_int8_t chlim; /* CurHopLimit */
u_int8_t receivedra;
};
struct in6_nbrinfo {
char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */
struct in6_addr addr; /* IPv6 address of the neighbor */
long asked; /* number of queries already sent for this addr */
int isrouter; /* if it acts as a router */
int state; /* reachability state */
int expire; /* lifetime for NDP state transition */
};
#define DRLSTSIZ 10
#define PRLSTSIZ 10
struct in6_drlist {
char ifname[IFNAMSIZ];
struct {
struct in6_addr rtaddr;
u_char flags;
u_short rtlifetime;
u_long expire;
u_short if_index;
} defrouter[DRLSTSIZ];
};
struct in6_prlist {
char ifname[IFNAMSIZ];
struct {
struct in6_addr prefix;
struct prf_ra raflags;
u_char prefixlen;
u_long vltime;
u_long pltime;
u_long expire;
u_short if_index;
u_short advrtrs; /* number of advertisement routers */
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
} prefix[PRLSTSIZ];
};
struct in6_ndireq {
char ifname[IFNAMSIZ];
struct nd_ifinfo ndi;
};
/* protocol constants */
#define MAX_RTR_SOLICITATION_DELAY 1 /*1sec*/
#define RTR_SOLICITATION_INTERVAL 4 /*4sec*/
#define MAX_RTR_SOLICITATIONS 3
#define ND6_INFINITE_LIFETIME 0xffffffff
#ifdef _KERNEL
/* node constants */
#define MAX_REACHABLE_TIME 3600000 /* msec */
#define REACHABLE_TIME 30000 /* msec */
#define RETRANS_TIMER 1000 /* msec */
#define MIN_RANDOM_FACTOR 512 /* 1024 * 0.5 */
#define MAX_RANDOM_FACTOR 1536 /* 1024 * 1.5 */
#define ND_COMPUTE_RTIME(x) \
(((MIN_RANDOM_FACTOR * (x >> 10)) + (random() & \
((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)
struct nd_defrouter {
LIST_ENTRY(nd_defrouter) dr_entry;
#define dr_next dr_entry.le_next
struct in6_addr rtaddr;
u_char flags;
u_short rtlifetime;
u_long expire;
struct ifnet *ifp;
};
struct nd_prefix {
struct ifnet *ndpr_ifp;
LIST_ENTRY(nd_prefix) ndpr_entry;
struct sockaddr_in6 ndpr_prefix; /* prefix */
struct in6_addr ndpr_mask; /* netmask derived from the prefix */
struct in6_addr ndpr_addr; /* address that is derived from the prefix */
u_int32_t ndpr_vltime; /* advertised valid lifetime */
u_int32_t ndpr_pltime; /* advertised preferred lifetime */
time_t ndpr_expire; /* expiration time of the prefix */
time_t ndpr_preferred; /* preferred time of the prefix */
struct prf_ra ndpr_flags;
/* list of routers that advertise the prefix: */
LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs;
u_char ndpr_plen;
struct ndpr_stateflags {
/* if this prefix can be regarded as on-link */
u_char onlink : 1;
} ndpr_stateflags;
};
#define ndpr_next ndpr_entry.le_next
#define ndpr_raf ndpr_flags
#define ndpr_raf_onlink ndpr_flags.onlink
#define ndpr_raf_auto ndpr_flags.autonomous
#define ndpr_statef_onlink ndpr_stateflags.onlink
#define ndpr_statef_addmark ndpr_stateflags.addmark
/*
* We keep expired prefix for certain amount of time, for validation purposes.
* 1800s = MaxRtrAdvInterval
*/
#define NDPR_KEEP_EXPIRED (1800 * 2)
/*
* Message format for use in obtaining information about prefixes
* from inet6 sysctl function
*/
struct inet6_ndpr_msghdr {
u_short inpm_msglen; /* to skip over non-understood messages */
u_char inpm_version; /* future binary compatability */
u_char inpm_type; /* message type */
struct in6_addr inpm_prefix;
u_long prm_vltim;
u_long prm_pltime;
u_long prm_expire;
u_long prm_preferred;
struct in6_prflags prm_flags;
u_short prm_index; /* index for associated ifp */
u_char prm_plen; /* length of prefix in bits */
};
#define prm_raf_onlink prm_flags.prf_ra.onlink
#define prm_raf_auto prm_flags.prf_ra.autonomous
#define prm_statef_onlink prm_flags.prf_state.onlink
#define prm_rrf_decrvalid prm_flags.prf_rr.decrvalid
#define prm_rrf_decrprefd prm_flags.prf_rr.decrprefd
#define ifpr2ndpr(ifpr) ((struct nd_prefix *)(ifpr))
#define ndpr2ifpr(ndpr) ((struct ifprefix *)(ndpr))
struct nd_pfxrouter {
LIST_ENTRY(nd_pfxrouter) pfr_entry;
#define pfr_next pfr_entry.le_next
struct nd_defrouter *router;
};
LIST_HEAD(nd_drhead, nd_defrouter);
LIST_HEAD(nd_prhead, nd_prefix);
/* nd6.c */
extern int nd6_prune;
extern int nd6_delay;
extern int nd6_umaxtries;
extern int nd6_mmaxtries;
extern int nd6_useloopback;
extern int nd6_proxyall;
extern struct llinfo_nd6 llinfo_nd6;
extern struct nd_ifinfo *nd_ifinfo;
extern struct nd_drhead nd_defrouter;
extern struct nd_prhead nd_prefix;
union nd_opts {
struct nd_opt_hdr *nd_opt_array[9];
struct {
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_rd_hdr *rh;
struct nd_opt_mtu *mtu;
struct nd_opt_hdr *search; /* multiple opts */
struct nd_opt_hdr *last; /* multiple opts */
int done;
struct nd_opt_prefix_info *pi_end;/* multiple opts, end */
} nd_opt_each;
};
#define nd_opts_src_lladdr nd_opt_each.src_lladdr
#define nd_opts_tgt_lladdr nd_opt_each.tgt_lladdr
#define nd_opts_pi nd_opt_each.pi_beg
#define nd_opts_pi_end nd_opt_each.pi_end
#define nd_opts_rh nd_opt_each.rh
#define nd_opts_mtu nd_opt_each.mtu
#define nd_opts_search nd_opt_each.search
#define nd_opts_last nd_opt_each.last
#define nd_opts_done nd_opt_each.done
/* XXX: need nd6_var.h?? */
/* nd6.c */
void nd6_init __P((void));
void nd6_ifattach __P((struct ifnet *));
int nd6_is_addr_neighbor __P((struct in6_addr *, 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_timer __P((void *));
void nd6_free __P((struct rtentry *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *));
int nd6_resolve __P((struct ifnet *, struct rtentry *,
struct mbuf *, struct sockaddr *, u_char *));
void nd6_rtrequest __P((int, struct rtentry *, struct sockaddr *));
void nd6_p2p_rtrequest __P((int, struct rtentry *, struct sockaddr *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
/* for test */
int nd6_output __P((struct ifnet *, struct mbuf *, struct sockaddr_in6 *,
struct rtentry *));
int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
/* nd6_nbr.c */
void nd6_na_input __P((struct mbuf *, int, int));
void nd6_na_output __P((struct ifnet *, struct in6_addr *,
struct in6_addr *, u_long, int));
void nd6_ns_input __P((struct mbuf *, int, int));
void nd6_ns_output __P((struct ifnet *, struct in6_addr *,
struct in6_addr *, struct llinfo_nd6 *, int));
caddr_t nd6_ifptomac __P((struct ifnet *));
void nd6_dad_start __P((struct ifaddr *, int *));
void nd6_dad_duplicated __P((struct ifaddr *));
/* nd6_rtr.c */
void nd6_rs_input __P((struct mbuf *, int, int));
void nd6_ra_input __P((struct mbuf *, int, int));
void prelist_del __P((struct nd_prefix *));
void defrouter_addreq __P((struct nd_defrouter *));
void defrouter_delreq __P((struct nd_defrouter *, int));
void defrtrlist_del __P((struct nd_defrouter *));
void prelist_remove __P((struct nd_prefix *));
int prelist_update __P((struct nd_prefix *, struct nd_defrouter *,
struct mbuf *));
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *,
struct ifnet *));
int in6_ifdel __P((struct ifnet *, struct in6_addr *));
int in6_init_prefix_ltimes __P((struct nd_prefix *ndpr));
void rt6_flush __P((struct in6_addr *, struct ifnet *));
#endif /* _KERNEL */
#endif /* _NETINET6_ND6_H_ */

1123
sys/netinet6/nd6_nbr.c Normal file

File diff suppressed because it is too large Load diff

1243
sys/netinet6/nd6_rtr.c Normal file

File diff suppressed because it is too large Load diff

68
sys/netinet6/pim6.h Normal file
View file

@ -0,0 +1,68 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Protocol Independent Multicast (PIM) definitions
*
* Written by Ahmed Helmy, SGI, July 1996
*
* MULTICAST
*/
/*
* PIM packet header
*/
#define PIM_VERSION 2
struct pim {
#if defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN)
u_char pim_type:4, /* the PIM message type, currently they are:
* Hello, Register, Register-Stop, Join/Prune,
* Bootstrap, Assert, Graft (PIM-DM only),
* Graft-Ack (PIM-DM only), C-RP-Adv
*/
pim_ver:4; /* PIM version number; 2 for PIMv2 */
#else
u_char pim_ver:4, /* PIM version */
pim_type:4; /* PIM type */
#endif
u_char pim_rsv; /* Reserved */
u_short pim_cksum; /* IP style check sum */
};
#define PIM_MINLEN 8 /* The header min. length is 8 */
#define PIM6_REG_MINLEN (PIM_MINLEN+40) /* Register message + inner IP6 header */
/*
* Message types
*/
#define PIM_REGISTER 1 /* PIM Register type is 1 */
/* second bit in reg_head is the null bit */
#define PIM_NULL_REGISTER 0x40000000

71
sys/netinet6/pim6_var.h Normal file
View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/* $Id: pim6_var.h,v 1.2 1999/08/01 15:58:13 itojun Exp $ */
#ifndef _NETINET6_PIM6_VAR_H_
#define _NETINET6_PIM6_VAR_H_
/*
* Protocol Independent Multicast (PIM),
* implementation-specific definitions.
*
* Written by George Edmond Eddy (Rusty), ISI, February 1998
* Modified by Pavlin Ivanov Radoslavov, USC/ISI, May 1998
*/
struct pim6stat {
u_int pim6s_rcv_total; /* total PIM messages received */
u_int pim6s_rcv_tooshort; /* received with too few bytes */
u_int pim6s_rcv_badsum; /* received with bad checksum */
u_int pim6s_rcv_badversion; /* received bad PIM version */
u_int pim6s_rcv_registers; /* received registers */
u_int pim6s_rcv_badregisters; /* received invalid registers */
u_int pim6s_snd_registers; /* sent registers */
};
#if (defined(KERNEL)) || (defined(_KERNEL))
extern struct pim6stat pim6stat;
int pim6_input __P((struct mbuf **, int*, int));
#endif /* KERNEL */
/*
* Names for PIM sysctl objects
*/
#define PIMCTL_STATS 1 /* statistics (read-only) */
#define PIMCTL_MAXID 2
#define PIMCTL_NAMES { \
{ 0, 0 }, \
{ 0, 0 }, \
}
#endif /* _NETINET6_PIM6_VAR_H_ */

612
sys/netinet6/raw_ip6.c Normal file
View file

@ -0,0 +1,612 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
*/
#include "opt_inet.h"
#include "opt_ipsec.h"
#include <stddef.h>
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/socketvar.h>
#include <sys/errno.h>
#include <sys/systm.h>
#include <net/if.h>
#include <net/route.h>
#include <net/if_types.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/in_systm.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/icmp6.h>
#include <netinet/in_pcb.h>
#include <netinet6/in6_pcb.h>
#include <netinet6/nd6.h>
#ifdef IPSEC
#include <netinet6/ipsec.h>
#ifdef INET6
#include <netinet6/ipsec6.h>
#endif /* INET6 */
#endif /*IPSEC*/
#include <machine/stdarg.h>
/* #include "faith.h" */
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
/*
* Raw interface to IP6 protocol.
*/
extern struct inpcbhead ripcb;
extern struct inpcbinfo ripcbinfo;
extern u_long rip_sendspace;
extern u_long rip_recvspace;
/*
* Setup generic address and protocol structures
* for raw_input routine, then pass them along with
* mbuf chain.
*/
int
rip6_input(mp, offp, proto)
struct mbuf **mp;
int *offp, proto;
{
struct mbuf *m = *mp;
register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
register struct inpcb *in6p;
struct inpcb *last = 0;
struct mbuf *opts = 0;
struct sockaddr_in6 rip6src;
#if defined(NFAITH) && 0 < NFAITH
if (m->m_pkthdr.rcvif) {
if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
/* XXX send icmp6 host/port unreach? */
m_freem(m);
return IPPROTO_DONE;
}
}
#endif
init_sin6(&rip6src, m); /* general init */
LIST_FOREACH(in6p, &ripcb, inp_list) {
if ((in6p->in6p_vflag & INP_IPV6) == NULL)
continue;
if (in6p->in6p_ip6_nxt &&
in6p->in6p_ip6_nxt != proto)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
continue;
if (in6p->in6p_cksum != -1
&& in6_cksum(m, ip6->ip6_nxt, *offp,
m->m_pkthdr.len - *offp)) {
/* XXX bark something */
continue;
}
if (last) {
struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
if (n) {
if (last->in6p_flags & IN6P_CONTROLOPTS ||
last->in6p_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, &opts, ip6, n);
/* strip intermediate headers */
m_adj(n, *offp);
if (sbappendaddr(&last->in6p_socket->so_rcv,
(struct sockaddr *)&rip6src,
n, opts) == 0) {
/* should notify about lost packet */
m_freem(n);
if (opts)
m_freem(opts);
} else
sorwakeup(last->in6p_socket);
opts = NULL;
}
}
last = in6p;
}
if (last) {
if (last->in6p_flags & IN6P_CONTROLOPTS ||
last->in6p_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, &opts, ip6, m);
/* strip intermediate headers */
m_adj(m, *offp);
if (sbappendaddr(&last->in6p_socket->so_rcv,
(struct sockaddr *)&rip6src, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
} else
sorwakeup(last->in6p_socket);
} else {
if (proto == IPPROTO_NONE)
m_freem(m);
else {
char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
icmp6_error(m, ICMP6_PARAM_PROB,
ICMP6_PARAMPROB_NEXTHEADER,
prvnxtp - mtod(m, char *));
}
ip6stat.ip6s_delivered--;
}
return IPPROTO_DONE;
}
/*
* Generate IPv6 header and pass packet to ip6_output.
* Tack on options user may have setup with control call.
*/
int
#if __STDC__
rip6_output(struct mbuf *m, ...)
#else
rip6_output(m, va_alist)
struct mbuf *m;
va_dcl
#endif
{
struct socket *so;
struct sockaddr_in6 *dstsock;
struct mbuf *control;
struct in6_addr *dst;
struct ip6_hdr *ip6;
struct inpcb *in6p;
u_int plen = m->m_pkthdr.len;
int error = 0;
struct ip6_pktopts opt, *optp = 0;
struct ifnet *oifp = NULL;
int type = 0, code = 0; /* for ICMPv6 output statistics only */
int priv = 0;
va_list ap;
va_start(ap, m);
so = va_arg(ap, struct socket *);
dstsock = va_arg(ap, struct sockaddr_in6 *);
control = va_arg(ap, struct mbuf *);
va_end(ap);
in6p = sotoin6pcb(so);
priv = 0;
if (so->so_cred->cr_uid == 0)
priv = 1;
dst = &dstsock->sin6_addr;
if (control) {
if ((error = ip6_setpktoptions(control, &opt, priv)) != 0)
goto bad;
optp = &opt;
} else
optp = in6p->in6p_outputopts;
/*
* For an ICMPv6 packet, we should know its type and code
* to update statistics.
*/
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
struct icmp6_hdr *icmp6;
if (m->m_len < sizeof(struct icmp6_hdr) &&
(m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
error = ENOBUFS;
goto bad;
}
icmp6 = mtod(m, struct icmp6_hdr *);
type = icmp6->icmp6_type;
code = icmp6->icmp6_code;
}
M_PREPEND(m, sizeof(*ip6), M_WAIT);
ip6 = mtod(m, struct ip6_hdr *);
/*
* Next header might not be ICMP6 but use its pseudo header anyway.
*/
ip6->ip6_dst = *dst;
/*
* If the scope of the destination is link-local, embed the interface
* index in the address.
*
* XXX advanced-api value overrides sin6_scope_id
*/
if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
struct in6_pktinfo *pi;
/*
* XXX Boundary check is assumed to be already done in
* ip6_setpktoptions().
*/
if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) {
ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex);
oifp = ifindex2ifnet[pi->ipi6_ifindex];
} else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
in6p->in6p_moptions &&
in6p->in6p_moptions->im6o_multicast_ifp) {
oifp = in6p->in6p_moptions->im6o_multicast_ifp;
ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index);
} else if (dstsock->sin6_scope_id) {
/* boundary check */
if (dstsock->sin6_scope_id < 0
|| if_index < dstsock->sin6_scope_id) {
error = ENXIO; /* XXX EINVAL? */
goto bad;
}
ip6->ip6_dst.s6_addr16[1]
= htons(dstsock->sin6_scope_id & 0xffff);/*XXX*/
}
}
/*
* Source address selection.
*/
{
struct in6_addr *in6a;
if ((in6a = in6_selectsrc(dstsock, optp,
in6p->in6p_moptions,
&in6p->in6p_route,
&in6p->in6p_laddr,
&error)) == 0) {
if (error == 0)
error = EADDRNOTAVAIL;
goto bad;
}
ip6->ip6_src = *in6a;
if (in6p->in6p_route.ro_rt)
oifp = ifindex2ifnet[in6p->in6p_route.ro_rt->rt_ifp->if_index];
}
ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
ip6->ip6_vfc = IPV6_VERSION;
/* ip6_plen will be filled in ip6_output, so not fill it here. */
ip6->ip6_nxt = in6p->in6p_ip6_nxt;
ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
in6p->in6p_cksum != -1) {
struct mbuf *n;
int off;
u_int16_t *p;
#define offsetof(type, member) ((size_t)(&((type *)0)->member)) /* XXX */
/* compute checksum */
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
off = offsetof(struct icmp6_hdr, icmp6_cksum);
else
off = in6p->in6p_cksum;
if (plen < off + 1) {
error = EINVAL;
goto bad;
}
off += sizeof(struct ip6_hdr);
n = m;
while (n && n->m_len <= off) {
off -= n->m_len;
n = n->m_next;
}
if (!n)
goto bad;
p = (u_int16_t *)(mtod(n, caddr_t) + off);
*p = 0;
*p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
}
#ifdef IPSEC
m->m_pkthdr.rcvif = (struct ifnet *)so;
#endif /*IPSEC*/
error = ip6_output(m, optp, &in6p->in6p_route, 0, in6p->in6p_moptions,
&oifp);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
if (oifp)
icmp6_ifoutstat_inc(oifp, type, code);
icmp6stat.icp6s_outhist[type]++;
}
goto freectl;
bad:
if (m)
m_freem(m);
freectl:
if (optp == &opt && optp->ip6po_rthdr && optp->ip6po_route.ro_rt)
RTFREE(optp->ip6po_route.ro_rt);
if (control)
m_freem(control);
return(error);
}
/*
* Raw IPv6 socket option processing.
*/
int
rip6_ctloutput(so, sopt)
struct socket *so;
struct sockopt *sopt;
{
int error;
if (sopt->sopt_level == IPPROTO_ICMPV6)
/*
* XXX: is it better to call icmp6_ctloutput() directly
* from protosw?
*/
return(icmp6_ctloutput(so, sopt));
else if (sopt->sopt_level != IPPROTO_IPV6)
return (EINVAL);
error = 0;
switch (sopt->sopt_dir) {
case SOPT_GET:
switch (sopt->sopt_name) {
default:
error = ip6_ctloutput(so, sopt);
break;
}
break;
case SOPT_SET:
switch (sopt->sopt_name) {
default:
error = ip6_ctloutput(so, sopt);
break;
}
break;
}
return (error);
}
static int
rip6_attach(struct socket *so, int proto, struct proc *p)
{
struct inpcb *inp;
int error, s;
inp = sotoinpcb(so);
if (inp)
panic("rip6_attach");
if (p && (error = suser(p)) != 0)
return error;
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
error = soreserve(so, rip_sendspace, rip_recvspace);
if (error)
return error;
}
s = splnet();
error = in_pcballoc(so, &ripcbinfo, p);
splx(s);
if (error)
return error;
inp = (struct inpcb *)so->so_pcb;
inp->inp_vflag |= INP_IPV6;
inp->in6p_ip6_nxt = (long)proto;
inp->in6p_hops = -1; /* use kernel default */
inp->in6p_cksum = -1;
#ifdef IPSEC
error = ipsec_init_policy(so, &inp->in6p_sp);
if (error != 0) {
in6_pcbdetach(inp);
return (error);
}
#endif /*IPSEC*/
MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *,
sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
return 0;
}
static int
rip6_detach(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
if (inp == 0)
panic("rip6_detach");
/* xxx: RSVP */
if (inp->in6p_icmp6filt) {
FREE(inp->in6p_icmp6filt, M_PCB);
inp->in6p_icmp6filt = NULL;
}
in6_pcbdetach(inp);
return 0;
}
static int
rip6_abort(struct socket *so)
{
soisdisconnected(so);
return rip6_detach(so);
}
static int
rip6_disconnect(struct socket *so)
{
struct inpcb *inp = sotoinpcb(so);
if ((so->so_state & SS_ISCONNECTED) == 0)
return ENOTCONN;
inp->in6p_faddr = in6addr_any;
return rip6_abort(so);
}
static int
rip6_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
{
struct inpcb *inp = sotoinpcb(so);
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
struct ifaddr *ia = NULL;
if (nam->sa_len != sizeof(*addr))
return EINVAL;
if (TAILQ_EMPTY(&ifnet) || addr->sin6_family != AF_INET6)
return EADDRNOTAVAIL;
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
(ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0)
return EADDRNOTAVAIL;
if (ia &&
((struct in6_ifaddr *)ia)->ia6_flags &
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
return(EADDRNOTAVAIL);
}
inp->in6p_laddr = addr->sin6_addr;
return 0;
}
static int
rip6_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
{
struct inpcb *inp = sotoinpcb(so);
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
struct in6_addr *in6a = NULL;
int error = 0;
if (nam->sa_len != sizeof(*addr))
return EINVAL;
if (TAILQ_EMPTY(&ifnet))
return EADDRNOTAVAIL;
if (addr->sin6_family != AF_INET6)
return EAFNOSUPPORT;
/* Source address selection. XXX: need pcblookup? */
in6a = in6_selectsrc(addr, inp->in6p_outputopts,
inp->in6p_moptions, &inp->in6p_route,
&inp->in6p_laddr, &error);
if (in6a == NULL)
return (error ? error : EADDRNOTAVAIL);
inp->in6p_laddr = *in6a;
inp->in6p_faddr = addr->sin6_addr;
soisconnected(so);
return 0;
}
static int
rip6_shutdown(struct socket *so)
{
socantsendmore(so);
return 0;
}
static int
rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct mbuf *control, struct proc *p)
{
struct inpcb *inp = sotoinpcb(so);
struct sockaddr_in6 tmp;
struct sockaddr_in6 *dst;
if (so->so_state & SS_ISCONNECTED) {
if (nam) {
m_freem(m);
return EISCONN;
}
/* XXX */
bzero(&tmp, sizeof(tmp));
tmp.sin6_family = AF_INET6;
tmp.sin6_len = sizeof(struct sockaddr_in6);
bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
sizeof(struct in6_addr));
dst = &tmp;
} else {
if (nam == NULL) {
m_freem(m);
return ENOTCONN;
}
dst = (struct sockaddr_in6 *)nam;
}
return rip6_output(m, so, dst, control);
}
struct pr_usrreqs rip6_usrreqs = {
rip6_abort, pru_accept_notsupp, rip6_attach, rip6_bind, rip6_connect,
pru_connect2_notsupp, in6_control, rip6_detach, rip6_disconnect,
pru_listen_notsupp, in6_setpeeraddr, pru_rcvd_notsupp,
pru_rcvoob_notsupp, rip6_send, pru_sense_null, rip6_shutdown,
in6_setsockaddr, sosend, soreceive, sopoll
};

155
sys/netinet6/route6.c Normal file
View file

@ -0,0 +1,155 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet6/in6.h>
#include <netinet6/in6_var.h>
#include <netinet6/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet/icmp6.h>
static int ip6_rthdr0 __P((struct mbuf *, struct ip6_hdr *, struct ip6_rthdr0 *));
int
route6_input(mp, offp, proto)
struct mbuf **mp;
int *offp, proto; /* proto is unused */
{
register struct ip6_hdr *ip6;
register struct mbuf *m = *mp;
register struct ip6_rthdr *rh;
int off = *offp, rhlen;
IP6_EXTHDR_CHECK(m, off, sizeof(*rh), IPPROTO_DONE);
ip6 = mtod(m, struct ip6_hdr *);
rh = (struct ip6_rthdr *)((caddr_t)ip6 + off);
switch(rh->ip6r_type) {
case IPV6_RTHDR_TYPE_0:
rhlen = (rh->ip6r_len + 1) << 3;
IP6_EXTHDR_CHECK(m, off, rhlen, IPPROTO_DONE);
if (ip6_rthdr0(m, ip6, (struct ip6_rthdr0 *)rh))
return(IPPROTO_DONE);
break;
default:
/* unknown routing type */
if (rh->ip6r_segleft == 0) {
rhlen = (rh->ip6r_len + 1) << 3;
break; /* Final dst. Just ignore the header. */
}
ip6stat.ip6s_badoptions++;
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
(caddr_t)&rh->ip6r_type - (caddr_t)ip6);
return(IPPROTO_DONE);
}
*offp += rhlen;
return(rh->ip6r_nxt);
}
/*
* Type0 routing header processing
*/
static int
ip6_rthdr0(m, ip6, rh0)
struct mbuf *m;
struct ip6_hdr *ip6;
struct ip6_rthdr0 *rh0;
{
int addrs, index;
struct in6_addr *nextaddr, tmpaddr;
if (rh0->ip6r0_segleft == 0)
return(0);
if (rh0->ip6r0_len % 2
#ifdef COMPAT_RFC1883
|| rh0->ip6r0_len > 46
#endif
) {
/*
* Type 0 routing header can't contain more than 23 addresses.
* RFC 2462: this limitation was removed since stict/loose
* bitmap field was deleted.
*/
ip6stat.ip6s_badoptions++;
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
(caddr_t)&rh0->ip6r0_len - (caddr_t)ip6);
return(-1);
}
if ((addrs = rh0->ip6r0_len / 2) < rh0->ip6r0_segleft) {
ip6stat.ip6s_badoptions++;
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
(caddr_t)&rh0->ip6r0_segleft - (caddr_t)ip6);
return(-1);
}
index = addrs - rh0->ip6r0_segleft;
rh0->ip6r0_segleft--;
nextaddr = rh0->ip6r0_addr + index;
if (IN6_IS_ADDR_MULTICAST(nextaddr) ||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
ip6stat.ip6s_badoptions++;
m_freem(m);
return(-1);
}
/*
* Swap the IPv6 destination address and nextaddr. Forward the packet.
*/
tmpaddr = *nextaddr;
*nextaddr = ip6->ip6_dst;
if (IN6_IS_ADDR_LINKLOCAL(nextaddr))
nextaddr->s6_addr16[1] = 0;
ip6->ip6_dst = tmpaddr;
if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
ip6->ip6_dst.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
#ifdef COMPAT_RFC1883
if (rh0->ip6r0_slmap[index / 8] & (1 << (7 - (index % 8))))
ip6_forward(m, IPV6_SRCRT_NEIGHBOR);
else
ip6_forward(m, IPV6_SRCRT_NOTNEIGHBOR);
#else
ip6_forward(m, 1);
#endif
return(-1); /* m would be freed in ip6_forward() */
}

83
sys/netinet6/tcp6_var.h Normal file
View file

@ -0,0 +1,83 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1993, 1994, 1995
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)tcp_var.h 8.4 (Berkeley) 5/24/95
* $FreeBSD$
*/
#ifndef _NETINET_TCP6_VAR_H_
#define _NETINET_TCP6_VAR_H_
#ifdef KERNEL
struct ip6_hdr;
void tcp6_ctlinput __P((int, struct sockaddr *, void *));
void tcp6_init __P((void));
int tcp6_input __P((struct mbuf **, int *, int));
struct rtentry *tcp_rtlookup6 __P((struct inpcb *));
extern struct pr_usrreqs tcp6_usrreqs;
#endif /* KERNEL */
#endif /* _NETINET_TCP6_VAR_H_ */

80
sys/netinet6/udp6_var.h Normal file
View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)udp_var.h 8.1 (Berkeley) 6/10/93
*/
#ifndef _NETINET6_UDP6_VAR_H_
#define _NETINET6_UDP6_VAR_H_
#ifdef KERNEL
extern struct pr_usrreqs udp6_usrreqs;
void udp6_ctlinput __P((int, struct sockaddr *, void *));
int udp6_input __P((struct mbuf **, int *, int));
int udp6_output __P((struct inpcb *inp, struct mbuf *m,
struct sockaddr *addr, struct mbuf *control,
struct proc *p));
#endif /* KERNEL */
#endif /*_NETINET6_UDP6_VAR_H_*/

106
sys/netkey/key_var.h Normal file
View file

@ -0,0 +1,106 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#ifndef _NETKEY_KEY_VAR_H_
#define _NETKEY_KEY_VAR_H_
/* sysctl */
#define KEYCTL_DEBUG_LEVEL 1
#define KEYCTL_SPI_TRY 2
#define KEYCTL_SPI_MIN_VALUE 3
#define KEYCTL_SPI_MAX_VALUE 4
#define KEYCTL_RANDOM_INT 5
#define KEYCTL_LARVAL_LIFETIME 6
#define KEYCTL_BLOCKACQ_COUNT 7
#define KEYCTL_BLOCKACQ_LIFETIME 8
#define KEYCTL_MAXID 9
#define KEYCTL_NAMES { \
{ 0, 0 }, \
{ "debug", CTLTYPE_INT }, \
{ "spi_try", CTLTYPE_INT }, \
{ "spi_min_value", CTLTYPE_INT }, \
{ "spi_max_value", CTLTYPE_INT }, \
{ "random_int", CTLTYPE_INT }, \
{ "larval_lifetime", CTLTYPE_INT }, \
{ "blockacq_count", CTLTYPE_INT }, \
{ "blockacq_lifetime", CTLTYPE_INT }, \
}
#define KEYCTL_VARS { \
0, \
&key_debug_level, \
&key_spi_trycnt, \
&key_spi_minval, \
&key_spi_maxval, \
&key_int_random, \
&key_larval_lifetime, \
&key_blockacq_count, \
&key_blockacq_lifetime, \
}
#define _ARRAYLEN(p) (sizeof(p)/sizeof(p[0]))
#define _KEYLEN(key) ((u_int)((key)->sadb_key_bits >> 3))
#define _KEYBITS(key) ((u_int)((key)->sadb_key_bits))
#define _KEYBUF(key) ((caddr_t)((caddr_t)(key) + sizeof(struct sadb_key)))
#define _INADDR(in) ((struct sockaddr_in *)(in))
/* should not ifdef kernel opt in kernel header file */
#if !defined(KERNEL) && !defined(_KERNEL)
#if defined(INET6)
#define _IN6ADDR(in6) ((struct sockaddr_in6 *)(in6))
#define _SALENBYAF(family) \
(((family) == AF_INET) ? \
(u_int)sizeof(struct sockaddr_in) : \
(u_int)sizeof(struct sockaddr_in6))
#define _INALENBYAF(family) \
(((family) == AF_INET) ? \
(u_int)sizeof(struct in_addr) : \
(u_int)sizeof(struct in6_addr))
#define _INADDRBYSA(saddr) \
((((struct sockaddr *)(saddr))->sa_family == AF_INET) ? \
(caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr : \
(caddr_t)&((struct sockaddr_in6 *)(saddr))->sin6_addr)
#define _INPORTBYSA(saddr) \
((((struct sockaddr *)(saddr))->sa_family == AF_INET) ? \
((struct sockaddr_in *)(saddr))->sin_port : \
((struct sockaddr_in6 *)(saddr))->sin6_port)
#else
#define _IN6ADDR(in6) "#error"
#define _SALENBYAF(family) sizeof(struct sockaddr_in)
#define _INALENBYAF(family) sizeof(struct in_addr)
#define _INADDRBYSA(saddr) ((caddr_t)&((struct sockaddr_in *)(saddr))->sin_addr)
#define _INPORTBYSA(saddr) (((struct sockaddr_in *)(saddr))->sin_port)
#endif /* defined(INET6) */
#endif /* !defined(KERNEL) && !defined(_KERNEL) */
#endif /* _NETKEY_KEY_VAR_H_ */

135
sys/netkey/keydb.h Normal file
View file

@ -0,0 +1,135 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
#ifndef _NETKEY_KEYDB_H_
#define _NETKEY_KEYDB_H_
#ifdef KERNEL
/* Security Assocciation Index */
/* NOTE: Encure to be same address family */
struct secasindex {
struct sockaddr_storage src; /* srouce address for SA */
struct sockaddr_storage dst; /* destination address for SA */
u_int16_t proto; /* IPPROTO_ESP or IPPROTO_AH */
u_int8_t mode; /* mode of protocol, see ipsec.h */
};
/* Security Association Data Base */
struct secashead {
LIST_ENTRY(secashead) chain;
struct secasindex saidx;
struct secpolicyindex *owner; /* Indicate it who owned its SA. */
/* If NULL then it's shared SA */
u_int8_t state; /* MATURE or DEAD. */
LIST_HEAD(_satree, secasvar) savtree[SADB_SASTATE_MAX+1];
/* SA chain */
/* The first of this list is newer SA */
struct route sa_route; /* XXX */
};
/* Security Association */
struct secasvar {
LIST_ENTRY(secasvar) chain;
int refcnt; /* reference count */
u_int8_t state; /* Status of this Association */
u_int8_t alg_auth; /* Authentication Algorithm Identifier*/
u_int8_t alg_enc; /* Cipher Algorithm Identifier */
u_int32_t spi; /* SPI Value, network byte order */
u_int32_t flags; /* holder for SADB_KEY_FLAGS */
struct sadb_key *key_auth; /* Key for Authentication */
/* length has been shifted up to 3. */
struct sadb_key *key_enc; /* Key for Encryption */
/* length has been shifted up to 3. */
caddr_t iv; /* Initilization Vector */
u_int ivlen; /* length of IV */
struct secreplay *replay; /* replay prevention */
u_int32_t tick; /* for lifetime */
struct sadb_lifetime *lft_c; /* CURRENT lifetime, it's constant. */
struct sadb_lifetime *lft_h; /* HARD lifetime */
struct sadb_lifetime *lft_s; /* SOFT lifetime */
u_int32_t seq; /* sequence number */
pid_t pid; /* message's pid */
struct secashead *sah; /* back pointer to the secashead */
};
/* replay prevention */
struct secreplay {
u_int32_t count;
u_int wsize; /* window size, i.g. 4 bytes */
u_int32_t seq; /* used by sender */
u_int32_t lastseq; /* used by receiver */
caddr_t bitmap; /* used by receiver */
};
/* socket table due to send PF_KEY messages. */
struct secreg {
LIST_ENTRY(secreg) chain;
struct socket *so;
};
#ifndef IPSEC_NONBLOCK_ACQUIRE
/* acquiring list table. */
struct secacq {
LIST_ENTRY(secacq) chain;
struct secasindex saidx;
u_int32_t seq; /* sequence number */
u_int32_t tick; /* for lifetime */
int count; /* for lifetime */
};
#endif
/* Sensitivity Level Specification */
/* nothing */
#define SADB_KILL_INTERVAL 600 /* six seconds */
struct key_cb {
int key_count;
int any_count;
};
#endif /* KERNEL */
#endif /* _NETKEY_KEYDB_H_ */

56
sys/netkey/keysock.h Normal file
View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*
* $FreeBSD$
*/
/* $Id: keysock.h,v 1.1.6.3.6.1 1999/05/17 17:03:19 itojun Exp $ */
#ifndef _NETKEY_KEYSOCK_H_
#define _NETKEY_KEYSOCK_H_
#if defined(KERNEL)
struct keycb {
struct rawcb kp_raw; /* rawcb */
int kp_promisc; /* promiscuous mode */
int kp_registered; /* registered socket */
};
extern int key_output __P((struct mbuf *, ...));
extern int key_usrreq __P((struct socket *, int, struct mbuf *,
struct mbuf *, struct mbuf *));
#define KEY_SENDUP_ONE 0
#define KEY_SENDUP_ALL 1
#define KEY_SENDUP_REGISTERED 2
extern int key_sendup __P((struct socket *, struct sadb_msg *, u_int,
int));
#endif /* defined(KERNEL) */
#endif _NETKEY_KEYSOCK_H_

View file

@ -355,6 +355,12 @@ struct socket *
int sooptcopyin __P((struct sockopt *sopt, void *buf, size_t len,
size_t minlen));
int sooptcopyout __P((struct sockopt *sopt, void *buf, size_t len));
/* XXX; prepare mbuf for (__FreeBSD__ < 3) routines. */
int soopt_getm __P((struct sockopt *sopt, struct mbuf **mp));
int soopt_mcopyin __P((struct sockopt *sopt, struct mbuf *m));
int soopt_mcopyout __P((struct sockopt *sopt, struct mbuf *m));
int sopoll __P((struct socket *so, int events, struct ucred *cred,
struct proc *p));
int soreceive __P((struct socket *so, struct sockaddr **paddr,