Move rtems/freebsd to freebsd and contrib to freebsd/contrib

This commit is contained in:
Joel Sherrill
2012-03-08 07:25:21 -06:00
parent af079f3ab6
commit e2d2bf579b
758 changed files with 0 additions and 0 deletions

125
freebsd/netinet6/dest6.c Normal file
View File

@@ -0,0 +1,125 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: dest6.c,v 1.59 2003/07/11 13:21:16 t-momose Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_inet.h>
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/domain.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/errno.h>
#include <rtems/freebsd/sys/time.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet/icmp6.h>
/*
* Destination options header processing.
*/
int
dest6_input(struct mbuf **mp, int *offp, int proto)
{
struct mbuf *m = *mp;
int off = *offp, dstoptlen, optlen;
struct ip6_dest *dstopts;
u_int8_t *opt;
/* validation of the length of the header */
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, sizeof(*dstopts), IPPROTO_DONE);
dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
#else
IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, sizeof(*dstopts));
if (dstopts == NULL)
return IPPROTO_DONE;
#endif
dstoptlen = (dstopts->ip6d_len + 1) << 3;
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, dstoptlen, IPPROTO_DONE);
dstopts = (struct ip6_dest *)(mtod(m, caddr_t) + off);
#else
IP6_EXTHDR_GET(dstopts, struct ip6_dest *, m, off, dstoptlen);
if (dstopts == NULL)
return IPPROTO_DONE;
#endif
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) {
if (*opt != IP6OPT_PAD1 &&
(dstoptlen < IP6OPT_MINLEN || *(opt + 1) + 2 > dstoptlen)) {
V_ip6stat.ip6s_toosmall++;
goto bad;
}
switch (*opt) {
case IP6OPT_PAD1:
optlen = 1;
break;
case IP6OPT_PADN:
optlen = *(opt + 1) + 2;
break;
default: /* unknown option */
optlen = ip6_unknown_opt(opt, m,
opt - mtod(m, u_int8_t *));
if (optlen == -1)
return (IPPROTO_DONE);
optlen += 2;
break;
}
}
*offp = off;
return (dstopts->ip6d_nxt);
bad:
m_freem(m);
return (IPPROTO_DONE);
}

781
freebsd/netinet6/frag6.c Normal file
View File

@@ -0,0 +1,781 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: frag6.c,v 1.33 2002/01/07 11:34:48 kjc Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/domain.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/errno.h>
#include <rtems/freebsd/sys/time.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/syslog.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/net/vnet.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet/icmp6.h>
#include <rtems/freebsd/netinet/in_systm.h> /* for ECN definitions */
#include <rtems/freebsd/netinet/ip.h> /* for ECN definitions */
#include <rtems/freebsd/security/mac/mac_framework.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(struct ip6asfrag *, struct ip6asfrag *);
static void frag6_deq(struct ip6asfrag *);
static void frag6_insque(struct ip6q *, struct ip6q *);
static void frag6_remque(struct ip6q *);
static void frag6_freef(struct ip6q *);
static struct mtx ip6qlock;
/*
* These fields all protected by ip6qlock.
*/
static VNET_DEFINE(u_int, frag6_nfragpackets);
static VNET_DEFINE(u_int, frag6_nfrags);
static VNET_DEFINE(struct ip6q, ip6q); /* ip6 reassemble queue */
#define V_frag6_nfragpackets VNET(frag6_nfragpackets)
#define V_frag6_nfrags VNET(frag6_nfrags)
#define V_ip6q VNET(ip6q)
#define IP6Q_LOCK_INIT() mtx_init(&ip6qlock, "ip6qlock", NULL, MTX_DEF);
#define IP6Q_LOCK() mtx_lock(&ip6qlock)
#define IP6Q_TRYLOCK() mtx_trylock(&ip6qlock)
#define IP6Q_LOCK_ASSERT() mtx_assert(&ip6qlock, MA_OWNED)
#define IP6Q_UNLOCK() mtx_unlock(&ip6qlock)
static MALLOC_DEFINE(M_FTABLE, "fragment", "fragment reassembly header");
/*
* Initialise reassembly queue and fragment identifier.
*/
static void
frag6_change(void *tag)
{
V_ip6_maxfragpackets = nmbclusters / 4;
V_ip6_maxfrags = nmbclusters / 4;
}
void
frag6_init(void)
{
V_ip6_maxfragpackets = nmbclusters / 4;
V_ip6_maxfrags = nmbclusters / 4;
V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q;
if (!IS_DEFAULT_VNET(curvnet))
return;
EVENTHANDLER_REGISTER(nmbclusters_change,
frag6_change, NULL, EVENTHANDLER_PRI_ANY);
IP6Q_LOCK_INIT();
}
/*
* In RFC2460, fragment and reassembly rule do not agree with each other,
* in terms of next header field handling in fragment header.
* While the sender will use the same value for all of the fragmented packets,
* receiver is suggested not to check the consistency.
*
* fragment rule (p20):
* (2) A Fragment header containing:
* The Next Header value that identifies the first header of
* the Fragmentable Part of the original packet.
* -> next header field is same for all fragments
*
* reassembly rule (p21):
* The Next Header field of the last header of the Unfragmentable
* Part is obtained from the Next Header field of the first
* fragment's Fragment header.
* -> should grab it from the first fragment only
*
* The following note also contradicts with fragment rule - noone is going to
* send different fragment with different next header field.
*
* additional note (p22):
* The Next Header values in the Fragment headers of different
* fragments of the same original packet may differ. Only the value
* from the Offset zero fragment packet is used for reassembly.
* -> should grab it from the first fragment only
*
* There is no explicit reason given in the RFC. Historical reason maybe?
*/
/*
* Fragment input
*/
int
frag6_input(struct mbuf **mp, int *offp, int proto)
{
struct mbuf *m = *mp, *t;
struct ip6_hdr *ip6;
struct ip6_frag *ip6f;
struct ip6q *q6;
struct ip6asfrag *af6, *ip6af, *af6dwn;
#ifdef IN6_IFSTAT_STRICT
struct in6_ifaddr *ia;
#endif
int offset = *offp, nxt, i, next;
int first_frag = 0;
int fragoff, frgpartlen; /* must be larger than u_int16_t */
struct ifnet *dstifp;
u_int8_t ecn, ecn0;
#if 0
char ip6buf[INET6_ADDRSTRLEN];
#endif
ip6 = mtod(m, struct ip6_hdr *);
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), IPPROTO_DONE);
ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset);
#else
IP6_EXTHDR_GET(ip6f, struct ip6_frag *, m, offset, sizeof(*ip6f));
if (ip6f == NULL)
return (IPPROTO_DONE);
#endif
dstifp = NULL;
#ifdef IN6_IFSTAT_STRICT
/* find the destination interface of the packet. */
if ((ia = ip6_getdstifaddr(m)) != NULL) {
dstifp = ia->ia_ifp;
ifa_free(&ia->ia_ifa);
}
#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,
offsetof(struct ip6_hdr, ip6_plen));
in6_ifstat_inc(dstifp, ifs6_reass_fail);
return IPPROTO_DONE;
}
V_ip6stat.ip6s_fragments++;
in6_ifstat_inc(dstifp, ifs6_reass_reqd);
/* offset now points to data portion */
offset += sizeof(struct ip6_frag);
IP6Q_LOCK();
/*
* Enforce upper bound on number of fragments.
* If maxfrag is 0, never accept fragments.
* If maxfrag is -1, accept all fragments without limitation.
*/
if (V_ip6_maxfrags < 0)
;
else if (V_frag6_nfrags >= (u_int)V_ip6_maxfrags)
goto dropfrag;
for (q6 = V_ip6q.ip6q_next; q6 != &V_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)
#ifdef MAC
&& mac_ip6q_match(m, q6)
#endif
)
break;
if (q6 == &V_ip6q) {
/*
* the first fragment to arrive, create a reassembly queue.
*/
first_frag = 1;
/*
* Enforce upper bound on number of fragmented packets
* for which we attempt reassembly;
* If maxfragpackets is 0, never accept fragments.
* If maxfragpackets is -1, accept all fragments without
* limitation.
*/
if (V_ip6_maxfragpackets < 0)
;
else if (V_frag6_nfragpackets >= (u_int)V_ip6_maxfragpackets)
goto dropfrag;
V_frag6_nfragpackets++;
q6 = (struct ip6q *)malloc(sizeof(struct ip6q), M_FTABLE,
M_NOWAIT);
if (q6 == NULL)
goto dropfrag;
bzero(q6, sizeof(*q6));
#ifdef MAC
if (mac_ip6q_init(q6, M_NOWAIT) != 0) {
free(q6, M_FTABLE);
goto dropfrag;
}
mac_ip6q_create(m, q6);
#endif
frag6_insque(q6, &V_ip6q);
/* ip6q_nxt will be filled afterwards, from 1st fragment */
q6->ip6q_down = q6->ip6q_up = (struct ip6asfrag *)q6;
#ifdef notyet
q6->ip6q_nxtp = (u_char *)nxtp;
#endif
q6->ip6q_ident = ip6f->ip6f_ident;
q6->ip6q_ttl = IPV6_FRAGTTL;
q6->ip6q_src = ip6->ip6_src;
q6->ip6q_dst = ip6->ip6_dst;
q6->ip6q_ecn =
(ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK;
q6->ip6q_unfrglen = -1; /* The 1st fragment has not arrived. */
q6->ip6q_nfrag = 0;
}
/*
* 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) {
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) +
offsetof(struct ip6_frag, ip6f_offlg));
IP6Q_UNLOCK();
return (IPPROTO_DONE);
}
} else if (fragoff + frgpartlen > IPV6_MAXPACKET) {
icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
offset - sizeof(struct ip6_frag) +
offsetof(struct ip6_frag, ip6f_offlg));
IP6Q_UNLOCK();
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) {
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);
free(af6, M_FTABLE);
/* adjust pointer. */
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) +
offsetof(struct ip6_frag, ip6f_offlg));
}
}
}
ip6af = (struct ip6asfrag *)malloc(sizeof(struct ip6asfrag), M_FTABLE,
M_NOWAIT);
if (ip6af == NULL)
goto dropfrag;
bzero(ip6af, sizeof(*ip6af));
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;
}
/*
* Handle ECN by comparing this segment with the first one;
* if CE is set, do not lose CE.
* drop if CE and not-ECT are mixed for the same packet.
*/
ecn = (ntohl(ip6->ip6_flow) >> 20) & IPTOS_ECN_MASK;
ecn0 = q6->ip6q_ecn;
if (ecn == IPTOS_ECN_CE) {
if (ecn0 == IPTOS_ECN_NOTECT) {
free(ip6af, M_FTABLE);
goto dropfrag;
}
if (ecn0 != IPTOS_ECN_CE)
q6->ip6q_ecn = IPTOS_ECN_CE;
}
if (ecn == IPTOS_ECN_NOTECT && ecn0 != IPTOS_ECN_NOTECT) {
free(ip6af, M_FTABLE);
goto dropfrag;
}
/*
* 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 0
/*
* If there is a preceding segment, it may provide some of
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
if (af6->ip6af_up != (struct ip6asfrag *)q6) {
i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
- ip6af->ip6af_off;
if (i > 0) {
if (i >= ip6af->ip6af_frglen)
goto dropfrag;
m_adj(IP6_REASS_MBUF(ip6af), i);
ip6af->ip6af_off += i;
ip6af->ip6af_frglen -= i;
}
}
/*
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
while (af6 != (struct ip6asfrag *)q6 &&
ip6af->ip6af_off + ip6af->ip6af_frglen > af6->ip6af_off) {
i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
if (i < af6->ip6af_frglen) {
af6->ip6af_frglen -= i;
af6->ip6af_off += i;
m_adj(IP6_REASS_MBUF(af6), i);
break;
}
af6 = af6->ip6af_down;
m_freem(IP6_REASS_MBUF(af6->ip6af_up));
frag6_deq(af6->ip6af_up);
}
#else
/*
* 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.
* We don't know which fragment is the bad guy - here we trust
* fragment that came in earlier, with no real reason.
*
* Note: due to changes after disabling this part, mbuf passed to
* m_adj() below now does not meet the requirement.
*/
if (af6->ip6af_up != (struct ip6asfrag *)q6) {
i = af6->ip6af_up->ip6af_off + af6->ip6af_up->ip6af_frglen
- ip6af->ip6af_off;
if (i > 0) {
#if 0 /* suppress the noisy log */
log(LOG_ERR, "%d bytes of a fragment from %s "
"overlaps the previous fragment\n",
i, ip6_sprintf(ip6buf, &q6->ip6q_src));
#endif
free(ip6af, M_FTABLE);
goto dropfrag;
}
}
if (af6 != (struct ip6asfrag *)q6) {
i = (ip6af->ip6af_off + ip6af->ip6af_frglen) - af6->ip6af_off;
if (i > 0) {
#if 0 /* suppress the noisy log */
log(LOG_ERR, "%d bytes of a fragment from %s "
"overlaps the succeeding fragment",
i, ip6_sprintf(ip6buf, &q6->ip6q_src));
#endif
free(ip6af, M_FTABLE);
goto dropfrag;
}
}
#endif
insert:
#ifdef MAC
if (!first_frag)
mac_ip6q_update(m, q6);
#endif
/*
* 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);
V_frag6_nfrags++;
q6->ip6q_nfrag++;
#if 0 /* xxx */
if (q6 != V_ip6q.ip6q_next) {
frag6_remque(q6);
frag6_insque(q6, &V_ip6q);
}
#endif
next = 0;
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = af6->ip6af_down) {
if (af6->ip6af_off != next) {
IP6Q_UNLOCK();
return IPPROTO_DONE;
}
next += af6->ip6af_frglen;
}
if (af6->ip6af_up->ip6af_mff) {
IP6Q_UNLOCK();
return IPPROTO_DONE;
}
/*
* Reassembly is complete; concatenate fragments.
*/
ip6af = q6->ip6q_down;
t = m = IP6_REASS_MBUF(ip6af);
af6 = ip6af->ip6af_down;
frag6_deq(ip6af);
while (af6 != (struct ip6asfrag *)q6) {
af6dwn = af6->ip6af_down;
frag6_deq(af6);
while (t->m_next)
t = t->m_next;
t->m_next = IP6_REASS_MBUF(af6);
m_adj(t->m_next, af6->ip6af_offset);
free(af6, M_FTABLE);
af6 = af6dwn;
}
/* adjust offset to point where the original next header starts */
offset = ip6af->ip6af_offset - sizeof(struct ip6_frag);
free(ip6af, M_FTABLE);
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_plen = htons((u_short)next + offset - sizeof(struct ip6_hdr));
if (q6->ip6q_ecn == IPTOS_ECN_CE)
ip6->ip6_flow |= htonl(IPTOS_ECN_CE << 20);
nxt = q6->ip6q_nxt;
#ifdef notyet
*q6->ip6q_nxtp = (u_char)(nxt & 0xff);
#endif
/* Delete frag6 header */
if (m->m_len >= offset + sizeof(struct ip6_frag)) {
/* This is the only possible case with !PULLDOWN_TEST */
ovbcopy((caddr_t)ip6, (caddr_t)ip6 + sizeof(struct ip6_frag),
offset);
m->m_data += sizeof(struct ip6_frag);
m->m_len -= sizeof(struct ip6_frag);
} else {
/* this comes with no copy if the boundary is on cluster */
if ((t = m_split(m, offset, M_DONTWAIT)) == NULL) {
frag6_remque(q6);
V_frag6_nfrags -= q6->ip6q_nfrag;
#ifdef MAC
mac_ip6q_destroy(q6);
#endif
free(q6, M_FTABLE);
V_frag6_nfragpackets--;
goto dropfrag;
}
m_adj(t, sizeof(struct ip6_frag));
m_cat(m, t);
}
/*
* Store NXT to the original.
*/
{
char *prvnxtp = ip6_get_prevhdr(m, offset); /* XXX */
*prvnxtp = nxt;
}
frag6_remque(q6);
V_frag6_nfrags -= q6->ip6q_nfrag;
#ifdef MAC
mac_ip6q_reassemble(q6, m);
mac_ip6q_destroy(q6);
#endif
free(q6, M_FTABLE);
V_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;
}
V_ip6stat.ip6s_reassembled++;
in6_ifstat_inc(dstifp, ifs6_reass_ok);
/*
* Tell launch routine the next header
*/
*mp = m;
*offp = offset;
IP6Q_UNLOCK();
return nxt;
dropfrag:
IP6Q_UNLOCK();
in6_ifstat_inc(dstifp, ifs6_reass_fail);
V_ip6stat.ip6s_fragdropped++;
m_freem(m);
return IPPROTO_DONE;
}
/*
* Free a fragment reassembly header and all
* associated datagrams.
*/
void
frag6_freef(struct ip6q *q6)
{
struct ip6asfrag *af6, *down6;
IP6Q_LOCK_ASSERT();
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 */
ip6 = mtod(m, struct ip6_hdr *);
/* restore 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);
free(af6, M_FTABLE);
}
frag6_remque(q6);
V_frag6_nfrags -= q6->ip6q_nfrag;
#ifdef MAC
mac_ip6q_destroy(q6);
#endif
free(q6, M_FTABLE);
V_frag6_nfragpackets--;
}
/*
* Put an ip fragment on a reassembly chain.
* Like insque, but pointers in middle of structure.
*/
void
frag6_enq(struct ip6asfrag *af6, struct ip6asfrag *up6)
{
IP6Q_LOCK_ASSERT();
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(struct ip6asfrag *af6)
{
IP6Q_LOCK_ASSERT();
af6->ip6af_up->ip6af_down = af6->ip6af_down;
af6->ip6af_down->ip6af_up = af6->ip6af_up;
}
void
frag6_insque(struct ip6q *new, struct ip6q *old)
{
IP6Q_LOCK_ASSERT();
new->ip6q_prev = old;
new->ip6q_next = old->ip6q_next;
old->ip6q_next->ip6q_prev= new;
old->ip6q_next = new;
}
void
frag6_remque(struct ip6q *p6)
{
IP6Q_LOCK_ASSERT();
p6->ip6q_prev->ip6q_next = p6->ip6q_next;
p6->ip6q_next->ip6q_prev = p6->ip6q_prev;
}
/*
* IPv6 reassembling timer processing;
* if a timer expires on a reassembly
* queue, discard it.
*/
void
frag6_slowtimo(void)
{
VNET_ITERATOR_DECL(vnet_iter);
struct ip6q *q6;
VNET_LIST_RLOCK_NOSLEEP();
IP6Q_LOCK();
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
q6 = V_ip6q.ip6q_next;
if (q6)
while (q6 != &V_ip6q) {
--q6->ip6q_ttl;
q6 = q6->ip6q_next;
if (q6->ip6q_prev->ip6q_ttl == 0) {
V_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 (V_frag6_nfragpackets > (u_int)V_ip6_maxfragpackets &&
V_ip6q.ip6q_prev) {
V_ip6stat.ip6s_fragoverflow++;
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
frag6_freef(V_ip6q.ip6q_prev);
}
CURVNET_RESTORE();
}
IP6Q_UNLOCK();
VNET_LIST_RUNLOCK_NOSLEEP();
}
/*
* Drain off all datagram fragments.
*/
void
frag6_drain(void)
{
VNET_ITERATOR_DECL(vnet_iter);
VNET_LIST_RLOCK_NOSLEEP();
if (IP6Q_TRYLOCK() == 0) {
VNET_LIST_RUNLOCK_NOSLEEP();
return;
}
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
while (V_ip6q.ip6q_next != &V_ip6q) {
V_ip6stat.ip6s_fragdropped++;
/* XXX in6_ifstat_inc(ifp, ifs6_reass_fail) */
frag6_freef(V_ip6q.ip6q_next);
}
CURVNET_RESTORE();
}
IP6Q_UNLOCK();
VNET_LIST_RUNLOCK_NOSLEEP();
}

2857
freebsd/netinet6/icmp6.c Normal file

File diff suppressed because it is too large Load Diff

4
freebsd/netinet6/icmp6.h Normal file
View File

@@ -0,0 +1,4 @@
/* $FreeBSD$ */
/* $KAME: icmp6.h,v 1.17 2000/06/11 17:23:40 jinmei Exp $ */
#error "netinet6/icmp6.h is obsolete. use netinet/icmp6.h"

2671
freebsd/netinet6/in6.c Normal file

File diff suppressed because it is too large Load Diff

708
freebsd/netinet6/in6.h Normal file
View File

@@ -0,0 +1,708 @@
/*-
* 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.
*
* $KAME: in6.h,v 1.89 2001/05/27 13:28:35 itojun Exp $
*/
/*-
* 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.
* 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.h 8.3 (Berkeley) 1/3/94
* $FreeBSD$
*/
#ifndef __KAME_NETINET_IN_HH_INCLUDED_
#error "do not include netinet6/in6.h directly, include netinet/in.h. see RFC2553"
#endif
#ifndef _NETINET6_IN6_HH_
#define _NETINET6_IN6_HH_
/*
* Identification of the network protocol stack
* for *BSD-current/release: http://www.kame.net/dev/cvsweb.cgi/kame/COVERAGE
* has the table of implementation/integration differences.
*/
#define __KAME__
#define __KAME_VERSION "FreeBSD"
/*
* IPv6 port allocation rules should mirror the IPv4 rules and are controlled
* by the the net.inet.ip.portrange sysctl tree. The following defines exist
* for compatibility with userland applications that need them.
*/
#if __BSD_VISIBLE
#define IPV6PORT_RESERVED 1024
#define IPV6PORT_ANONMIN 49152
#define IPV6PORT_ANONMAX 65535
#define IPV6PORT_RESERVEDMIN 600
#define IPV6PORT_RESERVEDMAX (IPV6PORT_RESERVED-1)
#endif
/*
* IPv6 address
*/
struct in6_addr {
union {
uint8_t __u6_addr8[16];
uint16_t __u6_addr16[8];
uint32_t __u6_addr32[4];
} __u6_addr; /* 128-bit IP6 address */
};
#define s6_addr __u6_addr.__u6_addr8
#ifdef _KERNEL /* XXX nonstandard */
#define s6_addr8 __u6_addr.__u6_addr8
#define s6_addr16 __u6_addr.__u6_addr16
#define s6_addr32 __u6_addr.__u6_addr32
#endif
#define INET6_ADDRSTRLEN 46
/*
* XXX missing POSIX.1-2001 macro IPPROTO_IPV6.
*/
/*
* Socket address for IPv6
*/
#if __BSD_VISIBLE
#define SIN6_LEN
#endif
struct sockaddr_in6 {
uint8_t sin6_len; /* length of this struct */
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* Transport layer port # */
uint32_t sin6_flowinfo; /* IP6 flow information */
struct in6_addr sin6_addr; /* IP6 address */
uint32_t sin6_scope_id; /* scope zone index */
};
/*
* Local definition for masks
*/
#ifdef _KERNEL /* XXX nonstandard */
#define IN6MASK0 {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}}
#define IN6MASK32 {{{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
#define IN6MASK64 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
#define IN6MASK96 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}
#define IN6MASK128 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}
#endif
#ifdef _KERNEL
extern const struct sockaddr_in6 sa6_any;
extern const struct in6_addr in6mask0;
extern const struct in6_addr in6mask32;
extern const struct in6_addr in6mask64;
extern const struct in6_addr in6mask96;
extern const struct in6_addr in6mask128;
#endif /* _KERNEL */
/*
* Macros started with IPV6_ADDR is KAME local
*/
#ifdef _KERNEL /* XXX nonstandard */
#if _BYTE_ORDER == _BIG_ENDIAN
#define IPV6_ADDR_INT32_ONE 1
#define IPV6_ADDR_INT32_TWO 2
#define IPV6_ADDR_INT32_MNL 0xff010000
#define IPV6_ADDR_INT32_MLL 0xff020000
#define IPV6_ADDR_INT32_SMP 0x0000ffff
#define IPV6_ADDR_INT16_ULL 0xfe80
#define IPV6_ADDR_INT16_USL 0xfec0
#define IPV6_ADDR_INT16_MLL 0xff02
#elif _BYTE_ORDER == _LITTLE_ENDIAN
#define IPV6_ADDR_INT32_ONE 0x01000000
#define IPV6_ADDR_INT32_TWO 0x02000000
#define IPV6_ADDR_INT32_MNL 0x000001ff
#define IPV6_ADDR_INT32_MLL 0x000002ff
#define IPV6_ADDR_INT32_SMP 0xffff0000
#define IPV6_ADDR_INT16_ULL 0x80fe
#define IPV6_ADDR_INT16_USL 0xc0fe
#define IPV6_ADDR_INT16_MLL 0x02ff
#endif
#endif
/*
* Definition of some useful macros to handle IP6 addresses
*/
#if __BSD_VISIBLE
#define IN6ADDR_ANY_INIT \
{{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
#define IN6ADDR_LOOPBACK_INIT \
{{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
#define IN6ADDR_NODELOCAL_ALLNODES_INIT \
{{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
#define IN6ADDR_INTFACELOCAL_ALLNODES_INIT \
{{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
#define IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT \
{{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16 }}}
#endif
extern const struct in6_addr in6addr_any;
extern const struct in6_addr in6addr_loopback;
#if __BSD_VISIBLE
extern const struct in6_addr in6addr_nodelocal_allnodes;
extern const struct in6_addr in6addr_linklocal_allnodes;
extern const struct in6_addr in6addr_linklocal_allrouters;
extern const struct in6_addr in6addr_linklocal_allv2routers;
#endif
/*
* Equality
* NOTE: Some of kernel programming environment (for example, openbsd/sparc)
* does not supply memcmp(). For userland memcmp() is preferred as it is
* in ANSI standard.
*/
#ifdef _KERNEL
#define IN6_ARE_ADDR_EQUAL(a, b) \
(bcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
#else
#if __BSD_VISIBLE
#define IN6_ARE_ADDR_EQUAL(a, b) \
(memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
#endif
#endif
/*
* Unspecified
*/
#define IN6_IS_ADDR_UNSPECIFIED(a) \
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) == 0))
/*
* Loopback
*/
#define IN6_IS_ADDR_LOOPBACK(a) \
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) == ntohl(1)))
/*
* IPv4 compatible
*/
#define IN6_IS_ADDR_V4COMPAT(a) \
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) != 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[12]) != ntohl(1)))
/*
* Mapped
*/
#define IN6_IS_ADDR_V4MAPPED(a) \
((*(const u_int32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
(*(const u_int32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff)))
/*
* KAME Scope Values
*/
#ifdef _KERNEL /* XXX nonstandard */
#define IPV6_ADDR_SCOPE_NODELOCAL 0x01
#define IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
#define IPV6_ADDR_SCOPE_LINKLOCAL 0x02
#define IPV6_ADDR_SCOPE_SITELOCAL 0x05
#define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
#define IPV6_ADDR_SCOPE_GLOBAL 0x0e
#else
#define __IPV6_ADDR_SCOPE_NODELOCAL 0x01
#define __IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
#define __IPV6_ADDR_SCOPE_LINKLOCAL 0x02
#define __IPV6_ADDR_SCOPE_SITELOCAL 0x05
#define __IPV6_ADDR_SCOPE_ORGLOCAL 0x08 /* just used in this file */
#define __IPV6_ADDR_SCOPE_GLOBAL 0x0e
#endif
/*
* Unicast Scope
* Note that we must check topmost 10 bits only, not 16 bits (see RFC2373).
*/
#define IN6_IS_ADDR_LINKLOCAL(a) \
(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
#define IN6_IS_ADDR_SITELOCAL(a) \
(((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
/*
* Multicast
*/
#define IN6_IS_ADDR_MULTICAST(a) ((a)->s6_addr[0] == 0xff)
#ifdef _KERNEL /* XXX nonstandard */
#define IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
#else
#define __IPV6_ADDR_MC_SCOPE(a) ((a)->s6_addr[1] & 0x0f)
#endif
/*
* Multicast Scope
*/
#ifdef _KERNEL /* refers nonstandard items */
#define IN6_IS_ADDR_MC_NODELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL))
#define IN6_IS_ADDR_MC_INTFACELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_INTFACELOCAL))
#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL))
#define IN6_IS_ADDR_MC_SITELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_SITELOCAL))
#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_ORGLOCAL))
#define IN6_IS_ADDR_MC_GLOBAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL))
#else
#define IN6_IS_ADDR_MC_NODELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL))
#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL))
#define IN6_IS_ADDR_MC_SITELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL))
#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL))
#define IN6_IS_ADDR_MC_GLOBAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && \
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL))
#endif
#ifdef _KERNEL /* nonstandard */
/*
* KAME Scope
*/
#define IN6_IS_SCOPE_LINKLOCAL(a) \
((IN6_IS_ADDR_LINKLOCAL(a)) || \
(IN6_IS_ADDR_MC_LINKLOCAL(a)))
#define IN6_IS_SCOPE_EMBED(a) \
((IN6_IS_ADDR_LINKLOCAL(a)) || \
(IN6_IS_ADDR_MC_LINKLOCAL(a)) || \
(IN6_IS_ADDR_MC_INTFACELOCAL(a)))
#define IFA6_IS_DEPRECATED(a) \
((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
(u_int32_t)((time_second - (a)->ia6_updatetime)) > \
(a)->ia6_lifetime.ia6t_pltime)
#define IFA6_IS_INVALID(a) \
((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \
(u_int32_t)((time_second - (a)->ia6_updatetime)) > \
(a)->ia6_lifetime.ia6t_vltime)
#endif /* _KERNEL */
/*
* IP6 route structure
*/
#if __BSD_VISIBLE
struct route_in6 {
struct rtentry *ro_rt;
struct llentry *ro_lle;
struct sockaddr_in6 ro_dst;
};
#endif
/*
* Options for use with [gs]etsockopt at the IPV6 level.
* First word of comment is data type; bool is stored in int.
*/
/* no hdrincl */
#if 0 /* the followings are relic in IPv4 and hence are disabled */
#define IPV6_OPTIONS 1 /* buf/ip6_opts; set/get IP6 options */
#define IPV6_RECVOPTS 5 /* bool; receive all IP6 opts w/dgram */
#define IPV6_RECVRETOPTS 6 /* bool; receive IP6 opts for response */
#define IPV6_RECVDSTADDR 7 /* bool; receive IP6 dst addr w/dgram */
#define IPV6_RETOPTS 8 /* ip6_opts; set/get IP6 options */
#endif
#define IPV6_SOCKOPT_RESERVED1 3 /* reserved for future use */
#define IPV6_UNICAST_HOPS 4 /* int; IP6 hops */
#define IPV6_MULTICAST_IF 9 /* u_int; set/get IP6 multicast i/f */
#define IPV6_MULTICAST_HOPS 10 /* int; set/get IP6 multicast hops */
#define IPV6_MULTICAST_LOOP 11 /* u_int; set/get IP6 multicast loopback */
#define IPV6_JOIN_GROUP 12 /* ip6_mreq; join a group membership */
#define IPV6_LEAVE_GROUP 13 /* ip6_mreq; leave a group membership */
#define IPV6_PORTRANGE 14 /* int; range to choose for unspec port */
#define ICMP6_FILTER 18 /* icmp6_filter; icmp6 filter */
/* RFC2292 options */
#ifdef _KERNEL
#define IPV6_2292PKTINFO 19 /* bool; send/recv if, src/dst addr */
#define IPV6_2292HOPLIMIT 20 /* bool; hop limit */
#define IPV6_2292NEXTHOP 21 /* bool; next hop addr */
#define IPV6_2292HOPOPTS 22 /* bool; hop-by-hop option */
#define IPV6_2292DSTOPTS 23 /* bool; destinaion option */
#define IPV6_2292RTHDR 24 /* bool; routing header */
#define IPV6_2292PKTOPTIONS 25 /* buf/cmsghdr; set/get IPv6 options */
#endif
#define IPV6_CHECKSUM 26 /* int; checksum offset for raw socket */
#define IPV6_V6ONLY 27 /* bool; make AF_INET6 sockets v6 only */
#ifndef _KERNEL
#define IPV6_BINDV6ONLY IPV6_V6ONLY
#endif
#if 1 /* IPSEC */
#define IPV6_IPSEC_POLICY 28 /* struct; get/set security policy */
#endif /* IPSEC */
#define IPV6_FAITH 29 /* bool; accept FAITH'ed connections */
#if 1 /* IPV6FIREWALL */
#define IPV6_FW_ADD 30 /* add a firewall rule to chain */
#define IPV6_FW_DEL 31 /* delete a firewall rule from chain */
#define IPV6_FW_FLUSH 32 /* flush firewall rule chain */
#define IPV6_FW_ZERO 33 /* clear single/all firewall counter(s) */
#define IPV6_FW_GET 34 /* get entire firewall rule chain */
#endif
/* new socket options introduced in RFC3542 */
#define IPV6_RTHDRDSTOPTS 35 /* ip6_dest; send dst option before rthdr */
#define IPV6_RECVPKTINFO 36 /* bool; recv if, dst addr */
#define IPV6_RECVHOPLIMIT 37 /* bool; recv hop limit */
#define IPV6_RECVRTHDR 38 /* bool; recv routing header */
#define IPV6_RECVHOPOPTS 39 /* bool; recv hop-by-hop option */
#define IPV6_RECVDSTOPTS 40 /* bool; recv dst option after rthdr */
#ifdef _KERNEL
#define IPV6_RECVRTHDRDSTOPTS 41 /* bool; recv dst option before rthdr */
#endif
#define IPV6_USE_MIN_MTU 42 /* bool; send packets at the minimum MTU */
#define IPV6_RECVPATHMTU 43 /* bool; notify an according MTU */
#define IPV6_PATHMTU 44 /* mtuinfo; get the current path MTU (sopt),
4 bytes int; MTU notification (cmsg) */
#if 0 /*obsoleted during 2292bis -> 3542*/
#define IPV6_REACHCONF 45 /* no data; ND reachability confirm
(cmsg only/not in of RFC3542) */
#endif
/* more new socket options introduced in RFC3542 */
#define IPV6_PKTINFO 46 /* in6_pktinfo; send if, src addr */
#define IPV6_HOPLIMIT 47 /* int; send hop limit */
#define IPV6_NEXTHOP 48 /* sockaddr; next hop addr */
#define IPV6_HOPOPTS 49 /* ip6_hbh; send hop-by-hop option */
#define IPV6_DSTOPTS 50 /* ip6_dest; send dst option befor rthdr */
#define IPV6_RTHDR 51 /* ip6_rthdr; send routing header */
#if 0
#define IPV6_PKTOPTIONS 52 /* buf/cmsghdr; set/get IPv6 options */
/* obsoleted by RFC3542 */
#endif
#define IPV6_RECVTCLASS 57 /* bool; recv traffic class values */
#define IPV6_AUTOFLOWLABEL 59 /* bool; attach flowlabel automagically */
#define IPV6_TCLASS 61 /* int; send traffic class value */
#define IPV6_DONTFRAG 62 /* bool; disable IPv6 fragmentation */
#define IPV6_PREFER_TEMPADDR 63 /* int; prefer temporary addresses as
* the source address.
*/
#define IPV6_BINDANY 64 /* bool: allow bind to any address */
/*
* The following option is private; do not use it from user applications.
* It is deliberately defined to the same value as IP_MSFILTER.
*/
#define IPV6_MSFILTER 74 /* struct __msfilterreq;
* set/get multicast source filter list.
*/
/* to define items, should talk with KAME guys first, for *BSD compatibility */
#define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor. XXX old spec */
#define IPV6_RTHDR_STRICT 1 /* this hop must be a neighbor. XXX old spec */
#define IPV6_RTHDR_TYPE_0 0 /* IPv6 routing header type 0 */
/*
* Defaults and limits for options
*/
#define IPV6_DEFAULT_MULTICAST_HOPS 1 /* normally limit m'casts to 1 hop */
#define IPV6_DEFAULT_MULTICAST_LOOP 1 /* normally hear sends if a member */
/*
* The im6o_membership vector for each socket is now dynamically allocated at
* run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
* according to a power-of-two increment.
*/
#define IPV6_MIN_MEMBERSHIPS 31
#define IPV6_MAX_MEMBERSHIPS 4095
/*
* Default resource limits for IPv6 multicast source filtering.
* These may be modified by sysctl.
*/
#define IPV6_MAX_GROUP_SRC_FILTER 512 /* sources per group */
#define IPV6_MAX_SOCK_SRC_FILTER 128 /* sources per socket/group */
/*
* Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP.
*/
struct ipv6_mreq {
struct in6_addr ipv6mr_multiaddr;
unsigned int ipv6mr_interface;
};
/*
* IPV6_PKTINFO: Packet information(RFC2292 sec 5)
*/
struct in6_pktinfo {
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
unsigned int ipi6_ifindex; /* send/recv interface index */
};
/*
* Control structure for IPV6_RECVPATHMTU socket option.
*/
struct ip6_mtuinfo {
struct sockaddr_in6 ip6m_addr; /* or sockaddr_storage? */
uint32_t ip6m_mtu;
};
/*
* Argument for IPV6_PORTRANGE:
* - which range to search when port is unspecified at bind() or connect()
*/
#define IPV6_PORTRANGE_DEFAULT 0 /* default range */
#define IPV6_PORTRANGE_HIGH 1 /* "high" - request firewall bypass */
#define IPV6_PORTRANGE_LOW 2 /* "low" - vouchsafe security */
#if __BSD_VISIBLE
/*
* Definitions for inet6 sysctl operations.
*
* Third level is protocol number.
* Fourth level is desired variable within that protocol.
*/
#define IPV6PROTO_MAXID (IPPROTO_PIM + 1) /* don't list to IPV6PROTO_MAX */
/*
* Names for IP sysctl objects
*/
#define IPV6CTL_FORWARDING 1 /* act as router */
#define IPV6CTL_SENDREDIRECTS 2 /* may send redirects when forwarding*/
#define IPV6CTL_DEFHLIM 3 /* default Hop-Limit */
#ifdef notyet
#define IPV6CTL_DEFMTU 4 /* default MTU */
#endif
#define IPV6CTL_FORWSRCRT 5 /* forward source-routed dgrams */
#define IPV6CTL_STATS 6 /* stats */
#define IPV6CTL_MRTSTATS 7 /* multicast forwarding stats */
#define IPV6CTL_MRTPROTO 8 /* multicast routing protocol */
#define IPV6CTL_MAXFRAGPACKETS 9 /* max packets reassembly queue */
#define IPV6CTL_SOURCECHECK 10 /* verify source route and intf */
#define IPV6CTL_SOURCECHECK_LOGINT 11 /* minimume logging interval */
#define IPV6CTL_ACCEPT_RTADV 12
#define IPV6CTL_KEEPFAITH 13
#define IPV6CTL_LOG_INTERVAL 14
#define IPV6CTL_HDRNESTLIMIT 15
#define IPV6CTL_DAD_COUNT 16
#define IPV6CTL_AUTO_FLOWLABEL 17
#define IPV6CTL_DEFMCASTHLIM 18
#define IPV6CTL_GIF_HLIM 19 /* default HLIM for gif encap packet */
#define IPV6CTL_KAME_VERSION 20
#define IPV6CTL_USE_DEPRECATED 21 /* use deprecated addr (RFC2462 5.5.4) */
#define IPV6CTL_RR_PRUNE 22 /* walk timer for router renumbering */
#if 0 /* obsolete */
#define IPV6CTL_MAPPED_ADDR 23
#endif
#define IPV6CTL_V6ONLY 24
#define IPV6CTL_RTEXPIRE 25 /* cloned route expiration time */
#define IPV6CTL_RTMINEXPIRE 26 /* min value for expiration time */
#define IPV6CTL_RTMAXCACHE 27 /* trigger level for dynamic expire */
#define IPV6CTL_USETEMPADDR 32 /* use temporary addresses (RFC3041) */
#define IPV6CTL_TEMPPLTIME 33 /* preferred lifetime for tmpaddrs */
#define IPV6CTL_TEMPVLTIME 34 /* valid lifetime for tmpaddrs */
#define IPV6CTL_AUTO_LINKLOCAL 35 /* automatic link-local addr assign */
#define IPV6CTL_RIP6STATS 36 /* raw_ip6 stats */
#define IPV6CTL_PREFER_TEMPADDR 37 /* prefer temporary addr as src */
#define IPV6CTL_ADDRCTLPOLICY 38 /* get/set address selection policy */
#define IPV6CTL_USE_DEFAULTZONE 39 /* use default scope zone */
#define IPV6CTL_MAXFRAGS 41 /* max fragments */
#if 0
#define IPV6CTL_IFQ 42 /* ip6intrq node */
#define IPV6CTL_ISATAPRTR 43 /* isatap router */
#endif
#define IPV6CTL_MCAST_PMTU 44 /* enable pMTU discovery for multicast? */
/* New entries should be added here from current IPV6CTL_MAXID value. */
/* to define items, should talk with KAME guys first, for *BSD compatibility */
#define IPV6CTL_STEALTH 45
#define ICMPV6CTL_ND6_ONLINKNSRFC4861 47
#define IPV6CTL_MAXID 48
#endif /* __BSD_VISIBLE */
/*
* Redefinition of mbuf flags
*/
#define M_AUTHIPHDR M_PROTO2
#define M_DECRYPTED M_PROTO3
#define M_LOOP M_PROTO4
#define M_AUTHIPDGM M_PROTO5
#define M_RTALERT_MLD M_PROTO6
#ifdef _KERNEL
struct cmsghdr;
int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
int in6_localaddr __P((struct in6_addr *));
int in6_addrscope __P((struct in6_addr *));
struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *));
extern void in6_if_up __P((struct ifnet *));
struct sockaddr;
extern u_char ip6_protox[];
void in6_sin6_2_sin __P((struct sockaddr_in *sin,
struct sockaddr_in6 *sin6));
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));
extern void addrsel_policy_init __P((void));
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
extern int (*faithprefix_p)(struct in6_addr *);
#endif /* _KERNEL */
#ifndef _SIZE_T_DECLARED
typedef __size_t size_t;
#define _SIZE_T_DECLARED
#endif
#ifndef _SOCKLEN_T_DECLARED
typedef __socklen_t socklen_t;
#define _SOCKLEN_T_DECLARED
#endif
#if __BSD_VISIBLE
__BEGIN_DECLS
struct cmsghdr;
extern int inet6_option_space __P((int));
extern int inet6_option_init __P((void *, struct cmsghdr **, int));
extern int inet6_option_append __P((struct cmsghdr *, const uint8_t *,
int, int));
extern uint8_t *inet6_option_alloc __P((struct cmsghdr *, int, int, int));
extern int inet6_option_next __P((const struct cmsghdr *, uint8_t **));
extern int inet6_option_find __P((const struct cmsghdr *, uint8_t **, int));
extern size_t inet6_rthdr_space __P((int, int));
extern struct cmsghdr *inet6_rthdr_init __P((void *, int));
extern int inet6_rthdr_add __P((struct cmsghdr *, const struct in6_addr *,
unsigned int));
extern int inet6_rthdr_lasthop __P((struct cmsghdr *, unsigned int));
#if 0 /* not implemented yet */
extern int inet6_rthdr_reverse __P((const struct cmsghdr *, struct cmsghdr *));
#endif
extern int inet6_rthdr_segments __P((const struct cmsghdr *));
extern struct in6_addr *inet6_rthdr_getaddr __P((struct cmsghdr *, int));
extern int inet6_rthdr_getflags __P((const struct cmsghdr *, int));
extern int inet6_opt_init __P((void *, socklen_t));
extern int inet6_opt_append __P((void *, socklen_t, int, uint8_t, socklen_t,
uint8_t, void **));
extern int inet6_opt_finish __P((void *, socklen_t, int));
extern int inet6_opt_set_val __P((void *, int, void *, socklen_t));
extern int inet6_opt_next __P((void *, socklen_t, int, uint8_t *, socklen_t *,
void **));
extern int inet6_opt_find __P((void *, socklen_t, int, uint8_t, socklen_t *,
void **));
extern int inet6_opt_get_val __P((void *, int, void *, socklen_t));
extern socklen_t inet6_rth_space __P((int, int));
extern void *inet6_rth_init __P((void *, socklen_t, int, int));
extern int inet6_rth_add __P((void *, const struct in6_addr *));
extern int inet6_rth_reverse __P((const void *, void *));
extern int inet6_rth_segments __P((const void *));
extern struct in6_addr *inet6_rth_getaddr __P((const void *, int));
__END_DECLS
#endif /* __BSD_VISIBLE */
#endif /* !_NETINET6_IN6_HH_ */

View File

@@ -0,0 +1,303 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: in6_cksum.c,v 1.10 2000/12/03 00:53:59 itojun Exp $
*/
/*-
* 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.
* 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 <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/scope6_var.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);}
/*
* m MUST contain a continuous IP6 header.
* off is an 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(struct mbuf *m, u_int8_t nxt, u_int32_t off, u_int32_t len)
{
u_int16_t *w;
int sum = 0;
int mlen = 0;
int byte_swapped = 0;
struct ip6_hdr *ip6;
struct in6_addr in6;
union {
u_int16_t phs[4];
struct {
u_int32_t ph_len;
u_int8_t ph_zero[3];
u_int8_t ph_nxt;
} __packed ph;
} uph;
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)",
m->m_pkthdr.len, off, len);
}
bzero(&uph, sizeof(uph));
/*
* First create IP6 pseudo header and calculate a summary.
*/
ip6 = mtod(m, struct ip6_hdr *);
uph.ph.ph_len = htonl(len);
uph.ph.ph_nxt = nxt;
/*
* IPv6 source address.
* XXX: we'd like to avoid copying the address, but we can't due to
* the possibly embedded scope zone ID.
*/
in6 = ip6->ip6_src;
in6_clearscope(&in6);
w = (u_int16_t *)&in6;
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
/* IPv6 destination address */
in6 = ip6->ip6_dst;
in6_clearscope(&in6);
w = (u_int16_t *)&in6;
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
/* 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 (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");
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);
}

466
freebsd/netinet6/in6_gif.c Normal file
View File

@@ -0,0 +1,466 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: in6_gif.c,v 1.49 2001/05/14 14:02:17 itojun Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_inet.h>
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/sockio.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/errno.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/queue.h>
#include <rtems/freebsd/sys/syslog.h>
#include <rtems/freebsd/sys/sysctl.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_systm.h>
#ifdef INET
#include <rtems/freebsd/netinet/ip.h>
#endif
#include <rtems/freebsd/netinet/ip_encap.h>
#ifdef INET6
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/in6_gif.h>
#include <rtems/freebsd/netinet6/in6_var.h>
#endif
#include <rtems/freebsd/netinet6/ip6protosw.h>
#include <rtems/freebsd/netinet/ip_ecn.h>
#ifdef INET6
#include <rtems/freebsd/netinet6/ip6_ecn.h>
#endif
#include <rtems/freebsd/net/if_gif.h>
VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
SYSCTL_DECL(_net_inet6_ip6);
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW,
&VNET_NAME(ip6_gif_hlim), 0, "");
static int gif_validate6(const struct ip6_hdr *, struct gif_softc *,
struct ifnet *);
extern struct domain inet6domain;
struct ip6protosw in6_gif_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = 0, /* IPPROTO_IPV[46] */
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = in6_gif_input,
.pr_output = rip6_output,
.pr_ctloutput = rip6_ctloutput,
.pr_usrreqs = &rip6_usrreqs
};
int
in6_gif_output(struct ifnet *ifp,
int family, /* family of the packet to be encapsulate */
struct mbuf *m)
{
struct gif_softc *sc = ifp->if_softc;
struct sockaddr_in6 *dst = (struct sockaddr_in6 *)&sc->gif_ro6.ro_dst;
struct sockaddr_in6 *sin6_src = (struct sockaddr_in6 *)sc->gif_psrc;
struct sockaddr_in6 *sin6_dst = (struct sockaddr_in6 *)sc->gif_pdst;
struct ip6_hdr *ip6;
struct etherip_header eiphdr;
int error, len, proto;
u_int8_t itos, otos;
GIF_LOCK_ASSERT(sc);
if (sin6_src == NULL || sin6_dst == NULL ||
sin6_src->sin6_family != AF_INET6 ||
sin6_dst->sin6_family != AF_INET6) {
m_freem(m);
return EAFNOSUPPORT;
}
switch (family) {
#ifdef INET
case AF_INET:
{
struct ip *ip;
proto = IPPROTO_IPV4;
if (m->m_len < sizeof(*ip)) {
m = m_pullup(m, sizeof(*ip));
if (!m)
return ENOBUFS;
}
ip = mtod(m, struct ip *);
itos = ip->ip_tos;
break;
}
#endif
#ifdef INET6
case AF_INET6:
{
struct ip6_hdr *ip6;
proto = IPPROTO_IPV6;
if (m->m_len < sizeof(*ip6)) {
m = m_pullup(m, sizeof(*ip6));
if (!m)
return ENOBUFS;
}
ip6 = mtod(m, struct ip6_hdr *);
itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
break;
}
#endif
case AF_LINK:
proto = IPPROTO_ETHERIP;
/*
* GIF_SEND_REVETHIP (disabled by default) intentionally
* sends an EtherIP packet with revered version field in
* the header. This is a knob for backward compatibility
* with FreeBSD 7.2R or prior.
*/
if ((sc->gif_options & GIF_SEND_REVETHIP)) {
eiphdr.eip_ver = 0;
eiphdr.eip_resvl = ETHERIP_VERSION;
eiphdr.eip_resvh = 0;
} else {
eiphdr.eip_ver = ETHERIP_VERSION;
eiphdr.eip_resvl = 0;
eiphdr.eip_resvh = 0;
}
/* prepend Ethernet-in-IP header */
M_PREPEND(m, sizeof(struct etherip_header), M_DONTWAIT);
if (m && m->m_len < sizeof(struct etherip_header))
m = m_pullup(m, sizeof(struct etherip_header));
if (m == NULL)
return ENOBUFS;
bcopy(&eiphdr, mtod(m, struct etherip_header *),
sizeof(struct etherip_header));
break;
default:
#ifdef DEBUG
printf("in6_gif_output: warning: unknown family %d passed\n",
family);
#endif
m_freem(m);
return EAFNOSUPPORT;
}
/* prepend new IP header */
len = sizeof(struct ip6_hdr);
#ifndef __NO_STRICT_ALIGNMENT
if (family == AF_LINK)
len += ETHERIP_ALIGN;
#endif
M_PREPEND(m, len, M_DONTWAIT);
if (m != NULL && m->m_len < len)
m = m_pullup(m, len);
if (m == NULL) {
printf("ENOBUFS in in6_gif_output %d\n", __LINE__);
return ENOBUFS;
}
#ifndef __NO_STRICT_ALIGNMENT
if (family == AF_LINK) {
len = mtod(m, vm_offset_t) & 3;
KASSERT(len == 0 || len == ETHERIP_ALIGN,
("in6_gif_output: unexpected misalignment"));
m->m_data += len;
m->m_len -= ETHERIP_ALIGN;
}
#endif
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_flow = 0;
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
ip6->ip6_plen = htons((u_short)m->m_pkthdr.len);
ip6->ip6_nxt = proto;
ip6->ip6_hlim = V_ip6_gif_hlim;
ip6->ip6_src = sin6_src->sin6_addr;
/* bidirectional configured tunnel mode */
if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
ip6->ip6_dst = sin6_dst->sin6_addr;
else {
m_freem(m);
return ENETUNREACH;
}
ip_ecn_ingress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED : ECN_NOCARE,
&otos, &itos);
ip6->ip6_flow &= ~htonl(0xff << 20);
ip6->ip6_flow |= htonl((u_int32_t)otos << 20);
if (dst->sin6_family != sin6_dst->sin6_family ||
!IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &sin6_dst->sin6_addr)) {
/* cache route doesn't match */
bzero(dst, sizeof(*dst));
dst->sin6_family = sin6_dst->sin6_family;
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_addr = sin6_dst->sin6_addr;
if (sc->gif_ro6.ro_rt) {
RTFREE(sc->gif_ro6.ro_rt);
sc->gif_ro6.ro_rt = NULL;
}
#if 0
GIF2IFP(sc)->if_mtu = GIF_MTU;
#endif
}
if (sc->gif_ro6.ro_rt == NULL) {
rtalloc((struct route *)&sc->gif_ro6);
if (sc->gif_ro6.ro_rt == NULL) {
m_freem(m);
return ENETUNREACH;
}
/* if it constitutes infinite encapsulation, punt. */
if (sc->gif_ro.ro_rt->rt_ifp == ifp) {
m_freem(m);
return ENETUNREACH; /*XXX*/
}
#if 0
ifp->if_mtu = sc->gif_ro6.ro_rt->rt_ifp->if_mtu
- sizeof(struct ip6_hdr);
#endif
}
#ifdef IPV6_MINMTU
/*
* force fragmentation to minimum MTU, to avoid path MTU discovery.
* it is too painful to ask for resend of inner packet, to achieve
* path MTU discovery for encapsulated packets.
*/
error = ip6_output(m, 0, &sc->gif_ro6, IPV6_MINMTU, 0, NULL, NULL);
#else
error = ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL, NULL);
#endif
if (!(GIF2IFP(sc)->if_flags & IFF_LINK0) &&
sc->gif_ro6.ro_rt != NULL) {
RTFREE(sc->gif_ro6.ro_rt);
sc->gif_ro6.ro_rt = NULL;
}
return (error);
}
int
in6_gif_input(struct mbuf **mp, int *offp, int proto)
{
struct mbuf *m = *mp;
struct ifnet *gifp = NULL;
struct gif_softc *sc;
struct ip6_hdr *ip6;
int af = 0;
u_int32_t otos;
ip6 = mtod(m, struct ip6_hdr *);
sc = (struct gif_softc *)encap_getarg(m);
if (sc == NULL) {
m_freem(m);
V_ip6stat.ip6s_nogif++;
return IPPROTO_DONE;
}
gifp = GIF2IFP(sc);
if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
m_freem(m);
V_ip6stat.ip6s_nogif++;
return IPPROTO_DONE;
}
otos = ip6->ip6_flow;
m_adj(m, *offp);
switch (proto) {
#ifdef INET
case IPPROTO_IPV4:
{
struct ip *ip;
u_int8_t otos8;
af = AF_INET;
otos8 = (ntohl(otos) >> 20) & 0xff;
if (m->m_len < sizeof(*ip)) {
m = m_pullup(m, sizeof(*ip));
if (!m)
return IPPROTO_DONE;
}
ip = mtod(m, struct ip *);
if (ip_ecn_egress((gifp->if_flags & IFF_LINK1) ?
ECN_ALLOWED : ECN_NOCARE,
&otos8, &ip->ip_tos) == 0) {
m_freem(m);
return IPPROTO_DONE;
}
break;
}
#endif /* INET */
#ifdef INET6
case IPPROTO_IPV6:
{
struct ip6_hdr *ip6;
af = AF_INET6;
if (m->m_len < sizeof(*ip6)) {
m = m_pullup(m, sizeof(*ip6));
if (!m)
return IPPROTO_DONE;
}
ip6 = mtod(m, struct ip6_hdr *);
if (ip6_ecn_egress((gifp->if_flags & IFF_LINK1) ?
ECN_ALLOWED : ECN_NOCARE,
&otos, &ip6->ip6_flow) == 0) {
m_freem(m);
return IPPROTO_DONE;
}
break;
}
#endif
case IPPROTO_ETHERIP:
af = AF_LINK;
break;
default:
V_ip6stat.ip6s_nogif++;
m_freem(m);
return IPPROTO_DONE;
}
gif_input(m, af, gifp);
return IPPROTO_DONE;
}
/*
* validate outer address.
*/
static int
gif_validate6(const struct ip6_hdr *ip6, struct gif_softc *sc,
struct ifnet *ifp)
{
struct sockaddr_in6 *src, *dst;
src = (struct sockaddr_in6 *)sc->gif_psrc;
dst = (struct sockaddr_in6 *)sc->gif_pdst;
/*
* Check for address match. Note that the check is for an incoming
* packet. We should compare the *source* address in our configuration
* and the *destination* address of the packet, and vice versa.
*/
if (!IN6_ARE_ADDR_EQUAL(&src->sin6_addr, &ip6->ip6_dst) ||
!IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_src))
return 0;
/* martian filters on outer source - done in ip6_input */
/* ingress filters on outer source */
if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0 && ifp) {
struct sockaddr_in6 sin6;
struct rtentry *rt;
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_addr = ip6->ip6_src;
sin6.sin6_scope_id = 0; /* XXX */
rt = rtalloc1((struct sockaddr *)&sin6, 0, 0UL);
if (!rt || rt->rt_ifp != ifp) {
#if 0
char ip6buf[INET6_ADDRSTRLEN];
log(LOG_WARNING, "%s: packet from %s dropped "
"due to ingress filter\n", if_name(GIF2IFP(sc)),
ip6_sprintf(ip6buf, &sin6.sin6_addr));
#endif
if (rt)
RTFREE_LOCKED(rt);
return 0;
}
RTFREE_LOCKED(rt);
}
return 128 * 2;
}
/*
* we know that we are in IFF_UP, outer address available, and outer family
* matched the physical addr family. see gif_encapcheck().
* sanity check for arg should have been done in the caller.
*/
int
gif_encapcheck6(const struct mbuf *m, int off, int proto, void *arg)
{
struct ip6_hdr ip6;
struct gif_softc *sc;
struct ifnet *ifp;
/* sanity check done in caller */
sc = (struct gif_softc *)arg;
/* LINTED const cast */
m_copydata(m, 0, sizeof(ip6), (caddr_t)&ip6);
ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL;
return gif_validate6(&ip6, sc, ifp);
}
int
in6_gif_attach(struct gif_softc *sc)
{
sc->encap_cookie6 = encap_attach_func(AF_INET6, -1, gif_encapcheck,
(void *)&in6_gif_protosw, sc);
if (sc->encap_cookie6 == NULL)
return EEXIST;
return 0;
}
int
in6_gif_detach(struct gif_softc *sc)
{
int error;
error = encap_detach(sc->encap_cookie6);
if (error == 0)
sc->encap_cookie6 = NULL;
return error;
}

View File

@@ -0,0 +1,45 @@
/*-
* 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.
*
* $KAME: in6_gif.h,v 1.5 2000/04/14 08:36:03 itojun Exp $
* $FreeBSD$
*/
#ifndef _NETINET6_IN6_GIF_HH_
#define _NETINET6_IN6_GIF_HH_
#define GIF_HLIM 30
struct gif_softc;
int in6_gif_input __P((struct mbuf **, int *, int));
int in6_gif_output __P((struct ifnet *, int, struct mbuf *));
int gif_encapcheck6 __P((const struct mbuf *, int, int, void *));
int in6_gif_attach __P((struct gif_softc *));
int in6_gif_detach __P((struct gif_softc *));
#endif /* _NETINET6_IN6_GIF_HH_ */

View File

@@ -0,0 +1,971 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: in6_ifattach.c,v 1.118 2001/05/24 07:44:00 itojun Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/sockio.h>
#include <rtems/freebsd/sys/jail.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/proc.h>
#include <rtems/freebsd/sys/syslog.h>
#include <rtems/freebsd/sys/md5.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/if_dl.h>
#include <rtems/freebsd/net/if_types.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/net/vnet.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/if_ether.h>
#include <rtems/freebsd/netinet/in_pcb.h>
#include <rtems/freebsd/netinet/ip_var.h>
#include <rtems/freebsd/netinet/udp.h>
#include <rtems/freebsd/netinet/udp_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/in6_var.h>
#include <rtems/freebsd/netinet6/in6_pcb.h>
#include <rtems/freebsd/netinet6/in6_ifattach.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/nd6.h>
#include <rtems/freebsd/netinet6/mld6_var.h>
#include <rtems/freebsd/netinet6/scope6_var.h>
VNET_DEFINE(unsigned long, in6_maxmtu) = 0;
#ifdef IP6_AUTO_LINKLOCAL
VNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL;
#else
VNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */
#endif
VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch);
#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
#define V_ripcbinfo VNET(ripcbinfo)
static int get_rand_ifid(struct ifnet *, struct in6_addr *);
static int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
static int in6_ifattach_loopback(struct ifnet *);
static void in6_purgemaddrs(struct ifnet *);
#define EUI64_GBIT 0x01
#define EUI64_UBIT 0x02
#define EUI64_TO_IFID(in6) do {(in6)->s6_addr[8] ^= EUI64_UBIT; } while (0)
#define EUI64_GROUP(in6) ((in6)->s6_addr[8] & EUI64_GBIT)
#define EUI64_INDIVIDUAL(in6) (!EUI64_GROUP(in6))
#define EUI64_LOCAL(in6) ((in6)->s6_addr[8] & EUI64_UBIT)
#define EUI64_UNIVERSAL(in6) (!EUI64_LOCAL(in6))
#define IFID_LOCAL(in6) (!EUI64_LOCAL(in6))
#define IFID_UNIVERSAL(in6) (!EUI64_UNIVERSAL(in6))
/*
* Generate a last-resort interface identifier, when the machine has no
* IEEE802/EUI64 address sources.
* The goal here is to get an interface identifier that is
* (1) random enough and (2) does not change across reboot.
* We currently use MD5(hostname) for it.
*
* in6 - upper 64bits are preserved
*/
static int
get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
{
MD5_CTX ctxt;
struct prison *pr;
u_int8_t digest[16];
int hostnamelen;
pr = curthread->td_ucred->cr_prison;
mtx_lock(&pr->pr_mtx);
hostnamelen = strlen(pr->pr_hostname);
#if 0
/* we need at least several letters as seed for ifid */
if (hostnamelen < 3) {
mtx_unlock(&pr->pr_mtx);
return -1;
}
#endif
/* generate 8 bytes of pseudo-random value. */
bzero(&ctxt, sizeof(ctxt));
MD5Init(&ctxt);
MD5Update(&ctxt, pr->pr_hostname, hostnamelen);
mtx_unlock(&pr->pr_mtx);
MD5Final(digest, &ctxt);
/* assumes sizeof(digest) > sizeof(ifid) */
bcopy(digest, &in6->s6_addr[8], 8);
/* make sure to set "u" bit to local, and "g" bit to individual. */
in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
/* convert EUI64 into IPv6 interface identifier */
EUI64_TO_IFID(in6);
return 0;
}
static int
generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
{
MD5_CTX ctxt;
u_int8_t seed[16], digest[16], nullbuf[8];
u_int32_t val32;
/* If there's no history, start with a random seed. */
bzero(nullbuf, sizeof(nullbuf));
if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
int i;
for (i = 0; i < 2; i++) {
val32 = arc4random();
bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
}
} else
bcopy(seed0, seed, 8);
/* copy the right-most 64-bits of the given address */
/* XXX assumption on the size of IFID */
bcopy(seed1, &seed[8], 8);
if (0) { /* for debugging purposes only */
int i;
printf("generate_tmp_ifid: new randomized ID from: ");
for (i = 0; i < 16; i++)
printf("%02x", seed[i]);
printf(" ");
}
/* generate 16 bytes of pseudo-random value. */
bzero(&ctxt, sizeof(ctxt));
MD5Init(&ctxt);
MD5Update(&ctxt, seed, sizeof(seed));
MD5Final(digest, &ctxt);
/*
* RFC 3041 3.2.1. (3)
* Take the left-most 64-bits of the MD5 digest and set bit 6 (the
* left-most bit is numbered 0) to zero.
*/
bcopy(digest, ret, 8);
ret[0] &= ~EUI64_UBIT;
/*
* XXX: we'd like to ensure that the generated value is not zero
* for simplicity. If the caclculated digest happens to be zero,
* use a random non-zero value as the last resort.
*/
if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
nd6log((LOG_INFO,
"generate_tmp_ifid: computed MD5 value is zero.\n"));
val32 = arc4random();
val32 = 1 + (val32 % (0xffffffff - 1));
}
/*
* RFC 3041 3.2.1. (4)
* Take the rightmost 64-bits of the MD5 digest and save them in
* stable storage as the history value to be used in the next
* iteration of the algorithm.
*/
bcopy(&digest[8], seed0, 8);
if (0) { /* for debugging purposes only */
int i;
printf("to: ");
for (i = 0; i < 16; i++)
printf("%02x", digest[i]);
printf("\n");
}
return 0;
}
/*
* Get interface identifier for the specified interface.
* XXX assumes single sockaddr_dl (AF_LINK address) per an interface
*
* in6 - upper 64bits are preserved
*/
int
in6_get_hw_ifid(struct ifnet *ifp, struct in6_addr *in6)
{
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
u_int8_t *addr;
size_t addrlen;
static u_int8_t allzero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static u_int8_t allone[8] =
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
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;
goto found;
}
IF_ADDR_UNLOCK(ifp);
return -1;
found:
IF_ADDR_LOCK_ASSERT(ifp);
addr = LLADDR(sdl);
addrlen = sdl->sdl_alen;
/* get EUI64 */
switch (ifp->if_type) {
case IFT_ETHER:
case IFT_FDDI:
case IFT_ISO88025:
case IFT_ATM:
case IFT_IEEE1394:
#ifdef IFT_IEEE80211
case IFT_IEEE80211:
#endif
/* IEEE802/EUI64 cases - what others? */
/* IEEE1394 uses 16byte length address starting with EUI64 */
if (addrlen > 8)
addrlen = 8;
/* look at IEEE802/EUI64 only */
if (addrlen != 8 && addrlen != 6) {
IF_ADDR_UNLOCK(ifp);
return -1;
}
/*
* check for invalid MAC address - on bsdi, we see it a lot
* since wildboar configures all-zero MAC on pccard before
* card insertion.
*/
if (bcmp(addr, allzero, addrlen) == 0) {
IF_ADDR_UNLOCK(ifp);
return -1;
}
if (bcmp(addr, allone, addrlen) == 0) {
IF_ADDR_UNLOCK(ifp);
return -1;
}
/* make EUI64 address */
if (addrlen == 8)
bcopy(addr, &in6->s6_addr[8], 8);
else if (addrlen == 6) {
in6->s6_addr[8] = addr[0];
in6->s6_addr[9] = addr[1];
in6->s6_addr[10] = addr[2];
in6->s6_addr[11] = 0xff;
in6->s6_addr[12] = 0xfe;
in6->s6_addr[13] = addr[3];
in6->s6_addr[14] = addr[4];
in6->s6_addr[15] = addr[5];
}
break;
case IFT_ARCNET:
if (addrlen != 1) {
IF_ADDR_UNLOCK(ifp);
return -1;
}
if (!addr[0]) {
IF_ADDR_UNLOCK(ifp);
return -1;
}
bzero(&in6->s6_addr[8], 8);
in6->s6_addr[15] = addr[0];
/*
* due to insufficient bitwidth, we mark it local.
*/
in6->s6_addr[8] &= ~EUI64_GBIT; /* g bit to "individual" */
in6->s6_addr[8] |= EUI64_UBIT; /* u bit to "local" */
break;
case IFT_GIF:
#ifdef IFT_STF
case IFT_STF:
#endif
/*
* RFC2893 says: "SHOULD use IPv4 address as ifid source".
* however, IPv4 address is not very suitable as unique
* identifier source (can be renumbered).
* we don't do this.
*/
IF_ADDR_UNLOCK(ifp);
return -1;
default:
IF_ADDR_UNLOCK(ifp);
return -1;
}
/* sanity check: g bit must not indicate "group" */
if (EUI64_GROUP(in6)) {
IF_ADDR_UNLOCK(ifp);
return -1;
}
/* convert EUI64 into IPv6 interface identifier */
EUI64_TO_IFID(in6);
/*
* sanity check: ifid must not be all zero, avoid conflict with
* subnet router anycast
*/
if ((in6->s6_addr[8] & ~(EUI64_GBIT | EUI64_UBIT)) == 0x00 &&
bcmp(&in6->s6_addr[9], allzero, 7) == 0) {
IF_ADDR_UNLOCK(ifp);
return -1;
}
IF_ADDR_UNLOCK(ifp);
return 0;
}
/*
* Get interface identifier for the specified interface. If it is not
* available on ifp0, borrow interface identifier from other information
* sources.
*
* altifp - secondary EUI64 source
*/
static int
get_ifid(struct ifnet *ifp0, struct ifnet *altifp,
struct in6_addr *in6)
{
struct ifnet *ifp;
/* first, try to get it from the interface itself */
if (in6_get_hw_ifid(ifp0, in6) == 0) {
nd6log((LOG_DEBUG, "%s: got interface identifier from itself\n",
if_name(ifp0)));
goto success;
}
/* try secondary EUI64 source. this basically is for ATM PVC */
if (altifp && in6_get_hw_ifid(altifp, in6) == 0) {
nd6log((LOG_DEBUG, "%s: got interface identifier from %s\n",
if_name(ifp0), if_name(altifp)));
goto success;
}
/* next, try to get it from some other hardware interface */
IFNET_RLOCK_NOSLEEP();
for (ifp = V_ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) {
if (ifp == ifp0)
continue;
if (in6_get_hw_ifid(ifp, in6) != 0)
continue;
/*
* to borrow ifid from other interface, ifid needs to be
* globally unique
*/
if (IFID_UNIVERSAL(in6)) {
nd6log((LOG_DEBUG,
"%s: borrow interface identifier from %s\n",
if_name(ifp0), if_name(ifp)));
IFNET_RUNLOCK_NOSLEEP();
goto success;
}
}
IFNET_RUNLOCK_NOSLEEP();
/* last resort: get from random number source */
if (get_rand_ifid(ifp, in6) == 0) {
nd6log((LOG_DEBUG,
"%s: interface identifier generated by random number\n",
if_name(ifp0)));
goto success;
}
printf("%s: failed to get interface identifier\n", if_name(ifp0));
return -1;
success:
nd6log((LOG_INFO, "%s: ifid: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
if_name(ifp0), in6->s6_addr[8], in6->s6_addr[9], in6->s6_addr[10],
in6->s6_addr[11], in6->s6_addr[12], in6->s6_addr[13],
in6->s6_addr[14], in6->s6_addr[15]));
return 0;
}
/*
* altifp - secondary EUI64 source
*/
static int
in6_ifattach_linklocal(struct ifnet *ifp, struct ifnet *altifp)
{
struct in6_ifaddr *ia;
struct in6_aliasreq ifra;
struct nd_prefixctl pr0;
int i, error;
/*
* configure link-local address.
*/
bzero(&ifra, sizeof(ifra));
/*
* in6_update_ifa() does not use ifra_name, but we accurately set it
* for safety.
*/
strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
ifra.ifra_addr.sin6_family = AF_INET6;
ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
ifra.ifra_addr.sin6_addr.s6_addr32[0] = htonl(0xfe800000);
ifra.ifra_addr.sin6_addr.s6_addr32[1] = 0;
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
ifra.ifra_addr.sin6_addr.s6_addr32[2] = 0;
ifra.ifra_addr.sin6_addr.s6_addr32[3] = htonl(1);
} else {
if (get_ifid(ifp, altifp, &ifra.ifra_addr.sin6_addr) != 0) {
nd6log((LOG_ERR,
"%s: no ifid available\n", if_name(ifp)));
return (-1);
}
}
if (in6_setscope(&ifra.ifra_addr.sin6_addr, ifp, NULL))
return (-1);
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
ifra.ifra_prefixmask.sin6_family = AF_INET6;
ifra.ifra_prefixmask.sin6_addr = in6mask64;
/* link-local addresses should NEVER expire. */
ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
/*
* Now call in6_update_ifa() to do a bunch of procedures to configure
* a link-local address. We can set the 3rd argument to NULL, because
* we know there's no other link-local address on the interface
* and therefore we are adding one (instead of updating one).
*/
if ((error = in6_update_ifa(ifp, &ifra, NULL,
IN6_IFAUPDATE_DADDELAY)) != 0) {
/*
* XXX: When the interface does not support IPv6, this call
* would fail in the SIOCSIFADDR ioctl. I believe the
* notification is rather confusing in this case, so just
* suppress it. (jinmei@kame.net 20010130)
*/
if (error != EAFNOSUPPORT)
nd6log((LOG_NOTICE, "in6_ifattach_linklocal: failed to "
"configure a link-local address on %s "
"(errno=%d)\n",
if_name(ifp), error));
return (-1);
}
ia = in6ifa_ifpforlinklocal(ifp, 0); /* ia must not be NULL */
#ifdef DIAGNOSTIC
if (!ia) {
panic("ia == NULL in in6_ifattach_linklocal");
/* NOTREACHED */
}
#endif
ifa_free(&ia->ia_ifa);
/*
* Make the link-local prefix (fe80::%link/64) as on-link.
* Since we'd like to manage prefixes separately from addresses,
* we make an ND6 prefix structure for the link-local prefix,
* and add it to the prefix list as a never-expire prefix.
* XXX: this change might affect some existing code base...
*/
bzero(&pr0, sizeof(pr0));
pr0.ndpr_ifp = ifp;
/* this should be 64 at this moment. */
pr0.ndpr_plen = in6_mask2len(&ifra.ifra_prefixmask.sin6_addr, NULL);
pr0.ndpr_prefix = ifra.ifra_addr;
/* apply the mask for safety. (nd6_prelist_add will apply it again) */
for (i = 0; i < 4; i++) {
pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
in6mask64.s6_addr32[i];
}
/*
* Initialize parameters. The link-local prefix must always be
* on-link, and its lifetimes never expire.
*/
pr0.ndpr_raf_onlink = 1;
pr0.ndpr_raf_auto = 1; /* probably meaningless */
pr0.ndpr_vltime = ND6_INFINITE_LIFETIME;
pr0.ndpr_pltime = ND6_INFINITE_LIFETIME;
/*
* Since there is no other link-local addresses, nd6_prefix_lookup()
* probably returns NULL. However, we cannot always expect the result.
* For example, if we first remove the (only) existing link-local
* address, and then reconfigure another one, the prefix is still
* valid with referring to the old link-local address.
*/
if (nd6_prefix_lookup(&pr0) == NULL) {
if ((error = nd6_prelist_add(&pr0, NULL, NULL)) != 0)
return (error);
}
return 0;
}
/*
* ifp - must be IFT_LOOP
*/
static int
in6_ifattach_loopback(struct ifnet *ifp)
{
struct in6_aliasreq ifra;
int error;
bzero(&ifra, sizeof(ifra));
/*
* in6_update_ifa() does not use ifra_name, but we accurately set it
* for safety.
*/
strncpy(ifra.ifra_name, if_name(ifp), sizeof(ifra.ifra_name));
ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
ifra.ifra_prefixmask.sin6_family = AF_INET6;
ifra.ifra_prefixmask.sin6_addr = in6mask128;
/*
* Always initialize ia_dstaddr (= broadcast address) to loopback
* address. Follows IPv4 practice - see in_ifinit().
*/
ifra.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
ifra.ifra_dstaddr.sin6_family = AF_INET6;
ifra.ifra_dstaddr.sin6_addr = in6addr_loopback;
ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
ifra.ifra_addr.sin6_family = AF_INET6;
ifra.ifra_addr.sin6_addr = in6addr_loopback;
/* the loopback address should NEVER expire. */
ifra.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
ifra.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
/* we don't need to perform DAD on loopback interfaces. */
ifra.ifra_flags |= IN6_IFF_NODAD;
/* skip registration to the prefix list. XXX should be temporary. */
ifra.ifra_flags |= IN6_IFF_NOPFX;
/*
* We are sure that this is a newly assigned address, so we can set
* NULL to the 3rd arg.
*/
if ((error = in6_update_ifa(ifp, &ifra, NULL, 0)) != 0) {
nd6log((LOG_ERR, "in6_ifattach_loopback: failed to configure "
"the loopback address on %s (errno=%d)\n",
if_name(ifp), error));
return (-1);
}
return 0;
}
/*
* compute NI group address, based on the current hostname setting.
* see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later).
*
* when ifp == NULL, the caller is responsible for filling scopeid.
*/
int
in6_nigroup(struct ifnet *ifp, const char *name, int namelen,
struct in6_addr *in6)
{
struct prison *pr;
const char *p;
u_char *q;
MD5_CTX ctxt;
u_int8_t digest[16];
char l;
char n[64]; /* a single label must not exceed 63 chars */
/*
* If no name is given and namelen is -1,
* we try to do the hostname lookup ourselves.
*/
if (!name && namelen == -1) {
pr = curthread->td_ucred->cr_prison;
mtx_lock(&pr->pr_mtx);
name = pr->pr_hostname;
namelen = strlen(name);
} else
pr = NULL;
if (!name || !namelen) {
if (pr != NULL)
mtx_unlock(&pr->pr_mtx);
return -1;
}
p = name;
while (p && *p && *p != '.' && p - name < namelen)
p++;
if (p == name || p - name > sizeof(n) - 1) {
if (pr != NULL)
mtx_unlock(&pr->pr_mtx);
return -1; /* label too long */
}
l = p - name;
strncpy(n, name, l);
if (pr != NULL)
mtx_unlock(&pr->pr_mtx);
n[(int)l] = '\0';
for (q = n; *q; q++) {
if ('A' <= *q && *q <= 'Z')
*q = *q - 'A' + 'a';
}
/* generate 8 bytes of pseudo-random value. */
bzero(&ctxt, sizeof(ctxt));
MD5Init(&ctxt);
MD5Update(&ctxt, &l, sizeof(l));
MD5Update(&ctxt, n, l);
MD5Final(digest, &ctxt);
bzero(in6, sizeof(*in6));
in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL;
in6->s6_addr8[11] = 2;
bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3]));
if (in6_setscope(in6, ifp, NULL))
return (-1); /* XXX: should not fail */
return 0;
}
/*
* XXX multiple loopback interface needs more care. for instance,
* nodelocal address needs to be configured onto only one of them.
* XXX multiple link-local address case
*
* altifp - secondary EUI64 source
*/
void
in6_ifattach(struct ifnet *ifp, struct ifnet *altifp)
{
struct in6_ifaddr *ia;
struct in6_addr in6;
/* some of the interfaces are inherently not IPv6 capable */
switch (ifp->if_type) {
case IFT_PFLOG:
case IFT_PFSYNC:
case IFT_CARP:
return;
}
/*
* quirks based on interface type
*/
switch (ifp->if_type) {
#ifdef IFT_STF
case IFT_STF:
/*
* 6to4 interface is a very special kind of beast.
* no multicast, no linklocal. RFC2529 specifies how to make
* linklocals for 6to4 interface, but there's no use and
* it is rather harmful to have one.
*/
goto statinit;
#endif
default:
break;
}
/*
* usually, we require multicast capability to the interface
*/
if ((ifp->if_flags & IFF_MULTICAST) == 0) {
nd6log((LOG_INFO, "in6_ifattach: "
"%s is not multicast capable, IPv6 not enabled\n",
if_name(ifp)));
return;
}
/*
* assign loopback address for loopback interface.
* XXX multiple loopback interface case.
*/
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
struct ifaddr *ifa;
in6 = in6addr_loopback;
ifa = (struct ifaddr *)in6ifa_ifpwithaddr(ifp, &in6);
if (ifa == NULL) {
if (in6_ifattach_loopback(ifp) != 0)
return;
} else
ifa_free(ifa);
}
/*
* assign a link-local address, if there's none.
*/
if (V_ip6_auto_linklocal && ifp->if_type != IFT_BRIDGE) {
ia = in6ifa_ifpforlinklocal(ifp, 0);
if (ia == NULL) {
if (in6_ifattach_linklocal(ifp, altifp) == 0) {
/* linklocal address assigned */
} else {
/* failed to assign linklocal address. bark? */
}
} else
ifa_free(&ia->ia_ifa);
}
#ifdef IFT_STF /* XXX */
statinit:
#endif
/* update dynamically. */
if (V_in6_maxmtu < ifp->if_mtu)
V_in6_maxmtu = ifp->if_mtu;
}
/*
* NOTE: in6_ifdetach() does not support loopback if at this moment.
* We don't need this function in bsdi, because interfaces are never removed
* from the ifnet list in bsdi.
*/
void
in6_ifdetach(struct ifnet *ifp)
{
struct in6_ifaddr *ia;
struct ifaddr *ifa, *next;
struct radix_node_head *rnh;
struct rtentry *rt;
short rtflags;
struct sockaddr_in6 sin6;
struct in6_multi_mship *imm;
/* remove neighbor management table */
nd6_purge(ifp);
/* nuke any of IPv6 addresses we have */
TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, next) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
in6_purgeaddr(ifa);
}
/* undo everything done by in6_ifattach(), just in case */
TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrhead, ifa_link, 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;
/*
* leave from multicast groups we have joined for the interface
*/
while ((imm = ia->ia6_memberships.lh_first) != NULL) {
LIST_REMOVE(imm, i6mm_chain);
in6_leavegroup(imm);
}
/* 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_LOCKED(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 */
IF_ADDR_LOCK(ifp);
TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);
IF_ADDR_UNLOCK(ifp);
ifa_free(ifa); /* if_addrhead */
IN6_IFADDR_WLOCK();
TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link);
IN6_IFADDR_WUNLOCK();
ifa_free(ifa);
}
in6_pcbpurgeif0(&V_udbinfo, ifp);
in6_pcbpurgeif0(&V_ripcbinfo, ifp);
/* leave from all multicast groups joined */
in6_purgemaddrs(ifp);
/*
* remove neighbor management table. we call it twice just to make
* sure we nuke everything. maybe we need just one call.
* XXX: since the first call did not release addresses, some prefixes
* might remain. We should call nd6_purge() again to release the
* prefixes after removing all addresses above.
* (Or can we just delay calling nd6_purge until at this point?)
*/
nd6_purge(ifp);
/* remove route to link-local allnodes multicast (ff02::1) */
bzero(&sin6, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = in6addr_linklocal_allnodes;
if (in6_setscope(&sin6.sin6_addr, ifp, NULL))
/* XXX: should not fail */
return;
/* XXX grab lock first to avoid LOR */
rnh = rt_tables_get_rnh(0, AF_INET6);
if (rnh != NULL) {
RADIX_NODE_HEAD_LOCK(rnh);
rt = rtalloc1((struct sockaddr *)&sin6, 0, RTF_RNH_LOCKED);
if (rt) {
if (rt->rt_ifp == ifp)
rtexpunge(rt);
RTFREE_LOCKED(rt);
}
RADIX_NODE_HEAD_UNLOCK(rnh);
}
}
int
in6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
const u_int8_t *baseid, int generate)
{
u_int8_t nullbuf[8];
struct nd_ifinfo *ndi = ND_IFINFO(ifp);
bzero(nullbuf, sizeof(nullbuf));
if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
/* we've never created a random ID. Create a new one. */
generate = 1;
}
if (generate) {
bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
/* generate_tmp_ifid will update seedn and buf */
(void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
ndi->randomid);
}
bcopy(ndi->randomid, retbuf, 8);
return (0);
}
void
in6_tmpaddrtimer(void *arg)
{
CURVNET_SET((struct vnet *) arg);
struct nd_ifinfo *ndi;
u_int8_t nullbuf[8];
struct ifnet *ifp;
callout_reset(&V_in6_tmpaddrtimer_ch,
(V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet);
bzero(nullbuf, sizeof(nullbuf));
for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
ifp = TAILQ_NEXT(ifp, if_list)) {
ndi = ND_IFINFO(ifp);
if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
/*
* We've been generating a random ID on this interface.
* Create a new one.
*/
(void)generate_tmp_ifid(ndi->randomseed0,
ndi->randomseed1, ndi->randomid);
}
}
CURVNET_RESTORE();
}
static void
in6_purgemaddrs(struct ifnet *ifp)
{
LIST_HEAD(,in6_multi) purgeinms;
struct in6_multi *inm, *tinm;
struct ifmultiaddr *ifma;
LIST_INIT(&purgeinms);
IN6_MULTI_LOCK();
/*
* Extract list of in6_multi associated with the detaching ifp
* which the PF_INET6 layer is about to release.
* We need to do this as IF_ADDR_LOCK() may be re-acquired
* by code further down.
*/
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_INET6 ||
ifma->ifma_protospec == NULL)
continue;
inm = (struct in6_multi *)ifma->ifma_protospec;
LIST_INSERT_HEAD(&purgeinms, inm, in6m_entry);
}
IF_ADDR_UNLOCK(ifp);
LIST_FOREACH_SAFE(inm, &purgeinms, in6m_entry, tinm) {
LIST_REMOVE(inm, in6m_entry);
in6m_release_locked(inm);
}
mld_ifdetach(ifp);
IN6_MULTI_UNLOCK();
}

View File

@@ -0,0 +1,45 @@
/*-
* 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.
*
* $KAME: in6_ifattach.h,v 1.14 2001/02/08 12:48:39 jinmei Exp $
* $FreeBSD$
*/
#ifndef _NETINET6_IN6_IFATTACH_HH_
#define _NETINET6_IN6_IFATTACH_HH_
#ifdef _KERNEL
void in6_ifattach __P((struct ifnet *, struct ifnet *));
void in6_ifdetach __P((struct ifnet *));
int in6_get_tmpifid __P((struct ifnet *, u_int8_t *, const u_int8_t *, int));
void in6_tmpaddrtimer __P((void *));
int in6_get_hw_ifid __P((struct ifnet *, struct in6_addr *));
int in6_nigroup __P((struct ifnet *, const char *, int, struct in6_addr *));
#endif /* _KERNEL */
#endif /* _NETINET6_IN6_IFATTACH_HH_ */

2840
freebsd/netinet6/in6_mcast.c Normal file

File diff suppressed because it is too large Load Diff

936
freebsd/netinet6/in6_pcb.c Normal file
View File

@@ -0,0 +1,936 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $
*/
/*-
* Copyright (c) 1982, 1986, 1991, 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.
* 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.c 8.2 (Berkeley) 1/4/94
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_inet.h>
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/local/opt_ipsec.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/domain.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/socketvar.h>
#include <rtems/freebsd/sys/sockio.h>
#include <rtems/freebsd/sys/errno.h>
#include <rtems/freebsd/sys/time.h>
#include <rtems/freebsd/sys/priv.h>
#include <rtems/freebsd/sys/proc.h>
#include <rtems/freebsd/sys/jail.h>
#include <rtems/freebsd/vm/uma.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/if_types.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/in_systm.h>
#include <rtems/freebsd/netinet/tcp_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet/ip_var.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/nd6.h>
#include <rtems/freebsd/netinet/in_pcb.h>
#include <rtems/freebsd/netinet6/in6_pcb.h>
#include <rtems/freebsd/netinet6/scope6_var.h>
#include <rtems/freebsd/security/mac/mac_framework.h>
struct in6_addr zeroin6_addr;
int
in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
struct ucred *cred)
{
struct socket *so = inp->inp_socket;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
u_short lport = 0;
int error, wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
if (TAILQ_EMPTY(&V_in6_ifaddrhead)) /* XXX broken! */
return (EADDRNOTAVAIL);
if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
return (EINVAL);
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
wild = INPLOOKUP_WILDCARD;
if (nam == NULL) {
if ((error = prison_local_ip6(cred, &inp->in6p_laddr,
((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
return (error);
} else {
sin6 = (struct sockaddr_in6 *)nam;
if (nam->sa_len != sizeof(*sin6))
return (EINVAL);
/*
* family check.
*/
if (nam->sa_family != AF_INET6)
return (EAFNOSUPPORT);
if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0)
return(error);
if ((error = prison_local_ip6(cred, &sin6->sin6_addr,
((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
return (error);
lport = sin6->sin6_port;
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
/*
* Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
* allow compepte duplication of binding if
* SO_REUSEPORT is set, or if SO_REUSEADDR is set
* and a multicast address is bound on both
* new and duplicated sockets.
*/
if (so->so_options & SO_REUSEADDR)
reuseport = SO_REUSEADDR|SO_REUSEPORT;
} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
struct ifaddr *ifa;
sin6->sin6_port = 0; /* yech... */
if ((ifa = ifa_ifwithaddr((struct sockaddr *)sin6)) ==
NULL &&
(inp->inp_flags & INP_BINDANY) == 0) {
return (EADDRNOTAVAIL);
}
/*
* XXX: bind to an anycast address might accidentally
* cause sending a packet with anycast source address.
* We should allow to bind to a deprecated address, since
* the application dares to use it.
*/
if (ifa != NULL &&
((struct in6_ifaddr *)ifa)->ia6_flags &
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
ifa_free(ifa);
return (EADDRNOTAVAIL);
}
if (ifa != NULL)
ifa_free(ifa);
}
if (lport) {
struct inpcb *t;
/* GROSS */
if (ntohs(lport) <= V_ipport_reservedhigh &&
ntohs(lport) >= V_ipport_reservedlow &&
priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT,
0))
return (EACCES);
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
priv_check_cred(inp->inp_cred,
PRIV_NETINET_REUSEPORT, 0) != 0) {
t = in6_pcblookup_local(pcbinfo,
&sin6->sin6_addr, lport,
INPLOOKUP_WILDCARD, cred);
if (t &&
((t->inp_flags & INP_TIMEWAIT) == 0) &&
(so->so_type != SOCK_STREAM ||
IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
!IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
(t->inp_socket->so_options & SO_REUSEPORT)
== 0) && (inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
struct sockaddr_in sin;
in6_sin6_2_sin(&sin, sin6);
t = in_pcblookup_local(pcbinfo,
sin.sin_addr, lport,
INPLOOKUP_WILDCARD, cred);
if (t &&
((t->inp_flags &
INP_TIMEWAIT) == 0) &&
(so->so_type != SOCK_STREAM ||
ntohl(t->inp_faddr.s_addr) ==
INADDR_ANY) &&
(inp->inp_cred->cr_uid !=
t->inp_cred->cr_uid))
return (EADDRINUSE);
}
}
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
lport, wild, cred);
if (t && (reuseport & ((t->inp_flags & INP_TIMEWAIT) ?
intotw(t)->tw_so_options :
t->inp_socket->so_options)) == 0)
return (EADDRINUSE);
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
struct sockaddr_in sin;
in6_sin6_2_sin(&sin, sin6);
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
lport, wild, cred);
if (t && t->inp_flags & INP_TIMEWAIT) {
if ((reuseport &
intotw(t)->tw_so_options) == 0 &&
(ntohl(t->inp_laddr.s_addr) !=
INADDR_ANY || ((inp->inp_vflag &
INP_IPV6PROTO) ==
(t->inp_vflag & INP_IPV6PROTO))))
return (EADDRINUSE);
}
else if (t &&
(reuseport & t->inp_socket->so_options)
== 0 && (ntohl(t->inp_laddr.s_addr) !=
INADDR_ANY || INP_SOCKAF(so) ==
INP_SOCKAF(t->inp_socket)))
return (EADDRINUSE);
}
}
inp->in6p_laddr = sin6->sin6_addr;
}
if (lport == 0) {
if ((error = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0)
return (error);
} else {
inp->inp_lport = lport;
if (in_pcbinshash(inp) != 0) {
inp->in6p_laddr = in6addr_any;
inp->inp_lport = 0;
return (EAGAIN);
}
}
return (0);
}
/*
* Transform old in6_pcbconnect() into an inner subroutine for new
* in6_pcbconnect(): Do some validity-checking on the remote
* address (in mbuf 'nam') and then determine local host address
* (i.e., which interface) to use to access that remote host.
*
* This preserves definition of in6_pcbconnect(), while supporting a
* slightly different version for T/TCP. (This is more than
* a bit of a kludge, but cleaning up the internal interfaces would
* have forced minor changes in every protocol).
*/
int
in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
struct in6_addr *plocal_addr6)
{
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
int error = 0;
struct ifnet *ifp = NULL;
int scope_ambiguous = 0;
struct in6_addr in6a;
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
if (nam->sa_len != sizeof (*sin6))
return (EINVAL);
if (sin6->sin6_family != AF_INET6)
return (EAFNOSUPPORT);
if (sin6->sin6_port == 0)
return (EADDRNOTAVAIL);
if (sin6->sin6_scope_id == 0 && !V_ip6_use_defzone)
scope_ambiguous = 1;
if ((error = sa6_embedscope(sin6, V_ip6_use_defzone)) != 0)
return(error);
if (!TAILQ_EMPTY(&V_in6_ifaddrhead)) {
/*
* If the destination address is UNSPECIFIED addr,
* use the loopback addr, e.g ::1.
*/
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
sin6->sin6_addr = in6addr_loopback;
}
if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
return (error);
error = in6_selectsrc(sin6, inp->in6p_outputopts,
inp, NULL, inp->inp_cred, &ifp, &in6a);
if (error)
return (error);
if (ifp && scope_ambiguous &&
(error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {
return(error);
}
/*
* Do not update this earlier, in case we return with an error.
*
* XXX: this in6_selectsrc result might replace the bound local
* address with the address specified by setsockopt(IPV6_PKTINFO).
* Is it the intended behavior?
*/
*plocal_addr6 = in6a;
/*
* Don't do pcblookup call here; return interface in
* plocal_addr6
* and exit to caller, that will do the lookup.
*/
return (0);
}
/*
* Outer subroutine:
* Connect from a socket to a specified address.
* Both address and port must be specified in argument sin.
* If don't have a local address for this socket yet,
* then pick one.
*/
int
in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
struct ucred *cred)
{
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
struct in6_addr addr6;
int error;
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
/*
* Call inner routine, to assign local interface address.
* in6_pcbladdr() may automatically fill in sin6_scope_id.
*/
if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
return (error);
if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
sin6->sin6_port,
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
? &addr6 : &inp->in6p_laddr,
inp->inp_lport, 0, NULL) != NULL) {
return (EADDRINUSE);
}
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
if (inp->inp_lport == 0) {
error = in6_pcbbind(inp, (struct sockaddr *)0, cred);
if (error)
return (error);
}
inp->in6p_laddr = addr6;
}
inp->in6p_faddr = sin6->sin6_addr;
inp->inp_fport = sin6->sin6_port;
/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
if (inp->inp_flags & IN6P_AUTOFLOWLABEL)
inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
in_pcbrehash(inp);
return (0);
}
void
in6_pcbdisconnect(struct inpcb *inp)
{
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
inp->inp_fport = 0;
/* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
in_pcbrehash(inp);
}
struct sockaddr *
in6_sockaddr(in_port_t port, struct in6_addr *addr_p)
{
struct sockaddr_in6 *sin6;
sin6 = malloc(sizeof *sin6, M_SONAME, M_WAITOK);
bzero(sin6, sizeof *sin6);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_port = port;
sin6->sin6_addr = *addr_p;
(void)sa6_recoverscope(sin6); /* XXX: should catch errors */
return (struct sockaddr *)sin6;
}
struct sockaddr *
in6_v4mapsin6_sockaddr(in_port_t port, struct in_addr *addr_p)
{
struct sockaddr_in sin;
struct sockaddr_in6 *sin6_p;
bzero(&sin, sizeof sin);
sin.sin_family = AF_INET;
sin.sin_len = sizeof(sin);
sin.sin_port = port;
sin.sin_addr = *addr_p;
sin6_p = malloc(sizeof *sin6_p, M_SONAME,
M_WAITOK);
in6_sin_2_v4mapsin6(&sin, sin6_p);
return (struct sockaddr *)sin6_p;
}
int
in6_getsockaddr(struct socket *so, struct sockaddr **nam)
{
register struct inpcb *inp;
struct in6_addr addr;
in_port_t port;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("in6_getsockaddr: inp == NULL"));
INP_RLOCK(inp);
port = inp->inp_lport;
addr = inp->in6p_laddr;
INP_RUNLOCK(inp);
*nam = in6_sockaddr(port, &addr);
return 0;
}
int
in6_getpeeraddr(struct socket *so, struct sockaddr **nam)
{
struct inpcb *inp;
struct in6_addr addr;
in_port_t port;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("in6_getpeeraddr: inp == NULL"));
INP_RLOCK(inp);
port = inp->inp_fport;
addr = inp->in6p_faddr;
INP_RUNLOCK(inp);
*nam = in6_sockaddr(port, &addr);
return 0;
}
int
in6_mapped_sockaddr(struct socket *so, struct sockaddr **nam)
{
struct inpcb *inp;
int error;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("in6_mapped_sockaddr: inp == NULL"));
if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) {
error = in_getsockaddr(so, nam);
if (error == 0)
in6_sin_2_v4mapsin6_in_sock(nam);
} else {
/* scope issues will be handled in in6_getsockaddr(). */
error = in6_getsockaddr(so, nam);
}
return error;
}
int
in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
{
struct inpcb *inp;
int error;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("in6_mapped_peeraddr: inp == NULL"));
if ((inp->inp_vflag & (INP_IPV4 | INP_IPV6)) == INP_IPV4) {
error = in_getpeeraddr(so, nam);
if (error == 0)
in6_sin_2_v4mapsin6_in_sock(nam);
} else
/* scope issues will be handled in in6_getpeeraddr(). */
error = in6_getpeeraddr(so, nam);
return error;
}
/*
* Pass some notification to all connections of a protocol
* associated with address dst. The local address and/or port numbers
* may be specified to limit the search. The "usual action" will be
* taken, depending on the ctlinput cmd. The caller must filter any
* cmds that are uninteresting (e.g., no error in the map).
* Call the protocol specific routine (if any) to report
* any errors for each matching socket.
*/
void
in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
u_int fport_arg, const struct sockaddr *src, u_int lport_arg,
int cmd, void *cmdarg,
struct inpcb *(*notify)(struct inpcb *, int))
{
struct inpcb *inp, *inp_temp;
struct sockaddr_in6 sa6_src, *sa6_dst;
u_short fport = fport_arg, lport = lport_arg;
u_int32_t flowinfo;
int errno;
if ((unsigned)cmd >= PRC_NCMDS || dst->sa_family != AF_INET6)
return;
sa6_dst = (struct sockaddr_in6 *)dst;
if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr))
return;
/*
* note that src can be NULL when we get notify by local fragmentation.
*/
sa6_src = (src == NULL) ? sa6_any : *(const struct sockaddr_in6 *)src;
flowinfo = sa6_src.sin6_flowinfo;
/*
* Redirects go to all references to the destination,
* and use in6_rtchange to invalidate the route cache.
* Dead host indications: also use in6_rtchange to invalidate
* the cache, and deliver the error to all the sockets.
* Otherwise, if we have knowledge of the local port and address,
* deliver only to that socket.
*/
if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
fport = 0;
lport = 0;
bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr));
if (cmd != PRC_HOSTDEAD)
notify = in6_rtchange;
}
errno = inet6ctlerrmap[cmd];
INP_INFO_WLOCK(pcbinfo);
LIST_FOREACH_SAFE(inp, pcbinfo->ipi_listhead, inp_list, inp_temp) {
INP_WLOCK(inp);
if ((inp->inp_vflag & INP_IPV6) == 0) {
INP_WUNLOCK(inp);
continue;
}
/*
* If the error designates a new path MTU for a destination
* and the application (associated with this socket) wanted to
* know the value, notify. Note that we notify for all
* disconnected sockets if the corresponding application
* wanted. This is because some UDP applications keep sending
* sockets disconnected.
* XXX: should we avoid to notify the value to TCP sockets?
*/
if (cmd == PRC_MSGSIZE && (inp->inp_flags & IN6P_MTU) != 0 &&
(IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &sa6_dst->sin6_addr))) {
ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst,
(u_int32_t *)cmdarg);
}
/*
* Detect if we should notify the error. If no source and
* destination ports are specifed, but non-zero flowinfo and
* local address match, notify the error. This is the case
* when the error is delivered with an encrypted buffer
* by ESP. Otherwise, just compare addresses and ports
* as usual.
*/
if (lport == 0 && fport == 0 && flowinfo &&
inp->inp_socket != NULL &&
flowinfo == (inp->inp_flow & IPV6_FLOWLABEL_MASK) &&
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
goto do_notify;
else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
&sa6_dst->sin6_addr) ||
inp->inp_socket == 0 ||
(lport && inp->inp_lport != lport) ||
(!IN6_IS_ADDR_UNSPECIFIED(&sa6_src.sin6_addr) &&
!IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr,
&sa6_src.sin6_addr)) ||
(fport && inp->inp_fport != fport)) {
INP_WUNLOCK(inp);
continue;
}
do_notify:
if (notify) {
if ((*notify)(inp, errno))
INP_WUNLOCK(inp);
} else
INP_WUNLOCK(inp);
}
INP_INFO_WUNLOCK(pcbinfo);
}
/*
* Lookup a PCB based on the local address and port.
*/
struct inpcb *
in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
u_short lport, int wild_okay, struct ucred *cred)
{
register struct inpcb *inp;
int matchwild = 3, wildcard;
INP_INFO_WLOCK_ASSERT(pcbinfo);
if (!wild_okay) {
struct inpcbhead *head;
/*
* Look for an unconnected (wildcard foreign addr) PCB that
* matches the local address and port we're looking for.
*/
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
0, pcbinfo->ipi_hashmask)];
LIST_FOREACH(inp, head, inp_hash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
inp->inp_lport == lport) {
/* Found. */
if (cred == NULL ||
prison_equal_ip6(cred->cr_prison,
inp->inp_cred->cr_prison))
return (inp);
}
}
/*
* Not found.
*/
return (NULL);
} else {
struct inpcbporthead *porthash;
struct inpcbport *phd;
struct inpcb *match = NULL;
/*
* Best fit PCB lookup.
*
* First see if this local port is in use by looking on the
* port hash list.
*/
porthash = &pcbinfo->ipi_porthashbase[INP_PCBPORTHASH(lport,
pcbinfo->ipi_porthashmask)];
LIST_FOREACH(phd, porthash, phd_hash) {
if (phd->phd_port == lport)
break;
}
if (phd != NULL) {
/*
* Port is in use by one or more PCBs. Look for best
* fit.
*/
LIST_FOREACH(inp, &phd->phd_pcblist, inp_portlist) {
wildcard = 0;
if (cred != NULL &&
!prison_equal_ip6(cred->cr_prison,
inp->inp_cred->cr_prison))
continue;
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
wildcard++;
if (!IN6_IS_ADDR_UNSPECIFIED(
&inp->in6p_laddr)) {
if (IN6_IS_ADDR_UNSPECIFIED(laddr))
wildcard++;
else if (!IN6_ARE_ADDR_EQUAL(
&inp->in6p_laddr, laddr))
continue;
} else {
if (!IN6_IS_ADDR_UNSPECIFIED(laddr))
wildcard++;
}
if (wildcard < matchwild) {
match = inp;
matchwild = wildcard;
if (matchwild == 0)
break;
}
}
}
return (match);
}
}
void
in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
{
struct inpcb *in6p;
struct ip6_moptions *im6o;
int i, gap;
INP_INFO_RLOCK(pcbinfo);
LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
INP_WLOCK(in6p);
im6o = in6p->in6p_moptions;
if ((in6p->inp_vflag & INP_IPV6) && im6o != NULL) {
/*
* Unselect the outgoing ifp for multicast if it
* is being detached.
*/
if (im6o->im6o_multicast_ifp == ifp)
im6o->im6o_multicast_ifp = NULL;
/*
* Drop multicast group membership if we joined
* through the interface being detached.
*/
gap = 0;
for (i = 0; i < im6o->im6o_num_memberships; i++) {
if (im6o->im6o_membership[i]->in6m_ifp ==
ifp) {
in6_mc_leave(im6o->im6o_membership[i],
NULL);
gap++;
} else if (gap != 0) {
im6o->im6o_membership[i - gap] =
im6o->im6o_membership[i];
}
}
im6o->im6o_num_memberships -= gap;
}
INP_WUNLOCK(in6p);
}
INP_INFO_RUNLOCK(pcbinfo);
}
/*
* Check for alternatives when higher level complains
* about service problems. For now, invalidate cached
* routing information. If the route was created dynamically
* (by a redirect), time to try a default gateway again.
*/
void
in6_losing(struct inpcb *in6p)
{
/*
* We don't store route pointers in the routing table anymore
*/
return;
}
/*
* After a routing change, flush old routing
* and allocate a (hopefully) better one.
*/
struct inpcb *
in6_rtchange(struct inpcb *inp, int errno)
{
/*
* We don't store route pointers in the routing table anymore
*/
return inp;
}
/*
* Lookup PCB in hash list.
*/
struct inpcb *
in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, int wildcard,
struct ifnet *ifp)
{
struct inpcbhead *head;
struct inpcb *inp, *tmpinp;
u_short fport = fport_arg, lport = lport_arg;
int faith;
INP_INFO_LOCK_ASSERT(pcbinfo);
if (faithprefix_p != NULL)
faith = (*faithprefix_p)(laddr);
else
faith = 0;
/*
* First look for an exact match.
*/
tmpinp = NULL;
head = &pcbinfo->ipi_hashbase[
INP_PCBHASH(faddr->s6_addr32[3] /* XXX */, lport, fport,
pcbinfo->ipi_hashmask)];
LIST_FOREACH(inp, head, inp_hash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
if (IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, faddr) &&
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
inp->inp_fport == fport &&
inp->inp_lport == lport) {
/*
* XXX We should be able to directly return
* the inp here, without any checks.
* Well unless both bound with SO_REUSEPORT?
*/
if (prison_flag(inp->inp_cred, PR_IP6))
return (inp);
if (tmpinp == NULL)
tmpinp = inp;
}
}
if (tmpinp != NULL)
return (tmpinp);
/*
* Then look for a wildcard match, if requested.
*/
if (wildcard == INPLOOKUP_WILDCARD) {
struct inpcb *local_wild = NULL, *local_exact = NULL;
struct inpcb *jail_wild = NULL;
int injail;
/*
* Order of socket selection - we always prefer jails.
* 1. jailed, non-wild.
* 2. jailed, wild.
* 3. non-jailed, non-wild.
* 4. non-jailed, wild.
*/
head = &pcbinfo->ipi_hashbase[INP_PCBHASH(INADDR_ANY, lport,
0, pcbinfo->ipi_hashmask)];
LIST_FOREACH(inp, head, inp_hash) {
/* XXX inp locking */
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
inp->inp_lport != lport) {
continue;
}
/* XXX inp locking */
if (faith && (inp->inp_flags & INP_FAITH) == 0)
continue;
injail = prison_flag(inp->inp_cred, PR_IP6);
if (injail) {
if (prison_check_ip6(inp->inp_cred,
laddr) != 0)
continue;
} else {
if (local_exact != NULL)
continue;
}
if (IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr)) {
if (injail)
return (inp);
else
local_exact = inp;
} else if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
if (injail)
jail_wild = inp;
else
local_wild = inp;
}
} /* LIST_FOREACH */
if (jail_wild != NULL)
return (jail_wild);
if (local_exact != NULL)
return (local_exact);
if (local_wild != NULL)
return (local_wild);
} /* if (wildcard == INPLOOKUP_WILDCARD) */
/*
* Not found.
*/
return (NULL);
}
void
init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
{
struct ip6_hdr *ip;
ip = mtod(m, struct ip6_hdr *);
bzero(sin6, sizeof(*sin6));
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_family = AF_INET6;
sin6->sin6_addr = ip->ip6_src;
(void)sa6_recoverscope(sin6); /* XXX: should catch errors... */
return;
}

109
freebsd/netinet6/in6_pcb.h Normal file
View File

@@ -0,0 +1,109 @@
/*-
* 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.
*
* $KAME: in6_pcb.h,v 1.13 2001/02/06 09:16:53 itojun Exp $
*/
/*-
* 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.
* 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
* $FreeBSD$
*/
#ifndef _NETINET6_IN6_PCB_HH_
#define _NETINET6_IN6_PCB_HH_
#ifdef _KERNEL
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
void in6_pcbpurgeif0 __P((struct inpcbinfo *, struct ifnet *));
void in6_losing __P((struct inpcb *));
int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct ucred *));
int in6_pcbconnect __P((struct inpcb *, struct sockaddr *, struct ucred *));
void in6_pcbdisconnect __P((struct inpcb *));
int in6_pcbladdr(struct inpcb *, struct sockaddr *, struct in6_addr *);
struct inpcb *
in6_pcblookup_local __P((struct inpcbinfo *,
struct in6_addr *, u_short, int,
struct ucred *));
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 inpcbinfo *, struct sockaddr *,
u_int, const struct sockaddr *, u_int, int, void *,
struct inpcb *(*)(struct inpcb *, int)));
#ifndef __rtems__
struct inpcb *
in6_rtchange __P((struct inpcb *, int));
#else
struct inpcb *
in6_rtchange(struct inpcb *inp, int errno);
#endif
struct sockaddr *
in6_sockaddr __P((in_port_t port, struct in6_addr *addr_p));
struct sockaddr *
in6_v4mapsin6_sockaddr __P((in_port_t port, struct in_addr *addr_p));
int in6_getpeeraddr __P((struct socket *so, struct sockaddr **nam));
int in6_getsockaddr __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));
int in6_selecthlim __P((struct in6pcb *, struct ifnet *));
int in6_pcbsetport __P((struct in6_addr *, struct inpcb *, struct ucred *));
void init_sin6 __P((struct sockaddr_in6 *sin6, struct mbuf *m));
#endif /* _KERNEL */
#endif /* !_NETINET6_IN6_PCB_HH_ */

View File

@@ -0,0 +1,597 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: in6_proto.c,v 1.91 2001/05/27 13:28:35 itojun 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.
* 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 <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_inet.h>
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/local/opt_ipsec.h>
#include <rtems/freebsd/local/opt_ipstealth.h>
#include <rtems/freebsd/local/opt_sctp.h>
#include <rtems/freebsd/local/opt_mpath.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/socketvar.h>
#include <rtems/freebsd/sys/proc.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/jail.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/domain.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/sysctl.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/radix.h>
#include <rtems/freebsd/net/route.h>
#ifdef RADIX_MPATH
#include <rtems/freebsd/net/radix_mpath.h>
#endif
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_systm.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/ip_encap.h>
#include <rtems/freebsd/netinet/ip.h>
#include <rtems/freebsd/netinet/ip_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet/icmp6.h>
#include <rtems/freebsd/netinet/tcp.h>
#include <rtems/freebsd/netinet/tcp_timer.h>
#include <rtems/freebsd/netinet/tcp_var.h>
#include <rtems/freebsd/netinet/udp.h>
#include <rtems/freebsd/netinet/udp_var.h>
#include <rtems/freebsd/netinet6/tcp6_var.h>
#include <rtems/freebsd/netinet6/raw_ip6.h>
#include <rtems/freebsd/netinet6/udp6_var.h>
#include <rtems/freebsd/netinet6/pim6_var.h>
#include <rtems/freebsd/netinet6/nd6.h>
#ifdef SCTP
#include <rtems/freebsd/netinet/in_pcb.h>
#include <rtems/freebsd/netinet/sctp_pcb.h>
#include <rtems/freebsd/netinet/sctp.h>
#include <rtems/freebsd/netinet/sctp_var.h>
#include <rtems/freebsd/netinet6/sctp6_var.h>
#endif /* SCTP */
#ifdef IPSEC
#include <rtems/freebsd/netipsec/ipsec.h>
#include <rtems/freebsd/netipsec/ipsec6.h>
#endif /* IPSEC */
#include <rtems/freebsd/netinet6/ip6protosw.h>
/*
* TCP/IP protocol family: IP6, ICMP6, UDP, TCP.
*/
extern struct domain inet6domain;
static struct pr_usrreqs nousrreqs;
#define PR_LISTEN 0
#define PR_ABRTACPTDIS 0
/* Spacer for loadable protocols. */
#define IP6PROTOSPACER \
{ \
.pr_domain = &inet6domain, \
.pr_protocol = PROTO_SPACER, \
.pr_usrreqs = &nousrreqs \
}
struct ip6protosw inet6sw[] = {
{
.pr_type = 0,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_IPV6,
.pr_init = ip6_init,
#ifdef VIMAGE
.pr_destroy = ip6_destroy,
#endif
.pr_slowtimo = frag6_slowtimo,
.pr_drain = frag6_drain,
.pr_usrreqs = &nousrreqs,
},
{
.pr_type = SOCK_DGRAM,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_UDP,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = udp6_input,
.pr_ctlinput = udp6_ctlinput,
.pr_ctloutput = ip6_ctloutput,
.pr_usrreqs = &udp6_usrreqs,
},
{
.pr_type = SOCK_STREAM,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_TCP,
.pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN,
.pr_input = tcp6_input,
.pr_ctlinput = tcp6_ctlinput,
.pr_ctloutput = tcp_ctloutput,
#ifndef INET /* don't call initialization and timeout routines twice */
.pr_init = tcp_init,
.pr_slowtimo = tcp_slowtimo,
#endif
.pr_drain = tcp_drain,
.pr_usrreqs = &tcp6_usrreqs,
},
#ifdef SCTP
{
.pr_type = SOCK_DGRAM,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_SCTP,
.pr_flags = PR_WANTRCVD,
.pr_input = sctp6_input,
.pr_ctlinput = sctp6_ctlinput,
.pr_ctloutput = sctp_ctloutput,
.pr_drain = sctp_drain,
.pr_usrreqs = &sctp6_usrreqs
},
{
.pr_type = SOCK_SEQPACKET,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_SCTP,
.pr_flags = PR_WANTRCVD,
.pr_input = sctp6_input,
.pr_ctlinput = sctp6_ctlinput,
.pr_ctloutput = sctp_ctloutput,
.pr_drain = sctp_drain,
.pr_usrreqs = &sctp6_usrreqs
},
{
.pr_type = SOCK_STREAM,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_SCTP,
.pr_flags = PR_WANTRCVD,
.pr_input = sctp6_input,
.pr_ctlinput = sctp6_ctlinput,
.pr_ctloutput = sctp_ctloutput,
.pr_drain = sctp_drain,
.pr_usrreqs = &sctp6_usrreqs
},
#endif /* SCTP */
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_RAW,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = rip6_input,
.pr_output = rip6_output,
.pr_ctlinput = rip6_ctlinput,
.pr_ctloutput = rip6_ctloutput,
.pr_usrreqs = &rip6_usrreqs
},
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_ICMPV6,
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
.pr_input = icmp6_input,
.pr_output = rip6_output,
.pr_ctlinput = rip6_ctlinput,
.pr_ctloutput = rip6_ctloutput,
.pr_fasttimo = icmp6_fasttimo,
.pr_slowtimo = icmp6_slowtimo,
.pr_usrreqs = &rip6_usrreqs
},
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_DSTOPTS,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = dest6_input,
.pr_usrreqs = &nousrreqs
},
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_ROUTING,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = route6_input,
.pr_usrreqs = &nousrreqs
},
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_FRAGMENT,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = frag6_input,
.pr_usrreqs = &nousrreqs
},
#ifdef IPSEC
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_AH,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = ipsec6_common_input,
.pr_usrreqs = &nousrreqs,
},
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_ESP,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = ipsec6_common_input,
.pr_ctlinput = esp6_ctlinput,
.pr_usrreqs = &nousrreqs,
},
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_IPCOMP,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = ipsec6_common_input,
.pr_usrreqs = &nousrreqs,
},
#endif /* IPSEC */
#ifdef INET
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_IPV4,
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
.pr_input = encap6_input,
.pr_output = rip6_output,
.pr_ctloutput = rip6_ctloutput,
.pr_init = encap_init,
.pr_usrreqs = &rip6_usrreqs
},
#endif /* INET */
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_IPV6,
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
.pr_input = encap6_input,
.pr_output = rip6_output,
.pr_ctloutput = rip6_ctloutput,
.pr_init = encap_init,
.pr_usrreqs = &rip6_usrreqs
},
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_PIM,
.pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR,
.pr_input = encap6_input,
.pr_output = rip6_output,
.pr_ctloutput = rip6_ctloutput,
.pr_usrreqs = &rip6_usrreqs
},
/* Spacer n-times for loadable protocols. */
IP6PROTOSPACER,
IP6PROTOSPACER,
IP6PROTOSPACER,
IP6PROTOSPACER,
IP6PROTOSPACER,
IP6PROTOSPACER,
IP6PROTOSPACER,
IP6PROTOSPACER,
/* raw wildcard */
{
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_flags = PR_ATOMIC|PR_ADDR,
.pr_input = rip6_input,
.pr_output = rip6_output,
.pr_ctloutput = rip6_ctloutput,
.pr_usrreqs = &rip6_usrreqs
},
};
extern int in6_inithead(void **, int);
#ifdef VIMAGE
extern int in6_detachhead(void **, int);
#endif
struct domain inet6domain = {
.dom_family = AF_INET6,
.dom_name = "internet6",
.dom_protosw = (struct protosw *)inet6sw,
.dom_protoswNPROTOSW = (struct protosw *)
&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])],
#ifdef RADIX_MPATH
.dom_rtattach = rn6_mpath_inithead,
#else
.dom_rtattach = in6_inithead,
#endif
#ifdef VIMAGE
.dom_rtdetach = in6_detachhead,
#endif
.dom_rtoffset = offsetof(struct sockaddr_in6, sin6_addr) << 3,
.dom_maxrtkey = sizeof(struct sockaddr_in6),
.dom_ifattach = in6_domifattach,
.dom_ifdetach = in6_domifdetach
};
VNET_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
VNET_DEFINE(int, ip6_forwarding) = IPV6FORWARDING; /* act as router? */
VNET_DEFINE(int, ip6_sendredirects) = IPV6_SENDREDIRECTS;
VNET_DEFINE(int, ip6_defhlim) = IPV6_DEFHLIM;
VNET_DEFINE(int, ip6_defmcasthlim) = IPV6_DEFAULT_MULTICAST_HOPS;
VNET_DEFINE(int, ip6_accept_rtadv) = 0;
VNET_DEFINE(int, ip6_maxfragpackets); /* initialized in frag6.c:frag6_init() */
VNET_DEFINE(int, ip6_maxfrags); /* initialized in frag6.c:frag6_init() */
VNET_DEFINE(int, ip6_log_interval) = 5;
VNET_DEFINE(int, ip6_hdrnestlimit) = 15;/* How many header options will we
* process? */
VNET_DEFINE(int, ip6_dad_count) = 1; /* DupAddrDetectionTransmits */
VNET_DEFINE(int, ip6_auto_flowlabel) = 1;
VNET_DEFINE(int, ip6_use_deprecated) = 1;/* allow deprecated addr
* (RFC2462 5.5.4) */
VNET_DEFINE(int, ip6_rr_prune) = 5; /* router renumbering prefix
* walk list every 5 sec. */
VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */
VNET_DEFINE(int, ip6_v6only) = 1;
VNET_DEFINE(int, ip6_keepfaith) = 0;
VNET_DEFINE(time_t, ip6_log_time) = (time_t)0L;
#ifdef IPSTEALTH
VNET_DEFINE(int, ip6stealth) = 0;
#endif
VNET_DEFINE(int, nd6_onlink_ns_rfc4861) = 0;/* allow 'on-link' nd6 NS
* (RFC 4861) */
/* 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)
*/
VNET_DEFINE(int, pmtu_expire) = 60*10;
VNET_DEFINE(int, pmtu_probe) = 60*2;
/* raw IP6 parameters */
/*
* Nominal space allocated to a raw ip socket.
*/
#define RIPV6SNDQ 8192
#define RIPV6RCVQ 8192
VNET_DEFINE(u_long, rip6_sendspace) = RIPV6SNDQ;
VNET_DEFINE(u_long, rip6_recvspace) = RIPV6RCVQ;
/* ICMPV6 parameters */
VNET_DEFINE(int, icmp6_rediraccept) = 1;/* accept and process redirects */
VNET_DEFINE(int, icmp6_redirtimeout) = 10 * 60; /* 10 minutes */
VNET_DEFINE(int, icmp6errppslim) = 100; /* 100pps */
/* control how to respond to NI queries */
VNET_DEFINE(int, icmp6_nodeinfo) =
(ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK);
/* UDP on IP6 parameters */
VNET_DEFINE(int, udp6_sendspace) = 9216;/* really max datagram size */
VNET_DEFINE(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 SCTP
SYSCTL_NODE(_net_inet6, IPPROTO_SCTP, sctp6, CTLFLAG_RW, 0, "SCTP6");
#endif
#ifdef IPSEC
SYSCTL_NODE(_net_inet6, IPPROTO_ESP, ipsec6, CTLFLAG_RW, 0, "IPSEC6");
#endif /* IPSEC */
/* net.inet6.ip6 */
static int
sysctl_ip6_temppltime(SYSCTL_HANDLER_ARGS)
{
int error = 0;
int old;
VNET_SYSCTL_ARG(req, arg1);
error = SYSCTL_OUT(req, arg1, sizeof(int));
if (error || !req->newptr)
return (error);
old = V_ip6_temp_preferred_lifetime;
error = SYSCTL_IN(req, arg1, sizeof(int));
if (V_ip6_temp_preferred_lifetime <
V_ip6_desync_factor + V_ip6_temp_regen_advance) {
V_ip6_temp_preferred_lifetime = old;
return (EINVAL);
}
return (error);
}
static int
sysctl_ip6_tempvltime(SYSCTL_HANDLER_ARGS)
{
int error = 0;
int old;
VNET_SYSCTL_ARG(req, arg1);
error = SYSCTL_OUT(req, arg1, sizeof(int));
if (error || !req->newptr)
return (error);
old = V_ip6_temp_valid_lifetime;
error = SYSCTL_IN(req, arg1, sizeof(int));
if (V_ip6_temp_valid_lifetime < V_ip6_temp_preferred_lifetime) {
V_ip6_temp_preferred_lifetime = old;
return (EINVAL);
}
return (error);
}
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_FORWARDING, forwarding, CTLFLAG_RW,
&VNET_NAME(ip6_forwarding), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_SENDREDIRECTS, redirect, CTLFLAG_RW,
&VNET_NAME(ip6_sendredirects), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DEFHLIM, hlim, CTLFLAG_RW,
&VNET_NAME(ip6_defhlim), 0, "");
SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6CTL_STATS, stats, CTLFLAG_RD,
&VNET_NAME(ip6stat), ip6stat, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS, maxfragpackets,
CTLFLAG_RW, &VNET_NAME(ip6_maxfragpackets), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_ACCEPT_RTADV, accept_rtadv,
CTLFLAG_RW, &VNET_NAME(ip6_accept_rtadv), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
&VNET_NAME(ip6_keepfaith), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL, log_interval,
CTLFLAG_RW, &VNET_NAME(ip6_log_interval), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_HDRNESTLIMIT, hdrnestlimit,
CTLFLAG_RW, &VNET_NAME(ip6_hdrnestlimit), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DAD_COUNT, dad_count, CTLFLAG_RW,
&VNET_NAME(ip6_dad_count), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_AUTO_FLOWLABEL, auto_flowlabel,
CTLFLAG_RW, &VNET_NAME(ip6_auto_flowlabel), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_DEFMCASTHLIM, defmcasthlim,
CTLFLAG_RW, &VNET_NAME(ip6_defmcasthlim), 0, "");
SYSCTL_STRING(_net_inet6_ip6, IPV6CTL_KAME_VERSION, kame_version,
CTLFLAG_RD, __KAME_VERSION, 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_USE_DEPRECATED, use_deprecated,
CTLFLAG_RW, &VNET_NAME(ip6_use_deprecated), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE, rr_prune, CTLFLAG_RW,
&VNET_NAME(ip6_rr_prune), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_USETEMPADDR, use_tempaddr,
CTLFLAG_RW, &VNET_NAME(ip6_use_tempaddr), 0, "");
SYSCTL_VNET_PROC(_net_inet6_ip6, IPV6CTL_TEMPPLTIME, temppltime,
CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(ip6_temp_preferred_lifetime), 0,
sysctl_ip6_temppltime, "I", "");
SYSCTL_VNET_PROC(_net_inet6_ip6, IPV6CTL_TEMPVLTIME, tempvltime,
CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(ip6_temp_valid_lifetime), 0,
sysctl_ip6_tempvltime, "I", "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_V6ONLY, v6only, CTLFLAG_RW,
&VNET_NAME(ip6_v6only), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_AUTO_LINKLOCAL, auto_linklocal,
CTLFLAG_RW, &VNET_NAME(ip6_auto_linklocal), 0, "");
SYSCTL_VNET_STRUCT(_net_inet6_ip6, IPV6CTL_RIP6STATS, rip6stats, CTLFLAG_RD,
&VNET_NAME(rip6stat), rip6stat, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_PREFER_TEMPADDR, prefer_tempaddr,
CTLFLAG_RW, &VNET_NAME(ip6_prefer_tempaddr), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_USE_DEFAULTZONE, use_defaultzone,
CTLFLAG_RW, &VNET_NAME(ip6_use_defzone), 0,"");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGS, maxfrags, CTLFLAG_RW,
&VNET_NAME(ip6_maxfrags), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_MCAST_PMTU, mcast_pmtu, CTLFLAG_RW,
&VNET_NAME(ip6_mcast_pmtu), 0, "");
#ifdef IPSTEALTH
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_STEALTH, stealth, CTLFLAG_RW,
&VNET_NAME(ip6stealth), 0, "");
#endif
/* net.inet6.icmp6 */
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRACCEPT, rediraccept,
CTLFLAG_RW, &VNET_NAME(icmp6_rediraccept), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT, redirtimeout,
CTLFLAG_RW, &VNET_NAME(icmp6_redirtimeout), 0, "");
SYSCTL_VNET_STRUCT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats, CTLFLAG_RD,
&VNET_NAME(icmp6stat), icmp6stat, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PRUNE, nd6_prune, CTLFLAG_RW,
&VNET_NAME(nd6_prune), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DELAY, nd6_delay, CTLFLAG_RW,
&VNET_NAME(nd6_delay), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_UMAXTRIES, nd6_umaxtries,
CTLFLAG_RW, &VNET_NAME(nd6_umaxtries), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MMAXTRIES, nd6_mmaxtries,
CTLFLAG_RW, &VNET_NAME(nd6_mmaxtries), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_USELOOPBACK, nd6_useloopback,
CTLFLAG_RW, &VNET_NAME(nd6_useloopback), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_NODEINFO, nodeinfo, CTLFLAG_RW,
&VNET_NAME(icmp6_nodeinfo), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ERRPPSLIMIT, errppslimit,
CTLFLAG_RW, &VNET_NAME(icmp6errppslim), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXNUDHINT, nd6_maxnudhint,
CTLFLAG_RW, &VNET_NAME(nd6_maxnudhint), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DEBUG, nd6_debug, CTLFLAG_RW,
&VNET_NAME(nd6_debug), 0, "");
SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_ONLINKNSRFC4861,
nd6_onlink_ns_rfc4861, CTLFLAG_RW, &VNET_NAME(nd6_onlink_ns_rfc4861),
0, "Accept 'on-link' nd6 NS in compliance with RFC 4861.");

449
freebsd/netinet6/in6_rmx.c Normal file
View File

@@ -0,0 +1,449 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: in6_rmx.c,v 1.11 2001/07/26 06:53:16 jinmei Exp $
*/
/*-
* 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.
*
*/
/*
* 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 <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/lock.h>
#include <rtems/freebsd/sys/sysctl.h>
#include <rtems/freebsd/sys/queue.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/socketvar.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/rwlock.h>
#include <rtems/freebsd/sys/syslog.h>
#include <rtems/freebsd/sys/callout.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/ip_var.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet/icmp6.h>
#include <rtems/freebsd/netinet6/nd6.h>
#include <rtems/freebsd/netinet/tcp.h>
#include <rtems/freebsd/netinet/tcp_seq.h>
#include <rtems/freebsd/netinet/tcp_timer.h>
#include <rtems/freebsd/netinet/tcp_var.h>
extern int in6_inithead(void **head, int off);
#ifdef VIMAGE
extern int in6_detachhead(void **head, int off);
#endif
#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;
RADIX_NODE_HEAD_WLOCK_ASSERT(head);
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
rt->rt_flags |= RTF_MULTICAST;
/*
* 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;
}
}
if (!rt->rt_rmx.rmx_mtu && rt->rt_ifp)
rt->rt_rmx.rmx_mtu = IN6_LINKMTU(rt->rt_ifp);
ret = rn_addroute(v_arg, n_arg, head, treenodes);
if (ret == NULL) {
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_RNH_LOCKED);
if (rt2) {
if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0)
&& rt2->rt_gateway
&& rt2->rt_gateway->sa_family == AF_LINK
&& rt2->rt_ifp == rt->rt_ifp) {
ret = rt2->rt_nodes;
}
RTFREE_LOCKED(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_LOCK(rt);
if (rt->rt_flags & RTPRF_OURS) {
rt->rt_flags &= ~RTPRF_OURS;
rt->rt_rmx.rmx_expire = 0;
}
RT_UNLOCK(rt);
}
return rn;
}
SYSCTL_DECL(_net_inet6_ip6);
static VNET_DEFINE(int, rtq_reallyold6) = 60*60;
/* one hour is ``really old'' */
#define V_rtq_reallyold6 VNET(rtq_reallyold6)
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTEXPIRE, rtexpire, CTLFLAG_RW,
&VNET_NAME(rtq_reallyold6) , 0, "");
static VNET_DEFINE(int, rtq_minreallyold6) = 10;
/* never automatically crank down to less */
#define V_rtq_minreallyold6 VNET(rtq_minreallyold6)
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW,
&VNET_NAME(rtq_minreallyold6) , 0, "");
static VNET_DEFINE(int, rtq_toomany6) = 128;
/* 128 cached routes is ``too many'' */
#define V_rtq_toomany6 VNET(rtq_toomany6)
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW,
&VNET_NAME(rtq_toomany6) , 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_reallyold6.
*/
static int
in6_rtqkill(struct radix_node *rn, void *rock)
{
struct rtqk_arg *ap = rock;
struct rtentry *rt = (struct rtentry *)rn;
int err;
RADIX_NODE_HEAD_WLOCK_ASSERT(ap->rnh);
if (rt->rt_flags & RTPRF_OURS) {
ap->found++;
if (ap->draining || rt->rt_rmx.rmx_expire <= time_uptime) {
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|RTF_RNH_LOCKED, 0);
if (err) {
log(LOG_WARNING, "in6_rtqkill: error %d", err);
} else {
ap->killed++;
}
} else {
if (ap->updating
&& (rt->rt_rmx.rmx_expire - time_uptime
> V_rtq_reallyold6)) {
rt->rt_rmx.rmx_expire = time_uptime
+ V_rtq_reallyold6;
}
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 VNET_DEFINE(int, rtq_timeout6) = RTQ_TIMEOUT;
static VNET_DEFINE(struct callout, rtq_timer6);
#define V_rtq_timeout6 VNET(rtq_timeout6)
#define V_rtq_timer6 VNET(rtq_timer6)
static void
in6_rtqtimo(void *rock)
{
CURVNET_SET_QUIET((struct vnet *) rock);
struct radix_node_head *rnh;
struct rtqk_arg arg;
struct timeval atv;
static time_t last_adjusted_timeout = 0;
rnh = rt_tables_get_rnh(0, AF_INET6);
if (rnh == NULL) {
CURVNET_RESTORE();
return;
}
arg.found = arg.killed = 0;
arg.rnh = rnh;
arg.nextstop = time_uptime + V_rtq_timeout6;
arg.draining = arg.updating = 0;
RADIX_NODE_HEAD_LOCK(rnh);
rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
RADIX_NODE_HEAD_UNLOCK(rnh);
/*
* 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_timeout6 seconds, to keep from cranking down too
* hard.
*/
if ((arg.found - arg.killed > V_rtq_toomany6)
&& (time_uptime - last_adjusted_timeout >= V_rtq_timeout6)
&& V_rtq_reallyold6 > V_rtq_minreallyold6) {
V_rtq_reallyold6 = 2*V_rtq_reallyold6 / 3;
if (V_rtq_reallyold6 < V_rtq_minreallyold6) {
V_rtq_reallyold6 = V_rtq_minreallyold6;
}
last_adjusted_timeout = time_uptime;
#ifdef DIAGNOSTIC
log(LOG_DEBUG, "in6_rtqtimo: adjusted rtq_reallyold6 to %d",
V_rtq_reallyold6);
#endif
arg.found = arg.killed = 0;
arg.updating = 1;
RADIX_NODE_HEAD_LOCK(rnh);
rnh->rnh_walktree(rnh, in6_rtqkill, &arg);
RADIX_NODE_HEAD_UNLOCK(rnh);
}
atv.tv_usec = 0;
atv.tv_sec = arg.nextstop - time_uptime;
callout_reset(&V_rtq_timer6, tvtohz(&atv), in6_rtqtimo, rock);
CURVNET_RESTORE();
}
/*
* Age old PMTUs.
*/
struct mtuex_arg {
struct radix_node_head *rnh;
time_t nextstop;
};
static VNET_DEFINE(struct callout, rtq_mtutimer);
#define V_rtq_mtutimer VNET(rtq_mtutimer)
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_uptime) {
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)
{
CURVNET_SET_QUIET((struct vnet *) rock);
struct radix_node_head *rnh;
struct mtuex_arg arg;
struct timeval atv;
rnh = rt_tables_get_rnh(0, AF_INET6);
if (rnh == NULL) {
CURVNET_RESTORE();
return;
}
arg.rnh = rnh;
arg.nextstop = time_uptime + MTUTIMO_DEFAULT;
RADIX_NODE_HEAD_LOCK(rnh);
rnh->rnh_walktree(rnh, in6_mtuexpire, &arg);
RADIX_NODE_HEAD_UNLOCK(rnh);
atv.tv_usec = 0;
atv.tv_sec = arg.nextstop - time_uptime;
if (atv.tv_sec < 0) {
printf("invalid mtu expiration time on routing table\n");
arg.nextstop = time_uptime + 30; /* last resort */
atv.tv_sec = 30;
}
callout_reset(&V_rtq_mtutimer, tvtohz(&atv), in6_mtutimo, rock);
CURVNET_RESTORE();
}
/*
* Initialize our routing tree.
* XXX MRT When off == 0, we are being called from vfs_export.c
* so just set up their table and leave. (we know what the correct
* value should be so just use that).. FIX AFTER RELENG_7 is MFC'd
* see also comments in in_inithead() vfs_export.c and domain.h
*/
int
in6_inithead(void **head, int off)
{
struct radix_node_head *rnh;
if (!rn_inithead(head, offsetof(struct sockaddr_in6, sin6_addr) << 3))
return 0; /* See above */
if (off == 0) /* See above */
return 1; /* only do the rest for the real thing */
rnh = *head;
KASSERT(rnh == rt_tables_get_rnh(0, AF_INET6), ("rnh?"));
rnh->rnh_addaddr = in6_addroute;
rnh->rnh_matchaddr = in6_matroute;
callout_init(&V_rtq_timer6, CALLOUT_MPSAFE);
callout_init(&V_rtq_mtutimer, CALLOUT_MPSAFE);
in6_rtqtimo(curvnet); /* kick off timeout first time */
in6_mtutimo(curvnet); /* kick off timeout first time */
return 1;
}
#ifdef VIMAGE
int
in6_detachhead(void **head, int off)
{
callout_drain(&V_rtq_timer6);
callout_drain(&V_rtq_mtutimer);
return (1);
}
#endif

1204
freebsd/netinet6/in6_src.c Normal file

File diff suppressed because it is too large Load Diff

786
freebsd/netinet6/in6_var.h Normal file
View File

@@ -0,0 +1,786 @@
/*-
* 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.
*
* $KAME: in6_var.h,v 1.56 2001/03/29 05:34:31 itojun Exp $
*/
/*-
* Copyright (c) 1985, 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.
* 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_var.h 8.1 (Berkeley) 6/10/93
* $FreeBSD$
*/
#ifndef _NETINET6_IN6_VAR_HH_
#define _NETINET6_IN6_VAR_HH_
#include <rtems/freebsd/sys/tree.h>
#ifdef _KERNEL
#include <rtems/freebsd/sys/libkern.h>
#endif
/*
* Interface address, Internet version. One of these structures
* is allocated for each interface with an Internet address.
* The ifaddr structure contains the protocol-independent part
* of the structure and is assumed to be first.
*/
/*
* pltime/vltime are just for future reference (required to implements 2
* hour rule for hosts). they should never be modified by nd6_timeout or
* anywhere else.
* userland -> kernel: accept pltime/vltime
* kernel -> userland: throw up everything
* in kernel: modify preferred/expire only
*/
struct in6_addrlifetime {
time_t ia6t_expire; /* valid lifetime expiration time */
time_t ia6t_preferred; /* preferred lifetime expiration time */
u_int32_t ia6t_vltime; /* valid lifetime */
u_int32_t ia6t_pltime; /* prefix lifetime */
};
struct nd_ifinfo;
struct scope6_id;
struct lltable;
struct mld_ifinfo;
struct in6_ifextra {
struct in6_ifstat *in6_ifstat;
struct icmp6_ifstat *icmp6_ifstat;
struct nd_ifinfo *nd_ifinfo;
struct scope6_id *scope6_id;
struct lltable *lltable;
struct mld_ifinfo *mld_ifinfo;
};
#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
struct in6_ifaddr {
struct ifaddr ia_ifa; /* protocol-independent info */
#define ia_ifp ia_ifa.ifa_ifp
#define ia_flags ia_ifa.ifa_flags
struct sockaddr_in6 ia_addr; /* interface address */
struct sockaddr_in6 ia_net; /* network number of interface */
struct sockaddr_in6 ia_dstaddr; /* space for destination addr */
struct sockaddr_in6 ia_prefixmask; /* prefix mask */
u_int32_t ia_plen; /* prefix length */
TAILQ_ENTRY(in6_ifaddr) ia_link; /* list of IPv6 addresses */
int ia6_flags;
struct in6_addrlifetime ia6_lifetime;
time_t ia6_createtime; /* the creation time of this address, which is
* currently used for temporary addresses only.
*/
time_t ia6_updatetime;
/* back pointer to the ND prefix (for autoconfigured addresses only) */
struct nd_prefix *ia6_ndpr;
/* multicast addresses joined from the kernel */
LIST_HEAD(, in6_multi_mship) ia6_memberships;
};
/* List of in6_ifaddr's. */
TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr);
/* control structure to manage address selection policy */
struct in6_addrpolicy {
struct sockaddr_in6 addr; /* prefix address */
struct sockaddr_in6 addrmask; /* prefix mask */
int preced; /* precedence */
int label; /* matching label */
u_quad_t use; /* statistics */
};
/*
* IPv6 interface statistics, as defined in RFC2465 Ipv6IfStatsEntry (p12).
*/
struct in6_ifstat {
u_quad_t ifs6_in_receive; /* # of total input datagram */
u_quad_t ifs6_in_hdrerr; /* # of datagrams with invalid hdr */
u_quad_t ifs6_in_toobig; /* # of datagrams exceeded MTU */
u_quad_t ifs6_in_noroute; /* # of datagrams with no route */
u_quad_t ifs6_in_addrerr; /* # of datagrams with invalid dst */
u_quad_t ifs6_in_protounknown; /* # of datagrams with unknown proto */
/* NOTE: increment on final dst if */
u_quad_t ifs6_in_truncated; /* # of truncated datagrams */
u_quad_t ifs6_in_discard; /* # of discarded datagrams */
/* NOTE: fragment timeout is not here */
u_quad_t ifs6_in_deliver; /* # of datagrams delivered to ULP */
/* NOTE: increment on final dst if */
u_quad_t ifs6_out_forward; /* # of datagrams forwarded */
/* NOTE: increment on outgoing if */
u_quad_t ifs6_out_request; /* # of outgoing datagrams from ULP */
/* NOTE: does not include forwrads */
u_quad_t ifs6_out_discard; /* # of discarded datagrams */
u_quad_t ifs6_out_fragok; /* # of datagrams fragmented */
u_quad_t ifs6_out_fragfail; /* # of datagrams failed on fragment */
u_quad_t ifs6_out_fragcreat; /* # of fragment datagrams */
/* NOTE: this is # after fragment */
u_quad_t ifs6_reass_reqd; /* # of incoming fragmented packets */
/* NOTE: increment on final dst if */
u_quad_t ifs6_reass_ok; /* # of reassembled packets */
/* NOTE: this is # after reass */
/* NOTE: increment on final dst if */
u_quad_t ifs6_reass_fail; /* # of reass failures */
/* NOTE: may not be packet count */
/* NOTE: increment on final dst if */
u_quad_t ifs6_in_mcast; /* # of inbound multicast datagrams */
u_quad_t ifs6_out_mcast; /* # of outbound multicast datagrams */
};
/*
* ICMPv6 interface statistics, as defined in RFC2466 Ipv6IfIcmpEntry.
* XXX: I'm not sure if this file is the right place for this structure...
*/
struct icmp6_ifstat {
/*
* Input statistics
*/
/* ipv6IfIcmpInMsgs, total # of input messages */
u_quad_t ifs6_in_msg;
/* ipv6IfIcmpInErrors, # of input error messages */
u_quad_t ifs6_in_error;
/* ipv6IfIcmpInDestUnreachs, # of input dest unreach errors */
u_quad_t ifs6_in_dstunreach;
/* ipv6IfIcmpInAdminProhibs, # of input administratively prohibited errs */
u_quad_t ifs6_in_adminprohib;
/* ipv6IfIcmpInTimeExcds, # of input time exceeded errors */
u_quad_t ifs6_in_timeexceed;
/* ipv6IfIcmpInParmProblems, # of input parameter problem errors */
u_quad_t ifs6_in_paramprob;
/* ipv6IfIcmpInPktTooBigs, # of input packet too big errors */
u_quad_t ifs6_in_pkttoobig;
/* ipv6IfIcmpInEchos, # of input echo requests */
u_quad_t ifs6_in_echo;
/* ipv6IfIcmpInEchoReplies, # of input echo replies */
u_quad_t ifs6_in_echoreply;
/* ipv6IfIcmpInRouterSolicits, # of input router solicitations */
u_quad_t ifs6_in_routersolicit;
/* ipv6IfIcmpInRouterAdvertisements, # of input router advertisements */
u_quad_t ifs6_in_routeradvert;
/* ipv6IfIcmpInNeighborSolicits, # of input neighbor solicitations */
u_quad_t ifs6_in_neighborsolicit;
/* ipv6IfIcmpInNeighborAdvertisements, # of input neighbor advertisements */
u_quad_t ifs6_in_neighboradvert;
/* ipv6IfIcmpInRedirects, # of input redirects */
u_quad_t ifs6_in_redirect;
/* ipv6IfIcmpInGroupMembQueries, # of input MLD queries */
u_quad_t ifs6_in_mldquery;
/* ipv6IfIcmpInGroupMembResponses, # of input MLD reports */
u_quad_t ifs6_in_mldreport;
/* ipv6IfIcmpInGroupMembReductions, # of input MLD done */
u_quad_t ifs6_in_mlddone;
/*
* Output statistics. We should solve unresolved routing problem...
*/
/* ipv6IfIcmpOutMsgs, total # of output messages */
u_quad_t ifs6_out_msg;
/* ipv6IfIcmpOutErrors, # of output error messages */
u_quad_t ifs6_out_error;
/* ipv6IfIcmpOutDestUnreachs, # of output dest unreach errors */
u_quad_t ifs6_out_dstunreach;
/* ipv6IfIcmpOutAdminProhibs, # of output administratively prohibited errs */
u_quad_t ifs6_out_adminprohib;
/* ipv6IfIcmpOutTimeExcds, # of output time exceeded errors */
u_quad_t ifs6_out_timeexceed;
/* ipv6IfIcmpOutParmProblems, # of output parameter problem errors */
u_quad_t ifs6_out_paramprob;
/* ipv6IfIcmpOutPktTooBigs, # of output packet too big errors */
u_quad_t ifs6_out_pkttoobig;
/* ipv6IfIcmpOutEchos, # of output echo requests */
u_quad_t ifs6_out_echo;
/* ipv6IfIcmpOutEchoReplies, # of output echo replies */
u_quad_t ifs6_out_echoreply;
/* ipv6IfIcmpOutRouterSolicits, # of output router solicitations */
u_quad_t ifs6_out_routersolicit;
/* ipv6IfIcmpOutRouterAdvertisements, # of output router advertisements */
u_quad_t ifs6_out_routeradvert;
/* ipv6IfIcmpOutNeighborSolicits, # of output neighbor solicitations */
u_quad_t ifs6_out_neighborsolicit;
/* ipv6IfIcmpOutNeighborAdvertisements, # of output neighbor advertisements */
u_quad_t ifs6_out_neighboradvert;
/* ipv6IfIcmpOutRedirects, # of output redirects */
u_quad_t ifs6_out_redirect;
/* ipv6IfIcmpOutGroupMembQueries, # of output MLD queries */
u_quad_t ifs6_out_mldquery;
/* ipv6IfIcmpOutGroupMembResponses, # of output MLD reports */
u_quad_t ifs6_out_mldreport;
/* ipv6IfIcmpOutGroupMembReductions, # of output MLD done */
u_quad_t ifs6_out_mlddone;
};
struct in6_ifreq {
char ifr_name[IFNAMSIZ];
union {
struct sockaddr_in6 ifru_addr;
struct sockaddr_in6 ifru_dstaddr;
int ifru_flags;
int ifru_flags6;
int ifru_metric;
caddr_t ifru_data;
struct in6_addrlifetime ifru_lifetime;
struct in6_ifstat ifru_stat;
struct icmp6_ifstat ifru_icmp6stat;
u_int32_t ifru_scope_id[16];
} ifr_ifru;
};
struct in6_aliasreq {
char ifra_name[IFNAMSIZ];
struct sockaddr_in6 ifra_addr;
struct sockaddr_in6 ifra_dstaddr;
struct sockaddr_in6 ifra_prefixmask;
int ifra_flags;
struct in6_addrlifetime ifra_lifetime;
};
/* prefix type macro */
#define IN6_PREFIX_ND 1
#define IN6_PREFIX_RR 2
/*
* prefix related flags passed between kernel(NDP related part) and
* user land command(ifconfig) and daemon(rtadvd).
*/
struct in6_prflags {
struct prf_ra {
u_char onlink : 1;
u_char autonomous : 1;
u_char reserved : 6;
} prf_ra;
u_char prf_reserved1;
u_short prf_reserved2;
/* want to put this on 4byte offset */
struct prf_rr {
u_char decrvalid : 1;
u_char decrprefd : 1;
u_char reserved : 6;
} prf_rr;
u_char prf_reserved3;
u_short prf_reserved4;
};
struct in6_prefixreq {
char ipr_name[IFNAMSIZ];
u_char ipr_origin;
u_char ipr_plen;
u_int32_t ipr_vltime;
u_int32_t ipr_pltime;
struct in6_prflags ipr_flags;
struct sockaddr_in6 ipr_prefix;
};
#define PR_ORIG_RA 0
#define PR_ORIG_RR 1
#define PR_ORIG_STATIC 2
#define PR_ORIG_KERNEL 3
#define ipr_raf_onlink ipr_flags.prf_ra.onlink
#define ipr_raf_auto ipr_flags.prf_ra.autonomous
#define ipr_statef_onlink ipr_flags.prf_state.onlink
#define ipr_rrf_decrvalid ipr_flags.prf_rr.decrvalid
#define ipr_rrf_decrprefd ipr_flags.prf_rr.decrprefd
struct in6_rrenumreq {
char irr_name[IFNAMSIZ];
u_char irr_origin;
u_char irr_m_len; /* match len for matchprefix */
u_char irr_m_minlen; /* minlen for matching prefix */
u_char irr_m_maxlen; /* maxlen for matching prefix */
u_char irr_u_uselen; /* uselen for adding prefix */
u_char irr_u_keeplen; /* keeplen from matching prefix */
struct irr_raflagmask {
u_char onlink : 1;
u_char autonomous : 1;
u_char reserved : 6;
} irr_raflagmask;
u_int32_t irr_vltime;
u_int32_t irr_pltime;
struct in6_prflags irr_flags;
struct sockaddr_in6 irr_matchprefix;
struct sockaddr_in6 irr_useprefix;
};
#define irr_raf_mask_onlink irr_raflagmask.onlink
#define irr_raf_mask_auto irr_raflagmask.autonomous
#define irr_raf_mask_reserved irr_raflagmask.reserved
#define irr_raf_onlink irr_flags.prf_ra.onlink
#define irr_raf_auto irr_flags.prf_ra.autonomous
#define irr_statef_onlink irr_flags.prf_state.onlink
#define irr_rrf irr_flags.prf_rr
#define irr_rrf_decrvalid irr_flags.prf_rr.decrvalid
#define irr_rrf_decrprefd irr_flags.prf_rr.decrprefd
/*
* Given a pointer to an in6_ifaddr (ifaddr),
* return a pointer to the addr as a sockaddr_in6
*/
#define IA6_IN6(ia) (&((ia)->ia_addr.sin6_addr))
#define IA6_DSTIN6(ia) (&((ia)->ia_dstaddr.sin6_addr))
#define IA6_MASKIN6(ia) (&((ia)->ia_prefixmask.sin6_addr))
#define IA6_SIN6(ia) (&((ia)->ia_addr))
#define IA6_DSTSIN6(ia) (&((ia)->ia_dstaddr))
#define IFA_IN6(x) (&((struct sockaddr_in6 *)((x)->ifa_addr))->sin6_addr)
#define IFA_DSTIN6(x) (&((struct sockaddr_in6 *)((x)->ifa_dstaddr))->sin6_addr)
#define IFPR_IN6(x) (&((struct sockaddr_in6 *)((x)->ifpr_prefix))->sin6_addr)
#ifdef _KERNEL
#define IN6_ARE_MASKED_ADDR_EQUAL(d, a, m) ( \
(((d)->s6_addr32[0] ^ (a)->s6_addr32[0]) & (m)->s6_addr32[0]) == 0 && \
(((d)->s6_addr32[1] ^ (a)->s6_addr32[1]) & (m)->s6_addr32[1]) == 0 && \
(((d)->s6_addr32[2] ^ (a)->s6_addr32[2]) & (m)->s6_addr32[2]) == 0 && \
(((d)->s6_addr32[3] ^ (a)->s6_addr32[3]) & (m)->s6_addr32[3]) == 0 )
#endif
#define SIOCSIFADDR_IN6 _IOW('i', 12, struct in6_ifreq)
#define SIOCGIFADDR_IN6 _IOWR('i', 33, struct in6_ifreq)
#ifdef _KERNEL
/*
* SIOCSxxx ioctls should be unused (see comments in in6.c), but
* we do not shift numbers for binary compatibility.
*/
#define SIOCSIFDSTADDR_IN6 _IOW('i', 14, struct in6_ifreq)
#define SIOCSIFNETMASK_IN6 _IOW('i', 22, struct in6_ifreq)
#endif
#define SIOCGIFDSTADDR_IN6 _IOWR('i', 34, struct in6_ifreq)
#define SIOCGIFNETMASK_IN6 _IOWR('i', 37, struct in6_ifreq)
#define SIOCDIFADDR_IN6 _IOW('i', 25, struct in6_ifreq)
#define SIOCAIFADDR_IN6 _IOW('i', 26, struct in6_aliasreq)
#define SIOCSIFPHYADDR_IN6 _IOW('i', 70, struct in6_aliasreq)
#define SIOCGIFPSRCADDR_IN6 _IOWR('i', 71, struct in6_ifreq)
#define SIOCGIFPDSTADDR_IN6 _IOWR('i', 72, struct in6_ifreq)
#define SIOCGIFAFLAG_IN6 _IOWR('i', 73, struct in6_ifreq)
#define SIOCGDRLST_IN6 _IOWR('i', 74, struct in6_drlist)
#ifdef _KERNEL
/* XXX: SIOCGPRLST_IN6 is exposed in KAME but in6_oprlist is not. */
#define SIOCGPRLST_IN6 _IOWR('i', 75, struct in6_oprlist)
#endif
#ifdef _KERNEL
#define OSIOCGIFINFO_IN6 _IOWR('i', 76, struct in6_ondireq)
#endif
#define SIOCGIFINFO_IN6 _IOWR('i', 108, struct in6_ndireq)
#define SIOCSIFINFO_IN6 _IOWR('i', 109, struct in6_ndireq)
#define SIOCSNDFLUSH_IN6 _IOWR('i', 77, struct in6_ifreq)
#define SIOCGNBRINFO_IN6 _IOWR('i', 78, struct in6_nbrinfo)
#define SIOCSPFXFLUSH_IN6 _IOWR('i', 79, struct in6_ifreq)
#define SIOCSRTRFLUSH_IN6 _IOWR('i', 80, struct in6_ifreq)
#define SIOCGIFALIFETIME_IN6 _IOWR('i', 81, struct in6_ifreq)
#define SIOCSIFALIFETIME_IN6 _IOWR('i', 82, struct in6_ifreq)
#define SIOCGIFSTAT_IN6 _IOWR('i', 83, struct in6_ifreq)
#define SIOCGIFSTAT_ICMP6 _IOWR('i', 84, struct in6_ifreq)
#define SIOCSDEFIFACE_IN6 _IOWR('i', 85, struct in6_ndifreq)
#define SIOCGDEFIFACE_IN6 _IOWR('i', 86, struct in6_ndifreq)
#define SIOCSIFINFO_FLAGS _IOWR('i', 87, struct in6_ndireq) /* XXX */
#define SIOCSSCOPE6 _IOW('i', 88, struct in6_ifreq)
#define SIOCGSCOPE6 _IOWR('i', 89, struct in6_ifreq)
#define SIOCGSCOPE6DEF _IOWR('i', 90, struct in6_ifreq)
#define SIOCSIFPREFIX_IN6 _IOW('i', 100, struct in6_prefixreq) /* set */
#define SIOCGIFPREFIX_IN6 _IOWR('i', 101, struct in6_prefixreq) /* get */
#define SIOCDIFPREFIX_IN6 _IOW('i', 102, struct in6_prefixreq) /* del */
#define SIOCAIFPREFIX_IN6 _IOW('i', 103, struct in6_rrenumreq) /* add */
#define SIOCCIFPREFIX_IN6 _IOW('i', 104, \
struct in6_rrenumreq) /* change */
#define SIOCSGIFPREFIX_IN6 _IOW('i', 105, \
struct in6_rrenumreq) /* set global */
#define SIOCGETSGCNT_IN6 _IOWR('u', 106, \
struct sioc_sg_req6) /* get s,g pkt cnt */
#define SIOCGETMIFCNT_IN6 _IOWR('u', 107, \
struct sioc_mif_req6) /* get pkt cnt per if */
#define SIOCAADDRCTL_POLICY _IOW('u', 108, struct in6_addrpolicy)
#define SIOCDADDRCTL_POLICY _IOW('u', 109, struct in6_addrpolicy)
#define IN6_IFF_ANYCAST 0x01 /* anycast address */
#define IN6_IFF_TENTATIVE 0x02 /* tentative address */
#define IN6_IFF_DUPLICATED 0x04 /* DAD detected duplicate */
#define IN6_IFF_DETACHED 0x08 /* may be detached from the link */
#define IN6_IFF_DEPRECATED 0x10 /* deprecated address */
#define IN6_IFF_NODAD 0x20 /* don't perform DAD on this address
* (used only at first SIOC* call)
*/
#define IN6_IFF_AUTOCONF 0x40 /* autoconfigurable address. */
#define IN6_IFF_TEMPORARY 0x80 /* temporary (anonymous) address. */
#define IN6_IFF_NOPFX 0x8000 /* skip kernel prefix management.
* XXX: this should be temporary.
*/
/* do not input/output */
#define IN6_IFF_NOTREADY (IN6_IFF_TENTATIVE|IN6_IFF_DUPLICATED)
#ifdef _KERNEL
#define IN6_ARE_SCOPE_CMP(a,b) ((a)-(b))
#define IN6_ARE_SCOPE_EQUAL(a,b) ((a)==(b))
#endif
#ifdef _KERNEL
VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead);
#define V_in6_ifaddrhead VNET(in6_ifaddrhead)
extern struct rwlock in6_ifaddr_lock;
#define IN6_IFADDR_LOCK_ASSERT( ) rw_assert(&in6_ifaddr_lock, RA_LOCKED)
#define IN6_IFADDR_RLOCK() rw_rlock(&in6_ifaddr_lock)
#define IN6_IFADDR_RLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_RLOCKED)
#define IN6_IFADDR_RUNLOCK() rw_runlock(&in6_ifaddr_lock)
#define IN6_IFADDR_WLOCK() rw_wlock(&in6_ifaddr_lock)
#define IN6_IFADDR_WLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_WLOCKED)
#define IN6_IFADDR_WUNLOCK() rw_wunlock(&in6_ifaddr_lock)
VNET_DECLARE(struct icmp6stat, icmp6stat);
#define V_icmp6stat VNET(icmp6stat)
#define in6_ifstat_inc(ifp, tag) \
do { \
if (ifp) \
((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->in6_ifstat->tag++; \
} while (/*CONSTCOND*/ 0)
extern struct in6_addr zeroin6_addr;
extern u_char inet6ctlerrmap[];
VNET_DECLARE(unsigned long, in6_maxmtu);
#define V_in6_maxmtu VNET(in6_maxmtu)
#endif /* _KERNEL */
/*
* IPv6 multicast MLD-layer source entry.
*/
struct ip6_msource {
RB_ENTRY(ip6_msource) im6s_link; /* RB tree links */
struct in6_addr im6s_addr;
struct im6s_st {
uint16_t ex; /* # of exclusive members */
uint16_t in; /* # of inclusive members */
} im6s_st[2]; /* state at t0, t1 */
uint8_t im6s_stp; /* pending query */
};
RB_HEAD(ip6_msource_tree, ip6_msource);
/*
* IPv6 multicast PCB-layer source entry.
*
* NOTE: overlapping use of struct ip6_msource fields at start.
*/
struct in6_msource {
RB_ENTRY(ip6_msource) im6s_link; /* Common field */
struct in6_addr im6s_addr; /* Common field */
uint8_t im6sl_st[2]; /* state before/at commit */
};
#ifdef _KERNEL
/*
* IPv6 source tree comparison function.
*
* An ordered predicate is necessary; bcmp() is not documented to return
* an indication of order, memcmp() is, and is an ISO C99 requirement.
*/
static __inline int
ip6_msource_cmp(const struct ip6_msource *a, const struct ip6_msource *b)
{
return (memcmp(&a->im6s_addr, &b->im6s_addr, sizeof(struct in6_addr)));
}
RB_PROTOTYPE(ip6_msource_tree, ip6_msource, im6s_link, ip6_msource_cmp);
#endif /* _KERNEL */
/*
* IPv6 multicast PCB-layer group filter descriptor.
*/
struct in6_mfilter {
struct ip6_msource_tree im6f_sources; /* source list for (S,G) */
u_long im6f_nsrc; /* # of source entries */
uint8_t im6f_st[2]; /* state before/at commit */
};
/*
* Legacy KAME IPv6 multicast membership descriptor.
*/
struct in6_multi_mship {
struct in6_multi *i6mm_maddr;
LIST_ENTRY(in6_multi_mship) i6mm_chain;
};
/*
* IPv6 group descriptor.
*
* For every entry on an ifnet's if_multiaddrs list which represents
* an IP multicast group, there is one of these structures.
*
* If any source filters are present, then a node will exist in the RB-tree
* to permit fast lookup by source whenever an operation takes place.
* This permits pre-order traversal when we issue reports.
* Source filter trees are kept separately from the socket layer to
* greatly simplify locking.
*
* When MLDv2 is active, in6m_timer is the response to group query timer.
* The state-change timer in6m_sctimer is separate; whenever state changes
* for the group the state change record is generated and transmitted,
* and kept if retransmissions are necessary.
*
* FUTURE: in6m_link is now only used when groups are being purged
* on a detaching ifnet. It could be demoted to a SLIST_ENTRY, but
* because it is at the very start of the struct, we can't do this
* w/o breaking the ABI for ifmcstat.
*/
struct in6_multi {
LIST_ENTRY(in6_multi) in6m_entry; /* list glue */
struct in6_addr in6m_addr; /* IPv6 multicast address */
struct ifnet *in6m_ifp; /* back pointer to ifnet */
struct ifmultiaddr *in6m_ifma; /* back pointer to ifmultiaddr */
u_int in6m_refcount; /* reference count */
u_int in6m_state; /* state of the membership */
u_int in6m_timer; /* MLD6 listener report timer */
/* New fields for MLDv2 follow. */
struct mld_ifinfo *in6m_mli; /* MLD info */
SLIST_ENTRY(in6_multi) in6m_nrele; /* to-be-released by MLD */
struct ip6_msource_tree in6m_srcs; /* tree of sources */
u_long in6m_nsrc; /* # of tree entries */
struct ifqueue in6m_scq; /* queue of pending
* state-change packets */
struct timeval in6m_lastgsrtv; /* last G-S-R query */
uint16_t in6m_sctimer; /* state-change timer */
uint16_t in6m_scrv; /* state-change rexmit count */
/*
* SSM state counters which track state at T0 (the time the last
* state-change report's RV timer went to zero) and T1
* (time of pending report, i.e. now).
* Used for computing MLDv2 state-change reports. Several refcounts
* are maintained here to optimize for common use-cases.
*/
struct in6m_st {
uint16_t iss_fmode; /* MLD filter mode */
uint16_t iss_asm; /* # of ASM listeners */
uint16_t iss_ex; /* # of exclusive members */
uint16_t iss_in; /* # of inclusive members */
uint16_t iss_rec; /* # of recorded sources */
} in6m_st[2]; /* state at t0, t1 */
};
/*
* Helper function to derive the filter mode on a source entry
* from its internal counters. Predicates are:
* A source is only excluded if all listeners exclude it.
* A source is only included if no listeners exclude it,
* and at least one listener includes it.
* May be used by ifmcstat(8).
*/
static __inline uint8_t
im6s_get_mode(const struct in6_multi *inm, const struct ip6_msource *ims,
uint8_t t)
{
t = !!t;
if (inm->in6m_st[t].iss_ex > 0 &&
inm->in6m_st[t].iss_ex == ims->im6s_st[t].ex)
return (MCAST_EXCLUDE);
else if (ims->im6s_st[t].in > 0 && ims->im6s_st[t].ex == 0)
return (MCAST_INCLUDE);
return (MCAST_UNDEFINED);
}
#ifdef _KERNEL
/*
* Lock macros for IPv6 layer multicast address lists. IPv6 lock goes
* before link layer multicast locks in the lock order. In most cases,
* consumers of IN_*_MULTI() macros should acquire the locks before
* calling them; users of the in_{add,del}multi() functions should not.
*/
extern struct mtx in6_multi_mtx;
#define IN6_MULTI_LOCK() mtx_lock(&in6_multi_mtx)
#define IN6_MULTI_UNLOCK() mtx_unlock(&in6_multi_mtx)
#define IN6_MULTI_LOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_OWNED)
#define IN6_MULTI_UNLOCK_ASSERT() mtx_assert(&in6_multi_mtx, MA_NOTOWNED)
/*
* Look up an in6_multi record for an IPv6 multicast address
* on the interface ifp.
* If no record found, return NULL.
*
* SMPng: The IN6_MULTI_LOCK and IF_ADDR_LOCK on ifp must be held.
*/
static __inline struct in6_multi *
in6m_lookup_locked(struct ifnet *ifp, const struct in6_addr *mcaddr)
{
struct ifmultiaddr *ifma;
struct in6_multi *inm;
IN6_MULTI_LOCK_ASSERT();
IF_ADDR_LOCK_ASSERT(ifp);
inm = NULL;
TAILQ_FOREACH(ifma, &((ifp)->if_multiaddrs), ifma_link) {
if (ifma->ifma_addr->sa_family == AF_INET6) {
inm = (struct in6_multi *)ifma->ifma_protospec;
if (IN6_ARE_ADDR_EQUAL(&inm->in6m_addr, mcaddr))
break;
inm = NULL;
}
}
return (inm);
}
/*
* Wrapper for in6m_lookup_locked().
*
* SMPng: Assumes that neithr the IN6_MULTI_LOCK() or IF_ADDR_LOCK() are held.
*/
static __inline struct in6_multi *
in6m_lookup(struct ifnet *ifp, const struct in6_addr *mcaddr)
{
struct in6_multi *inm;
IN6_MULTI_LOCK();
IF_ADDR_LOCK(ifp);
inm = in6m_lookup_locked(ifp, mcaddr);
IF_ADDR_UNLOCK(ifp);
IN6_MULTI_UNLOCK();
return (inm);
}
/* Acquire an in6_multi record. */
static __inline void
in6m_acquire_locked(struct in6_multi *inm)
{
IN6_MULTI_LOCK_ASSERT();
++inm->in6m_refcount;
}
struct ip6_moptions;
struct sockopt;
/* Multicast KPIs. */
int im6o_mc_filter(const struct ip6_moptions *, const struct ifnet *,
const struct sockaddr *, const struct sockaddr *);
int in6_mc_join(struct ifnet *, const struct in6_addr *,
struct in6_mfilter *, struct in6_multi **, int);
int in6_mc_join_locked(struct ifnet *, const struct in6_addr *,
struct in6_mfilter *, struct in6_multi **, int);
int in6_mc_leave(struct in6_multi *, struct in6_mfilter *);
int in6_mc_leave_locked(struct in6_multi *, struct in6_mfilter *);
void in6m_clear_recorded(struct in6_multi *);
void in6m_commit(struct in6_multi *);
void in6m_print(const struct in6_multi *);
int in6m_record_source(struct in6_multi *, const struct in6_addr *);
void in6m_release_locked(struct in6_multi *);
void ip6_freemoptions(struct ip6_moptions *);
int ip6_getmoptions(struct inpcb *, struct sockopt *);
int ip6_setmoptions(struct inpcb *, struct sockopt *);
/* Legacy KAME multicast KPIs. */
struct in6_multi_mship *
in6_joingroup(struct ifnet *, struct in6_addr *, int *, int);
int in6_leavegroup(struct in6_multi_mship *);
/* flags to in6_update_ifa */
#define IN6_IFAUPDATE_DADDELAY 0x1 /* first time to configure an address */
int in6_mask2len __P((struct in6_addr *, u_char *));
int in6_control __P((struct socket *, u_long, caddr_t, struct ifnet *,
struct thread *));
int in6_update_ifa __P((struct ifnet *, struct in6_aliasreq *,
struct in6_ifaddr *, int));
void in6_purgeaddr __P((struct ifaddr *));
int in6if_do_dad __P((struct ifnet *));
void in6_purgeif __P((struct ifnet *));
void in6_savemkludge __P((struct in6_ifaddr *));
void *in6_domifattach __P((struct ifnet *));
void in6_domifdetach __P((struct ifnet *, void *));
void in6_setmaxmtu __P((void));
int in6_if2idlen __P((struct ifnet *));
struct in6_ifaddr *in6ifa_ifpforlinklocal __P((struct ifnet *, int));
struct in6_ifaddr *in6ifa_ifpwithaddr __P((struct ifnet *, struct in6_addr *));
char *ip6_sprintf __P((char *, const struct in6_addr *));
int in6_addr2zoneid __P((struct ifnet *, struct in6_addr *, u_int32_t *));
int in6_matchlen __P((struct in6_addr *, struct in6_addr *));
int in6_are_prefix_equal __P((struct in6_addr *, struct in6_addr *, int));
void in6_prefixlen2mask __P((struct in6_addr *, int));
int in6_prefix_ioctl __P((struct socket *, u_long, caddr_t,
struct ifnet *));
int in6_prefix_add_ifid __P((int, struct in6_ifaddr *));
void in6_prefix_remove_ifid __P((int, struct in6_ifaddr *));
void in6_purgeprefix __P((struct ifnet *));
void in6_ifremloop(struct ifaddr *);
void in6_ifaddloop(struct ifaddr *);
int in6_is_addr_deprecated __P((struct sockaddr_in6 *));
struct inpcb;
int in6_src_ioctl __P((u_long, caddr_t));
#endif /* _KERNEL */
#endif /* _NETINET6_IN6_VAR_HH_ */

4
freebsd/netinet6/ip6.h Normal file
View File

@@ -0,0 +1,4 @@
/* $FreeBSD$ */
/* $KAME: ip6.h,v 1.7 2000/03/25 07:23:36 sumikawa Exp $ */
#error "netinet6/ip6.h is obsolete. use netinet/ip6.h"

View File

@@ -0,0 +1,41 @@
/*-
* Copyright (C) 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.
*
* $KAME: ip_ecn.h,v 1.5 2000/03/27 04:58:38 sumikawa Exp $
* $FreeBSD$
*/
/*
* ECN consideration on tunnel ingress/egress operation.
* http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
*/
#ifdef _KERNEL
extern void ip6_ecn_ingress(int, u_int32_t *, const u_int32_t *);
extern int ip6_ecn_egress(int, const u_int32_t *, u_int32_t *);
#endif

View File

@@ -0,0 +1,626 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: ip6_forward.c,v 1.69 2001/05/17 03:48:30 itojun Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_inet.h>
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/local/opt_ipsec.h>
#include <rtems/freebsd/local/opt_ipstealth.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/domain.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/errno.h>
#include <rtems/freebsd/sys/time.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/syslog.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/net/pfil.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/in_systm.h>
#include <rtems/freebsd/netinet/ip.h>
#include <rtems/freebsd/netinet/ip_var.h>
#include <rtems/freebsd/netinet6/in6_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/scope6_var.h>
#include <rtems/freebsd/netinet/icmp6.h>
#include <rtems/freebsd/netinet6/nd6.h>
#include <rtems/freebsd/netinet/in_pcb.h>
#ifdef IPSEC
#include <rtems/freebsd/netipsec/ipsec.h>
#include <rtems/freebsd/netipsec/ipsec6.h>
#include <rtems/freebsd/netipsec/key.h>
#endif /* IPSEC */
#include <rtems/freebsd/netinet6/ip6protosw.h>
/*
* 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(struct mbuf *m, int srcrt)
{
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
struct sockaddr_in6 *dst = NULL;
struct rtentry *rt = NULL;
struct route_in6 rin6;
int error, type = 0, code = 0;
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
u_int32_t inzone, outzone;
struct in6_addr src_in6, dst_in6;
#ifdef IPSEC
struct secpolicy *sp = NULL;
int ipsecrt = 0;
#endif
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
#ifdef IPSEC
/*
* Check AH/ESP integrity.
*/
/*
* Don't increment ip6s_cantforward because this is the check
* before forwarding packet actually.
*/
if (ipsec6_in_reject(m, NULL)) {
V_ipsec6stat.in_polvio++;
m_freem(m);
return;
}
#endif /* IPSEC */
/*
* Do not forward packets to multicast destination (should be handled
* by ip6_mforward().
* Do not forward packets with unspecified source. It was discussed
* in July 2000, on the ipngwg mailing list.
*/
if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 ||
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
V_ip6stat.ip6s_cantforward++;
/* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */
if (V_ip6_log_time + V_ip6_log_interval < time_second) {
V_ip6_log_time = time_second;
log(LOG_DEBUG,
"cannot forward "
"from %s to %s nxt %d received on %s\n",
ip6_sprintf(ip6bufs, &ip6->ip6_src),
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
ip6->ip6_nxt,
if_name(m->m_pkthdr.rcvif));
}
m_freem(m);
return;
}
#ifdef IPSTEALTH
if (!V_ip6stealth) {
#endif
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 IPSTEALTH
}
#endif
/*
* Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU -
* size of IPv6 + ICMPv6 headers) 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.
*
* It is important to save it before IPsec processing as IPsec
* processing may modify the mbuf.
*/
mcopy = m_copy(m, 0, imin(m->m_pkthdr.len, ICMPV6_PLD_MAXLEN));
#ifdef IPSEC
/* get a security policy for this packet */
sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND,
IP_FORWARDING, &error);
if (sp == NULL) {
V_ipsec6stat.out_inval++;
V_ip6stat.ip6s_cantforward++;
if (mcopy) {
#if 0
/* XXX: what icmp ? */
#else
m_freem(mcopy);
#endif
}
m_freem(m);
return;
}
error = 0;
/* check policy */
switch (sp->policy) {
case IPSEC_POLICY_DISCARD:
/*
* This packet is just discarded.
*/
V_ipsec6stat.out_polvio++;
V_ip6stat.ip6s_cantforward++;
KEY_FREESP(&sp);
if (mcopy) {
#if 0
/* XXX: what icmp ? */
#else
m_freem(mcopy);
#endif
}
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");
V_ip6stat.ip6s_cantforward++;
KEY_FREESP(&sp);
if (mcopy) {
#if 0
/* XXX: what icmp ? */
#else
m_freem(mcopy);
#endif
}
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 ipsecrequest *isr = NULL;
struct ipsec_output_state state;
/*
* when the kernel forwards a packet, it is not proper to apply
* IPsec transport mode to the packet is not proper. this check
* avoid from this.
* at present, if there is even a transport mode SA request in the
* security policy, the kernel does not apply IPsec to the packet.
* this check is not enough because the following case is valid.
* ipsec esp/tunnel/xxx-xxx/require esp/transport//require;
*/
for (isr = sp->req; isr; isr = isr->next) {
if (isr->saidx.mode == IPSEC_MODE_ANY)
goto doipsectunnel;
if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
goto doipsectunnel;
}
/*
* if there's no need for tunnel mode IPsec, skip.
*/
if (!isr)
goto skip_ipsec;
doipsectunnel:
/*
* 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;
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);
/* FALLTHROUGH */
case ENOENT:
/* don't show these error codes to the user */
break;
}
V_ip6stat.ip6s_cantforward++;
if (mcopy) {
#if 0
/* XXX: what icmp ? */
#else
m_freem(mcopy);
#endif
}
m_freem(m);
return;
} else {
/*
* In the FAST IPSec case we have already
* re-injected the packet and it has been freed
* by the ipsec_done() function. So, just clean
* up after ourselves.
*/
m = NULL;
goto freecopy;
}
if ((m != NULL) && (ip6 != mtod(m, struct ip6_hdr *)) ){
/*
* now tunnel mode headers are added. we are originating
* packet instead of forwarding the packet.
*/
ip6_output(m, NULL, NULL, IPV6_FORWARDING/*XXX*/, NULL, NULL,
NULL);
goto freecopy;
}
/* adjust pointer */
dst = (struct sockaddr_in6 *)state.dst;
rt = state.ro ? state.ro->ro_rt : NULL;
if (dst != NULL && rt != NULL)
ipsecrt = 1;
}
if (ipsecrt)
goto skip_routing;
skip_ipsec:
#endif
bzero(&rin6, sizeof(struct route_in6));
dst = (struct sockaddr_in6 *)&rin6.ro_dst;
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_family = AF_INET6;
dst->sin6_addr = ip6->ip6_dst;
rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
if (rin6.ro_rt != NULL)
RT_UNLOCK(rin6.ro_rt);
else {
V_ip6stat.ip6s_noroute++;
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_noroute);
if (mcopy) {
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_NOROUTE, 0);
}
goto bad;
}
rt = rin6.ro_rt;
#ifdef IPSEC
skip_routing:
#endif
/*
* Source scope check: if a packet can't be delivered to its
* destination for the reason that the destination is beyond the scope
* of the source address, discard the packet and return an icmp6
* destination unreachable error with Code 2 (beyond scope of source
* address). We use a local copy of ip6_src, since in6_setscope()
* will possibly modify its first argument.
* [draft-ietf-ipngwg-icmp-v3-04.txt, Section 3.1]
*/
src_in6 = ip6->ip6_src;
if (in6_setscope(&src_in6, rt->rt_ifp, &outzone)) {
/* XXX: this should not happen */
V_ip6stat.ip6s_cantforward++;
V_ip6stat.ip6s_badscope++;
goto bad;
}
if (in6_setscope(&src_in6, m->m_pkthdr.rcvif, &inzone)) {
V_ip6stat.ip6s_cantforward++;
V_ip6stat.ip6s_badscope++;
goto bad;
}
if (inzone != outzone
#ifdef IPSEC
&& !ipsecrt
#endif
) {
V_ip6stat.ip6s_cantforward++;
V_ip6stat.ip6s_badscope++;
in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard);
if (V_ip6_log_time + V_ip6_log_interval < time_second) {
V_ip6_log_time = time_second;
log(LOG_DEBUG,
"cannot forward "
"src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
ip6_sprintf(ip6bufs, &ip6->ip6_src),
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
ip6->ip6_nxt,
if_name(m->m_pkthdr.rcvif), if_name(rt->rt_ifp));
}
if (mcopy)
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_BEYONDSCOPE, 0);
goto bad;
}
/*
* Destination scope check: if a packet is going to break the scope
* zone of packet's destination address, discard it. This case should
* usually be prevented by appropriately-configured routing table, but
* we need an explicit check because we may mistakenly forward the
* packet to a different zone by (e.g.) a default route.
*/
dst_in6 = ip6->ip6_dst;
if (in6_setscope(&dst_in6, m->m_pkthdr.rcvif, &inzone) != 0 ||
in6_setscope(&dst_in6, rt->rt_ifp, &outzone) != 0 ||
inzone != outzone) {
V_ip6stat.ip6s_cantforward++;
V_ip6stat.ip6s_badscope++;
goto bad;
}
if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
if (mcopy) {
u_long mtu;
#ifdef IPSEC
struct secpolicy *sp;
int ipsecerror;
size_t ipsechdrsiz;
#endif /* IPSEC */
mtu = IN6_LINKMTU(rt->rt_ifp);
#ifdef IPSEC
/*
* When we do IPsec tunnel ingress, we need to play
* with the link value (decrement IPsec header size
* from mtu value). The code is much simpler than v4
* case, as we have the outgoing interface for
* encapsulated packet as "rt->rt_ifp".
*/
sp = ipsec_getpolicybyaddr(mcopy, IPSEC_DIR_OUTBOUND,
IP_FORWARDING, &ipsecerror);
if (sp) {
ipsechdrsiz = ipsec_hdrsiz(mcopy,
IPSEC_DIR_OUTBOUND, NULL);
if (ipsechdrsiz < mtu)
mtu -= ipsechdrsiz;
}
/*
* if mtu becomes less than minimum MTU,
* tell minimum MTU (and I'll need to fragment it).
*/
if (mtu < IPV6_MMTU)
mtu = IPV6_MMTU;
#endif /* IPSEC */
icmp6_error(mcopy, ICMP6_PACKET_TOO_BIG, 0, mtu);
}
goto bad;
}
if (rt->rt_flags & RTF_GATEWAY)
dst = (struct sockaddr_in6 *)rt->rt_gateway;
/*
* 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 (V_ip6_sendredirects && rt->rt_ifp == m->m_pkthdr.rcvif && !srcrt &&
#ifdef IPSEC
!ipsecrt &&
#endif /* IPSEC */
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {
if ((rt->rt_ifp->if_flags & IFF_POINTOPOINT) != 0) {
/*
* If the incoming interface is equal to the outgoing
* one, and the link attached to the interface is
* point-to-point, then it will be highly probable
* that a routing loop occurs. Thus, we immediately
* drop the packet and send an ICMPv6 error message.
*
* type/code is based on suggestion by Rich Draves.
* not sure if it is the best pick.
*/
icmp6_error(mcopy, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_ADDR, 0);
goto bad;
}
type = ND_REDIRECT;
}
/*
* Fake scoped addresses. Note that even link-local source or
* destinaion can appear, if the originating node just sends the
* packet to us (without address resolution for the destination).
* Since both icmp6_error and icmp6_redirect_output fill the embedded
* link identifiers, we can do this stuff after making a copy for
* returning an error.
*/
if ((rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
/*
* See corresponding comments in ip6_output.
* XXX: but is it possible that ip6_forward() sends a packet
* to a loopback interface? I don't think so, and thus
* I bark here. (jinmei@kame.net)
* XXX: it is common to route invalid packets to loopback.
* also, the codepath will be visited on use of ::1 in
* rthdr. (itojun)
*/
#if 1
if (0)
#else
if ((rt->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) == 0)
#endif
{
printf("ip6_forward: outgoing interface is loopback. "
"src %s, dst %s, nxt %d, rcvif %s, outif %s\n",
ip6_sprintf(ip6bufs, &ip6->ip6_src),
ip6_sprintf(ip6bufd, &ip6->ip6_dst),
ip6->ip6_nxt, if_name(m->m_pkthdr.rcvif),
if_name(rt->rt_ifp));
}
/* we can just use rcvif in forwarding. */
origifp = m->m_pkthdr.rcvif;
}
else
origifp = rt->rt_ifp;
/*
* clear embedded scope identifiers if necessary.
* in6_clearscope will touch the addresses only when necessary.
*/
in6_clearscope(&ip6->ip6_src);
in6_clearscope(&ip6->ip6_dst);
/* Jump over all PFIL processing if hooks are not active. */
if (!PFIL_HOOKED(&V_inet6_pfil_hook))
goto pass;
/* Run through list of hooks for output packets. */
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
if (error != 0)
goto senderr;
if (m == NULL)
goto freecopy;
ip6 = mtod(m, struct ip6_hdr *);
pass:
error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
if (error) {
in6_ifstat_inc(rt->rt_ifp, ifs6_out_discard);
V_ip6stat.ip6s_cantforward++;
} else {
V_ip6stat.ip6s_forward++;
in6_ifstat_inc(rt->rt_ifp, ifs6_out_forward);
if (type)
V_ip6stat.ip6s_redirectsent++;
else {
if (mcopy)
goto freecopy;
}
}
senderr:
if (mcopy == NULL)
goto out;
switch (error) {
case 0:
if (type == ND_REDIRECT) {
icmp6_redirect_output(mcopy, rt);
goto out;
}
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);
goto out;
freecopy:
m_freem(mcopy);
goto out;
bad:
m_freem(m);
out:
if (rt != NULL
#ifdef IPSEC
&& !ipsecrt
#endif
)
RTFREE(rt);
}

269
freebsd/netinet6/ip6_id.c Normal file
View File

@@ -0,0 +1,269 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* Copyright (C) 2003 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.
*
* $KAME: ip6_id.c,v 1.13 2003/09/16 09:11:19 itojun Exp $
*/
/*-
* Copyright 1998 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
* such a mathematical system to generate more random (yet non-repeating)
* ids to solve the resolver/named problem. But Niels designed the
* actual system based on the constraints.
*
* 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 Niels Provos.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR 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.
*
* $OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* seed = random (bits - 1) bit
* n = prime, g0 = generator to n,
* j = random so that gcd(j,n-1) == 1
* g = g0^j mod n will be a generator again.
*
* X[0] = random seed.
* X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator
* with a = 7^(even random) mod m,
* b = random with gcd(b,m) == 1
* m = constant and a maximal period of m-1.
*
* The transaction id is determined by:
* id[n] = seed xor (g^X[n] mod n)
*
* Effectivly the id is restricted to the lower (bits - 1) bits, thus
* yielding two different cycles by toggling the msb on and off.
* This avoids reuse issues caused by reseeding.
*/
#include <rtems/freebsd/sys/types.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/libkern.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffffU
#endif
struct randomtab {
const int ru_bits; /* resulting bits */
const long ru_out; /* Time after wich will be reseeded */
const u_int32_t ru_max; /* Uniq cycle, avoid blackjack prediction */
const u_int32_t ru_gen; /* Starting generator */
const u_int32_t ru_n; /* ru_n: prime, ru_n - 1: product of pfacts[] */
const u_int32_t ru_agen; /* determine ru_a as ru_agen^(2*rand) */
const u_int32_t ru_m; /* ru_m = 2^x*3^y */
const u_int32_t pfacts[4]; /* factors of ru_n */
u_int32_t ru_counter;
u_int32_t ru_msb;
u_int32_t ru_x;
u_int32_t ru_seed, ru_seed2;
u_int32_t ru_a, ru_b;
u_int32_t ru_g;
long ru_reseed;
};
static struct randomtab randomtab_32 = {
32, /* resulting bits */
180, /* Time after wich will be reseeded */
1000000000, /* Uniq cycle, avoid blackjack prediction */
2, /* Starting generator */
2147483629, /* RU_N-1 = 2^2*3^2*59652323 */
7, /* determine ru_a as RU_AGEN^(2*rand) */
1836660096, /* RU_M = 2^7*3^15 - don't change */
{ 2, 3, 59652323, 0 }, /* factors of ru_n */
};
static struct randomtab randomtab_20 = {
20, /* resulting bits */
180, /* Time after wich will be reseeded */
200000, /* Uniq cycle, avoid blackjack prediction */
2, /* Starting generator */
524269, /* RU_N-1 = 2^2*3^2*14563 */
7, /* determine ru_a as RU_AGEN^(2*rand) */
279936, /* RU_M = 2^7*3^7 - don't change */
{ 2, 3, 14563, 0 }, /* factors of ru_n */
};
static u_int32_t pmod(u_int32_t, u_int32_t, u_int32_t);
static void initid(struct randomtab *);
static u_int32_t randomid(struct randomtab *);
/*
* Do a fast modular exponation, returned value will be in the range
* of 0 - (mod-1)
*/
static u_int32_t
pmod(u_int32_t gen, u_int32_t expo, u_int32_t mod)
{
u_int64_t s, t, u;
s = 1;
t = gen;
u = expo;
while (u) {
if (u & 1)
s = (s * t) % mod;
u >>= 1;
t = (t * t) % mod;
}
return (s);
}
/*
* Initalizes the seed and chooses a suitable generator. Also toggles
* the msb flag. The msb flag is used to generate two distinct
* cycles of random numbers and thus avoiding reuse of ids.
*
* This function is called from id_randomid() when needed, an
* application does not have to worry about it.
*/
static void
initid(struct randomtab *p)
{
u_int32_t j, i;
int noprime = 1;
p->ru_x = arc4random() % p->ru_m;
/* (bits - 1) bits of random seed */
p->ru_seed = arc4random() & (~0U >> (32 - p->ru_bits + 1));
p->ru_seed2 = arc4random() & (~0U >> (32 - p->ru_bits + 1));
/* Determine the LCG we use */
p->ru_b = (arc4random() & (~0U >> (32 - p->ru_bits))) | 1;
p->ru_a = pmod(p->ru_agen,
(arc4random() & (~0U >> (32 - p->ru_bits))) & (~1U), p->ru_m);
while (p->ru_b % 3 == 0)
p->ru_b += 2;
j = arc4random() % p->ru_n;
/*
* Do a fast gcd(j, RU_N - 1), so we can find a j with
* gcd(j, RU_N - 1) == 1, giving a new generator for
* RU_GEN^j mod RU_N
*/
while (noprime) {
for (i = 0; p->pfacts[i] > 0; i++)
if (j % p->pfacts[i] == 0)
break;
if (p->pfacts[i] == 0)
noprime = 0;
else
j = (j + 1) % p->ru_n;
}
p->ru_g = pmod(p->ru_gen, j, p->ru_n);
p->ru_counter = 0;
p->ru_reseed = time_second + p->ru_out;
p->ru_msb = p->ru_msb ? 0 : (1U << (p->ru_bits - 1));
}
static u_int32_t
randomid(struct randomtab *p)
{
int i, n;
u_int32_t tmp;
if (p->ru_counter >= p->ru_max || time_second > p->ru_reseed)
initid(p);
tmp = arc4random();
/* Skip a random number of ids */
n = tmp & 0x3; tmp = tmp >> 2;
if (p->ru_counter + n >= p->ru_max)
initid(p);
for (i = 0; i <= n; i++) {
/* Linear Congruential Generator */
p->ru_x = (u_int32_t)((u_int64_t)p->ru_a * p->ru_x + p->ru_b) % p->ru_m;
}
p->ru_counter += i;
return (p->ru_seed ^ pmod(p->ru_g, p->ru_seed2 ^ p->ru_x, p->ru_n)) |
p->ru_msb;
}
u_int32_t
ip6_randomid(void)
{
return randomid(&randomtab_32);
}
u_int32_t
ip6_randomflowlabel(void)
{
return randomid(&randomtab_20) & 0xfffff;
}

1759
freebsd/netinet6/ip6_input.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,386 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
* 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.
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/local/opt_ipsec.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/kernel.h>
#include <rtems/freebsd/sys/mac.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/socketvar.h>
#include <rtems/freebsd/sys/sysctl.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/net/vnet.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_systm.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/ip.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet/in_pcb.h>
#include <rtems/freebsd/netinet/ip_var.h>
#include <rtems/freebsd/netinet/ip_options.h>
#include <rtems/freebsd/machine/in_cksum.h>
#ifdef IPSEC
#include <rtems/freebsd/netipsec/ipsec.h>
#include <rtems/freebsd/netipsec/ipsec6.h>
#include <rtems/freebsd/netipsec/xform.h>
#include <rtems/freebsd/netipsec/key.h>
#ifdef IPSEC_DEBUG
#include <rtems/freebsd/netipsec/key_debug.h>
#else
#define KEYDEBUG(lev,arg)
#endif
#endif /*IPSEC*/
#include <rtems/freebsd/netinet6/ip6_ipsec.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
extern struct protosw inet6sw[];
#ifdef INET6
#ifdef IPSEC
#ifdef IPSEC_FILTERTUNNEL
static VNET_DEFINE(int, ip6_ipsec6_filtertunnel) = 1;
#else
static VNET_DEFINE(int, ip6_ipsec6_filtertunnel) = 0;
#endif
#define V_ip6_ipsec6_filtertunnel VNET(ip6_ipsec6_filtertunnel)
SYSCTL_DECL(_net_inet6_ipsec6);
SYSCTL_VNET_INT(_net_inet6_ipsec6, OID_AUTO,
filtertunnel, CTLFLAG_RW, &VNET_NAME(ip6_ipsec6_filtertunnel), 0,
"If set filter packets from an IPsec tunnel.");
#endif /* IPSEC */
#endif /* INET6 */
/*
* Check if we have to jump over firewall processing for this packet.
* Called from ip_input().
* 1 = jump over firewall, 0 = packet goes through firewall.
*/
int
ip6_ipsec_filtertunnel(struct mbuf *m)
{
#if defined(IPSEC)
/*
* Bypass packet filtering for packets from a tunnel.
*/
if (!V_ip6_ipsec6_filtertunnel &&
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
return 1;
#endif
return 0;
}
/*
* Check if this packet has an active SA and needs to be dropped instead
* of forwarded.
* Called from ip_input().
* 1 = drop packet, 0 = forward packet.
*/
int
ip6_ipsec_fwd(struct mbuf *m)
{
#ifdef IPSEC
struct m_tag *mtag;
struct tdb_ident *tdbi;
struct secpolicy *sp;
int s, error;
mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
s = splnet();
if (mtag != NULL) {
tdbi = (struct tdb_ident *)(mtag + 1);
sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
} else {
sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
IP_FORWARDING, &error);
}
if (sp == NULL) { /* NB: can happen if error */
splx(s);
/*XXX error stat???*/
DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/
return 1;
}
/*
* Check security policy against packet attributes.
*/
error = ipsec_in_reject(sp, m);
KEY_FREESP(&sp);
splx(s);
if (error) {
V_ip6stat.ip6s_cantforward++;
return 1;
}
#endif /* IPSEC */
return 0;
}
/*
* Check if protocol type doesn't have a further header and do IPSEC
* decryption or reject right now. Protocols with further headers get
* their IPSEC treatment within the protocol specific processing.
* Called from ip_input().
* 1 = drop packet, 0 = continue processing packet.
*/
int
ip6_ipsec_input(struct mbuf *m, int nxt)
{
#ifdef IPSEC
struct m_tag *mtag;
struct tdb_ident *tdbi;
struct secpolicy *sp;
int s, error;
/*
* enforce IPsec policy checking if we are seeing last header.
* note that we do not visit this with protocols with pcb layer
* code - like udp/tcp/raw ip.
*/
if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
ipsec6_in_reject(m, NULL)) {
/*
* Check if the packet has already had IPsec processing
* done. If so, then just pass it along. This tag gets
* set during AH, ESP, etc. input handling, before the
* packet is returned to the ip input queue for delivery.
*/
mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
s = splnet();
if (mtag != NULL) {
tdbi = (struct tdb_ident *)(mtag + 1);
sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
} else {
sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
IP_FORWARDING, &error);
}
if (sp != NULL) {
/*
* Check security policy against packet attributes.
*/
error = ipsec_in_reject(sp, m);
KEY_FREESP(&sp);
} else {
/* XXX error stat??? */
error = EINVAL;
DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/
return 1;
}
splx(s);
if (error)
return 1;
}
#endif /* IPSEC */
return 0;
}
/*
* Called from ip6_output().
* 1 = drop packet, 0 = continue processing packet,
* -1 = packet was reinjected and stop processing packet
*/
int
ip6_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
struct ifnet **ifp, struct secpolicy **sp)
{
#ifdef IPSEC
struct tdb_ident *tdbi;
struct m_tag *mtag;
/* XXX int s; */
if (sp == NULL)
return 1;
mtag = m_tag_find(*m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
if (mtag != NULL) {
tdbi = (struct tdb_ident *)(mtag + 1);
*sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
if (*sp == NULL)
*error = -EINVAL; /* force silent drop */
m_tag_delete(*m, mtag);
} else {
*sp = ipsec4_checkpolicy(*m, IPSEC_DIR_OUTBOUND, *flags,
error, inp);
}
/*
* There are four return cases:
* sp != NULL apply IPsec policy
* sp == NULL, error == 0 no IPsec handling needed
* sp == NULL, error == -EINVAL discard packet w/o error
* sp == NULL, error != 0 discard packet, report error
*/
if (*sp != NULL) {
/* Loop detection, check if ipsec processing already done */
KASSERT((*sp)->req != NULL, ("ip_output: no ipsec request"));
for (mtag = m_tag_first(*m); mtag != NULL;
mtag = m_tag_next(*m, mtag)) {
if (mtag->m_tag_cookie != MTAG_ABI_COMPAT)
continue;
if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE &&
mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
continue;
/*
* Check if policy has an SA associated with it.
* This can happen when an SP has yet to acquire
* an SA; e.g. on first reference. If it occurs,
* then we let ipsec4_process_packet do its thing.
*/
if ((*sp)->req->sav == NULL)
break;
tdbi = (struct tdb_ident *)(mtag + 1);
if (tdbi->spi == (*sp)->req->sav->spi &&
tdbi->proto == (*sp)->req->sav->sah->saidx.proto &&
bcmp(&tdbi->dst, &(*sp)->req->sav->sah->saidx.dst,
sizeof (union sockaddr_union)) == 0) {
/*
* No IPsec processing is needed, free
* reference to SP.
*
* NB: null pointer to avoid free at
* done: below.
*/
KEY_FREESP(sp), *sp = NULL;
/* XXX splx(s); */
goto done;
}
}
/*
* Do delayed checksums now because we send before
* this is done in the normal processing path.
*/
if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
in_delayed_cksum(*m);
(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
/*
* Preserve KAME behaviour: ENOENT can be returned
* when an SA acquire is in progress. Don't propagate
* this to user-level; it confuses applications.
*
* XXX this will go away when the SADB is redone.
*/
if (*error == ENOENT)
*error = 0;
goto do_ipsec;
} else { /* sp == NULL */
if (*error != 0) {
/*
* Hack: -EINVAL is used to signal that a packet
* should be silently discarded. This is typically
* because we asked key management for an SA and
* it was delayed (e.g. kicked up to IKE).
*/
if (*error == -EINVAL)
*error = 0;
goto bad;
} else {
/* No IPsec processing for this packet. */
}
}
done:
return 0;
do_ipsec:
return -1;
bad:
return 1;
#endif /* IPSEC */
return 0;
}
#if 0
/*
* Compute the MTU for a forwarded packet that gets IPSEC encapsulated.
* Called from ip_forward().
* Returns MTU suggestion for ICMP needfrag reply.
*/
int
ip6_ipsec_mtu(struct mbuf *m)
{
int mtu = 0;
/*
* If the packet is routed over IPsec tunnel, tell the
* originator the tunnel MTU.
* tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
* XXX quickhack!!!
*/
#ifdef IPSEC
struct secpolicy *sp = NULL;
int ipsecerror;
int ipsechdr;
struct route *ro;
sp = ipsec_getpolicybyaddr(m,
IPSEC_DIR_OUTBOUND,
IP_FORWARDING,
&ipsecerror);
if (sp != NULL) {
/* count IPsec header size */
ipsechdr = ipsec_hdrsiz(m, IPSEC_DIR_OUTBOUND, NULL);
/*
* find the correct route for outer IPv4
* header, compute tunnel MTU.
*/
if (sp->req != NULL &&
sp->req->sav != NULL &&
sp->req->sav->sah != NULL) {
ro = &sp->req->sav->sah->route_cache.sa_route;
if (ro->ro_rt && ro->ro_rt->rt_ifp) {
mtu =
ro->ro_rt->rt_rmx.rmx_mtu ?
ro->ro_rt->rt_rmx.rmx_mtu :
ro->ro_rt->rt_ifp->if_mtu;
mtu -= ipsechdr;
}
}
KEY_FREESP(&sp);
}
#endif /* IPSEC */
/* XXX else case missing. */
return mtu;
}
#endif

View File

@@ -0,0 +1,43 @@
/*-
* 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.
* 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.
*
* $FreeBSD$
*/
#ifndef _NETINET_IP6_IPSEC_HH_
#define _NETINET_IP6_IPSEC_HH_
int ip6_ipsec_filtertunnel(struct mbuf *);
int ip6_ipsec_fwd(struct mbuf *);
int ip6_ipsec_input(struct mbuf *, int);
int ip6_ipsec_output(struct mbuf **, struct inpcb *, int *, int *,
struct ifnet **, struct secpolicy **sp);
#if 0
int ip6_ipsec_mtu(struct mbuf *);
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
/*-
* 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.
*
* $KAME: ip6_mroute.h,v 1.19 2001/06/14 06:12:55 suz Exp $
* $FreeBSD$
*/
/* BSDI ip_mroute.h,v 2.5 1996/10/11 16:01:48 pjd Exp */
/*
* Definitions for IP multicast forwarding.
*
* Written by David Waitzman, BBN Labs, August 1988.
* Modified by Steve Deering, Stanford, February 1989.
* Modified by Ajit Thyagarajan, PARC, August 1993.
* Modified by Ajit Thyagarajan, PARC, August 1994.
* Modified by Ahmed Helmy, USC, September 1996.
*
* MROUTING Revision: 1.2
*/
#ifndef _NETINET6_IP6_MROUTE_HH_
#define _NETINET6_IP6_MROUTE_HH_
/*
* Multicast Routing set/getsockopt commands.
*/
#ifdef _KERNEL
#define MRT6_OINIT 100 /* initialize forwarder (omrt6msg) */
#endif
#define MRT6_DONE 101 /* shut down forwarder */
#define MRT6_ADD_MIF 102 /* add multicast interface */
#define MRT6_DEL_MIF 103 /* delete multicast interface */
#define MRT6_ADD_MFC 104 /* insert forwarding cache entry */
#define MRT6_DEL_MFC 105 /* delete forwarding cache entry */
#define MRT6_PIM 107 /* enable pim code */
#define MRT6_INIT 108 /* initialize forwarder (mrt6msg) */
#if BSD >= 199103
#define GET_TIME(t) microtime(&t)
#elif defined(sun)
#define GET_TIME(t) uniqtime(&t)
#else
#define GET_TIME(t) ((t) = time)
#endif
/*
* Types and macros for handling bitmaps with one bit per multicast interface.
*/
typedef u_short mifi_t; /* type of a mif index */
#define MAXMIFS 64
#ifndef IF_SETSIZE
#define IF_SETSIZE 256
#endif
typedef u_int32_t if_mask;
#define NIFBITS (sizeof(if_mask) * NBBY) /* bits per mask */
#ifndef howmany
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
#endif
typedef struct if_set {
if_mask ifs_bits[howmany(IF_SETSIZE, NIFBITS)];
} if_set;
#define IF_SET(n, p) ((p)->ifs_bits[(n)/NIFBITS] |= (1 << ((n) % NIFBITS)))
#define IF_CLR(n, p) ((p)->ifs_bits[(n)/NIFBITS] &= ~(1 << ((n) % NIFBITS)))
#define IF_ISSET(n, p) ((p)->ifs_bits[(n)/NIFBITS] & (1 << ((n) % NIFBITS)))
#define IF_COPY(f, t) bcopy(f, t, sizeof(*(f)))
#define IF_ZERO(p) bzero(p, sizeof(*(p)))
/*
* Argument structure for MRT6_ADD_IF.
*/
struct mif6ctl {
mifi_t mif6c_mifi; /* the index of the mif to be added */
u_char mif6c_flags; /* MIFF_ flags defined below */
u_short mif6c_pifi; /* the index of the physical IF */
};
#define MIFF_REGISTER 0x1 /* mif represents a register end-point */
/*
* Argument structure for MRT6_ADD_MFC and MRT6_DEL_MFC
*/
struct mf6cctl {
struct sockaddr_in6 mf6cc_origin; /* IPv6 origin of mcasts */
struct sockaddr_in6 mf6cc_mcastgrp; /* multicast group associated */
mifi_t mf6cc_parent; /* incoming ifindex */
struct if_set mf6cc_ifset; /* set of forwarding ifs */
};
/*
* The kernel's multicast routing statistics.
*/
struct mrt6stat {
u_quad_t mrt6s_mfc_lookups; /* # forw. cache hash table hits */
u_quad_t mrt6s_mfc_misses; /* # forw. cache hash table misses */
u_quad_t mrt6s_upcalls; /* # calls to multicast routing daemon */
u_quad_t mrt6s_no_route; /* no route for packet's origin */
u_quad_t mrt6s_bad_tunnel; /* malformed tunnel options */
u_quad_t mrt6s_cant_tunnel; /* no room for tunnel options */
u_quad_t mrt6s_wrong_if; /* arrived on wrong interface */
u_quad_t mrt6s_upq_ovflw; /* upcall Q overflow */
u_quad_t mrt6s_cache_cleanups; /* # entries with no upcalls */
u_quad_t mrt6s_drop_sel; /* pkts dropped selectively */
u_quad_t mrt6s_q_overflow; /* pkts dropped - Q overflow */
u_quad_t mrt6s_pkt2large; /* pkts dropped - size > BKT SIZE */
u_quad_t mrt6s_upq_sockfull; /* upcalls dropped - socket full */
};
#ifdef MRT6_OINIT
/*
* Struct used to communicate from kernel to multicast router
* note the convenient similarity to an IPv6 header.
* XXX old version, superseded by mrt6msg.
*/
struct omrt6msg {
u_long unused1;
u_char im6_msgtype; /* what type of message */
#if 0
#define MRT6MSG_NOCACHE 1
#define MRT6MSG_WRONGMIF 2
#define MRT6MSG_WHOLEPKT 3 /* used for user level encap*/
#endif
u_char im6_mbz; /* must be zero */
u_char im6_mif; /* mif rec'd on */
u_char unused2;
struct in6_addr im6_src, im6_dst;
};
#endif
/*
* Structure used to communicate from kernel to multicast router.
* We'll overlay the structure onto an MLD header (not an IPv6 header
* like igmpmsg{} used for IPv4 implementation). This is because this
* structure will be passed via an IPv6 raw socket, on which an application
* will only receive the payload i.e. the data after the IPv6 header and all
* the extension headers. (see Section 3 of RFC3542)
*/
struct mrt6msg {
#define MRT6MSG_NOCACHE 1
#define MRT6MSG_WRONGMIF 2
#define MRT6MSG_WHOLEPKT 3 /* used for user level encap*/
u_char im6_mbz; /* must be zero */
u_char im6_msgtype; /* what type of message */
u_int16_t im6_mif; /* mif rec'd on */
u_int32_t im6_pad; /* padding for 64bit arch */
struct in6_addr im6_src, im6_dst;
};
/*
* Argument structure used by multicast routing daemon to get src-grp
* packet counts
*/
struct sioc_sg_req6 {
struct sockaddr_in6 src;
struct sockaddr_in6 grp;
u_quad_t pktcnt;
u_quad_t bytecnt;
u_quad_t wrong_if;
};
/*
* Argument structure used by mrouted to get mif pkt counts
*/
struct sioc_mif_req6 {
mifi_t mifi; /* mif number */
u_quad_t icount; /* Input packet count on mif */
u_quad_t ocount; /* Output packet count on mif */
u_quad_t ibytes; /* Input byte count on mif */
u_quad_t obytes; /* Output byte count on mif */
};
#if defined(_KERNEL) || defined(KERNEL)
/*
* The kernel's multicast-interface structure.
*/
struct mif6 {
u_char m6_flags; /* MIFF_ flags defined above */
u_int m6_rate_limit; /* max rate */
struct in6_addr m6_lcl_addr; /* local interface address */
struct ifnet *m6_ifp; /* pointer to interface */
u_quad_t m6_pkt_in; /* # pkts in on interface */
u_quad_t m6_pkt_out; /* # pkts out on interface */
u_quad_t m6_bytes_in; /* # bytes in on interface */
u_quad_t m6_bytes_out; /* # bytes out on interface */
struct route_in6 m6_route; /* cached route */
#ifdef notyet
u_int m6_rsvp_on; /* RSVP listening on this vif */
struct socket *m6_rsvpd; /* RSVP daemon socket */
#endif
};
/*
* The kernel's multicast forwarding cache entry structure
*/
struct mf6c {
struct sockaddr_in6 mf6c_origin; /* IPv6 origin of mcasts */
struct sockaddr_in6 mf6c_mcastgrp; /* multicast group associated*/
mifi_t mf6c_parent; /* incoming IF */
struct if_set mf6c_ifset; /* set of outgoing IFs */
u_quad_t mf6c_pkt_cnt; /* pkt count for src-grp */
u_quad_t mf6c_byte_cnt; /* byte count for src-grp */
u_quad_t mf6c_wrong_if; /* wrong if for src-grp */
int mf6c_expire; /* time to clean entry up */
struct timeval mf6c_last_assert; /* last time I sent an assert*/
struct rtdetq *mf6c_stall; /* pkts waiting for route */
struct mf6c *mf6c_next; /* hash table linkage */
};
#define MF6C_INCOMPLETE_PARENT ((mifi_t)-1)
/*
* Argument structure used for pkt info. while upcall is made
*/
#ifndef _NETINET_IP_MROUTE_HH_
struct rtdetq { /* XXX: rtdetq is also defined in ip_mroute.h */
struct mbuf *m; /* A copy of the packet */
struct ifnet *ifp; /* Interface pkt came in on */
#ifdef UPCALL_TIMING
struct timeval t; /* Timestamp */
#endif /* UPCALL_TIMING */
struct rtdetq *next;
};
#endif /* _NETINET_IP_MROUTE_HH_ */
#define MF6CTBLSIZ 256
#if (MF6CTBLSIZ & (MF6CTBLSIZ - 1)) == 0 /* from sys:route.h */
#define MF6CHASHMOD(h) ((h) & (MF6CTBLSIZ - 1))
#else
#define MF6CHASHMOD(h) ((h) % MF6CTBLSIZ)
#endif
#define MAX_UPQ6 4 /* max. no of pkts in upcall Q */
extern int (*ip6_mrouter_set)(struct socket *so, struct sockopt *sopt);
extern int (*ip6_mrouter_get)(struct socket *so, struct sockopt *sopt);
extern int (*ip6_mrouter_done)(void);
extern int (*mrt6_ioctl)(u_long, caddr_t);
#endif /* _KERNEL */
#endif /* !_NETINET6_IP6_MROUTE_HH_ */

File diff suppressed because it is too large Load Diff

444
freebsd/netinet6/ip6_var.h Normal file
View File

@@ -0,0 +1,444 @@
/*-
* 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.
*
* $KAME: ip6_var.h,v 1.62 2001/05/03 14:51:48 itojun 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.
* 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
* $FreeBSD$
*/
#ifndef _NETINET6_IP6_VAR_HH_
#define _NETINET6_IP6_VAR_HH_
/*
* IP6 reassembly queue structure. Each fragment
* being reassembled is attached to one of these structures.
*/
struct ip6q {
struct ip6asfrag *ip6q_down;
struct ip6asfrag *ip6q_up;
u_int32_t ip6q_ident;
u_int8_t ip6q_nxt;
u_int8_t ip6q_ecn;
u_int8_t ip6q_ttl;
struct in6_addr ip6q_src, ip6q_dst;
struct ip6q *ip6q_next;
struct ip6q *ip6q_prev;
int ip6q_unfrglen; /* len of unfragmentable part */
#ifdef notyet
u_char *ip6q_nxtp;
#endif
int ip6q_nfrag; /* # of fragments */
struct label *ip6q_label;
};
struct ip6asfrag {
struct ip6asfrag *ip6af_down;
struct ip6asfrag *ip6af_up;
struct mbuf *ip6af_m;
int ip6af_offset; /* offset in ip6af_m to next header */
int ip6af_frglen; /* fragmentable part length */
int ip6af_off; /* fragment offset */
u_int16_t ip6af_mff; /* more fragment bit in frag off */
};
#define IP6_REASS_MBUF(ip6af) (*(struct mbuf **)&((ip6af)->ip6af_m))
/*
* Structure attached to inpcb.in6p_moptions and
* passed to ip6_output when IPv6 multicast options are in use.
* This structure is lazy-allocated.
*/
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 */
u_short im6o_num_memberships; /* no. memberships this socket */
u_short im6o_max_memberships; /* max memberships this socket */
struct in6_multi **im6o_membership; /* group memberships */
struct in6_mfilter *im6o_mfilters; /* source filters */
};
/*
* 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
/* Nexthop related info */
struct ip6po_nhinfo {
struct sockaddr *ip6po_nhi_nexthop;
struct route_in6 ip6po_nhi_route; /* Route to the nexthop */
};
#define ip6po_nexthop ip6po_nhinfo.ip6po_nhi_nexthop
#define ip6po_nextroute ip6po_nhinfo.ip6po_nhi_route
struct ip6_pktopts {
struct mbuf *ip6po_m; /* Pointer to mbuf storing the data */
int ip6po_hlim; /* Hoplimit for outgoing packets */
/* Outgoing IF/address information */
struct in6_pktinfo *ip6po_pktinfo;
/* Next-hop address information */
struct ip6po_nhinfo ip6po_nhinfo;
struct ip6_hbh *ip6po_hbh; /* Hop-by-Hop options header */
/* Destination options header (before a routing header) */
struct ip6_dest *ip6po_dest1;
/* Routing header related info. */
struct ip6po_rhinfo ip6po_rhinfo;
/* Destination options header (after a routing header) */
struct ip6_dest *ip6po_dest2;
int ip6po_tclass; /* traffic class */
int ip6po_minmtu; /* fragment vs PMTU discovery policy */
#define IP6PO_MINMTU_MCASTONLY -1 /* default; send at min MTU for multicast*/
#define IP6PO_MINMTU_DISABLE 0 /* always perform pmtu disc */
#define IP6PO_MINMTU_ALL 1 /* always send at min MTU */
int ip6po_prefer_tempaddr; /* whether temporary addresses are
preferred as source address */
#define IP6PO_TEMPADDR_SYSTEM -1 /* follow the system default */
#define IP6PO_TEMPADDR_NOTPREFER 0 /* not prefer temporary address */
#define IP6PO_TEMPADDR_PREFER 1 /* prefer temporary address */
int ip6po_flags;
#if 0 /* parameters in this block is obsolete. do not reuse the values. */
#define IP6PO_REACHCONF 0x01 /* upper-layer reachability confirmation. */
#define IP6PO_MINMTU 0x02 /* use minimum MTU (IPV6_USE_MIN_MTU) */
#endif
#define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */
#define IP6PO_USECOA 0x08 /* use care of address */
};
/*
* Control options for incoming packets
*/
struct ip6stat {
u_quad_t ip6s_total; /* total packets received */
u_quad_t ip6s_tooshort; /* packet too short */
u_quad_t ip6s_toosmall; /* not enough data */
u_quad_t ip6s_fragments; /* fragments received */
u_quad_t ip6s_fragdropped; /* frags dropped(dups, out of space) */
u_quad_t ip6s_fragtimeout; /* fragments timed out */
u_quad_t ip6s_fragoverflow; /* fragments that exceeded limit */
u_quad_t ip6s_forward; /* packets forwarded */
u_quad_t ip6s_cantforward; /* packets rcvd for unreachable dest */
u_quad_t ip6s_redirectsent; /* packets forwarded on same net */
u_quad_t ip6s_delivered; /* datagrams delivered to upper level*/
u_quad_t ip6s_localout; /* total ip packets generated here */
u_quad_t ip6s_odropped; /* lost packets due to nobufs, etc. */
u_quad_t ip6s_reassembled; /* total packets reassembled ok */
u_quad_t ip6s_fragmented; /* datagrams successfully fragmented */
u_quad_t ip6s_ofragments; /* output fragments created */
u_quad_t ip6s_cantfrag; /* don't fragment flag was set, etc. */
u_quad_t ip6s_badoptions; /* error in option processing */
u_quad_t ip6s_noroute; /* packets discarded due to no route */
u_quad_t ip6s_badvers; /* ip6 version != 6 */
u_quad_t ip6s_rawout; /* total raw ip packets generated */
u_quad_t ip6s_badscope; /* scope error */
u_quad_t ip6s_notmember; /* don't join this multicast group */
u_quad_t ip6s_nxthist[256]; /* next header history */
u_quad_t ip6s_m1; /* one mbuf */
u_quad_t ip6s_m2m[32]; /* two or more mbuf */
u_quad_t ip6s_mext1; /* one ext mbuf */
u_quad_t ip6s_mext2m; /* two or more ext mbuf */
u_quad_t ip6s_exthdrtoolong; /* ext hdr are not continuous */
u_quad_t ip6s_nogif; /* no match gif found */
u_quad_t ip6s_toomanyhdr; /* discarded due to too many headers */
/*
* statistics for improvement of the source address selection
* algorithm:
* XXX: hardcoded 16 = # of ip6 multicast scope types + 1
*/
/* number of times that address selection fails */
u_quad_t ip6s_sources_none;
/* number of times that an address on the outgoing I/F is chosen */
u_quad_t ip6s_sources_sameif[16];
/* number of times that an address on a non-outgoing I/F is chosen */
u_quad_t ip6s_sources_otherif[16];
/*
* number of times that an address that has the same scope
* from the destination is chosen.
*/
u_quad_t ip6s_sources_samescope[16];
/*
* number of times that an address that has a different scope
* from the destination is chosen.
*/
u_quad_t ip6s_sources_otherscope[16];
/* number of times that a deprecated address is chosen */
u_quad_t ip6s_sources_deprecated[16];
/* number of times that each rule of source selection is applied. */
u_quad_t ip6s_sources_rule[16];
};
#ifdef _KERNEL
#define IP6STAT_ADD(name, val) V_ip6stat.name += (val)
#define IP6STAT_SUB(name, val) V_ip6stat.name -= (val)
#define IP6STAT_INC(name) IP6STAT_ADD(name, 1)
#define IP6STAT_DEC(name) IP6STAT_SUB(name, 1)
#endif
#ifdef _KERNEL
/*
* IPv6 onion peeling state.
* it will be initialized when we come into ip6_input().
* XXX do not make it a kitchen sink!
*/
struct ip6aux {
u_int32_t ip6a_flags;
#define IP6A_SWAP 0x01 /* swapped home/care-of on packet */
#define IP6A_HASEEN 0x02 /* HA was present */
#define IP6A_BRUID 0x04 /* BR Unique Identifier was present */
#define IP6A_RTALERTSEEN 0x08 /* rtalert present */
/* ip6.ip6_src */
struct in6_addr ip6a_careof; /* care-of address of the peer */
struct in6_addr ip6a_home; /* home address of the peer */
u_int16_t ip6a_bruid; /* BR unique identifier */
/* ip6.ip6_dst */
struct in6_ifaddr *ip6a_dstia6; /* my ifaddr that matches ip6_dst */
/* rtalert */
u_int16_t ip6a_rtalert; /* rtalert option value */
/*
* decapsulation history will be here.
* with IPsec it may not be accurate.
*/
};
#endif
#ifdef _KERNEL
/* flags passed to ip6_output as last parameter */
#define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */
#define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */
#define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */
#ifdef __NO_STRICT_ALIGNMENT
#define IP6_HDR_ALIGNED_P(ip) 1
#else
#define IP6_HDR_ALIGNED_P(ip) ((((intptr_t) (ip)) & 3) == 0)
#endif
VNET_DECLARE(struct ip6stat, ip6stat); /* statistics */
VNET_DECLARE(int, ip6_defhlim); /* default hop limit */
VNET_DECLARE(int, ip6_defmcasthlim); /* default multicast hop limit */
VNET_DECLARE(int, ip6_forwarding); /* act as router? */
VNET_DECLARE(int, ip6_use_deprecated); /* allow deprecated addr as source */
VNET_DECLARE(int, ip6_rr_prune); /* router renumbering prefix
* walk list every 5 sec. */
VNET_DECLARE(int, ip6_mcast_pmtu); /* enable pMTU discovery for multicast? */
VNET_DECLARE(int, ip6_v6only);
#define V_ip6stat VNET(ip6stat)
#define V_ip6_defhlim VNET(ip6_defhlim)
#define V_ip6_defmcasthlim VNET(ip6_defmcasthlim)
#define V_ip6_forwarding VNET(ip6_forwarding)
#define V_ip6_use_deprecated VNET(ip6_use_deprecated)
#define V_ip6_rr_prune VNET(ip6_rr_prune)
#define V_ip6_mcast_pmtu VNET(ip6_mcast_pmtu)
#define V_ip6_v6only VNET(ip6_v6only)
VNET_DECLARE(struct socket *, ip6_mrouter); /* multicast routing daemon */
VNET_DECLARE(int, ip6_sendredirects); /* send IP redirects when forwarding? */
VNET_DECLARE(int, ip6_maxfragpackets); /* Maximum packets in reassembly
* queue */
VNET_DECLARE(int, ip6_maxfrags); /* Maximum fragments in reassembly
* queue */
VNET_DECLARE(int, ip6_accept_rtadv); /* Acts as a host not a router */
VNET_DECLARE(int, ip6_keepfaith); /* Firewall Aided Internet Translator */
VNET_DECLARE(int, ip6_log_interval);
VNET_DECLARE(time_t, ip6_log_time);
VNET_DECLARE(int, ip6_hdrnestlimit); /* upper limit of # of extension
* headers */
VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */
#define V_ip6_mrouter VNET(ip6_mrouter)
#define V_ip6_sendredirects VNET(ip6_sendredirects)
#define V_ip6_maxfragpackets VNET(ip6_maxfragpackets)
#define V_ip6_maxfrags VNET(ip6_maxfrags)
#define V_ip6_accept_rtadv VNET(ip6_accept_rtadv)
#define V_ip6_keepfaith VNET(ip6_keepfaith)
#define V_ip6_log_interval VNET(ip6_log_interval)
#define V_ip6_log_time VNET(ip6_log_time)
#define V_ip6_hdrnestlimit VNET(ip6_hdrnestlimit)
#define V_ip6_dad_count VNET(ip6_dad_count)
VNET_DECLARE(int, ip6_auto_flowlabel);
VNET_DECLARE(int, ip6_auto_linklocal);
#define V_ip6_auto_flowlabel VNET(ip6_auto_flowlabel)
#define V_ip6_auto_linklocal VNET(ip6_auto_linklocal)
VNET_DECLARE(int, ip6_use_tempaddr); /* Whether to use temporary addresses */
VNET_DECLARE(int, ip6_prefer_tempaddr); /* Whether to prefer temporary
* addresses in the source address
* selection */
#define V_ip6_use_tempaddr VNET(ip6_use_tempaddr)
#define V_ip6_prefer_tempaddr VNET(ip6_prefer_tempaddr)
VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope
* zone when unspecified */
#define V_ip6_use_defzone VNET(ip6_use_defzone)
VNET_DECLARE (struct pfil_head, inet6_pfil_hook); /* packet filter hooks */
#define V_inet6_pfil_hook VNET(inet6_pfil_hook)
#ifdef IPSTEALTH
VNET_DECLARE(int, ip6stealth);
#define V_ip6stealth VNET(ip6stealth)
#endif
extern struct pr_usrreqs rip6_usrreqs;
struct sockopt;
struct inpcb;
int icmp6_ctloutput __P((struct socket *, struct sockopt *sopt));
struct in6_ifaddr;
void ip6_init __P((void));
#ifdef VIMAGE
void ip6_destroy __P((void));
#endif
int ip6proto_register(short);
int ip6proto_unregister(short);
void ip6_input __P((struct mbuf *));
struct in6_ifaddr *ip6_getdstifaddr __P((struct mbuf *));
void ip6_freepcbopts __P((struct ip6_pktopts *));
int ip6_unknown_opt __P((u_int8_t *, struct mbuf *, int));
char * ip6_get_prevhdr __P((struct mbuf *, int));
int ip6_nexthdr __P((struct mbuf *, int, int, int *));
int ip6_lasthdr __P((struct mbuf *, int, int, int *));
struct ip6aux *ip6_addaux __P((struct mbuf *));
struct ip6aux *ip6_findaux __P((struct mbuf *));
void ip6_delaux __P((struct mbuf *));
extern int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *,
struct mbuf *);
int ip6_process_hopopts __P((struct mbuf *, u_int8_t *, int, u_int32_t *,
u_int32_t *));
struct mbuf **ip6_savecontrol_v4(struct inpcb *, struct mbuf *,
struct mbuf **, int *);
void ip6_savecontrol __P((struct inpcb *, struct mbuf *, struct mbuf **));
void ip6_notify_pmtu __P((struct inpcb *, struct sockaddr_in6 *,
u_int32_t *));
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 **,
struct inpcb *));
int ip6_ctloutput __P((struct socket *, struct sockopt *));
int ip6_raw_ctloutput __P((struct socket *, struct sockopt *));
void ip6_initpktopts __P((struct ip6_pktopts *));
int ip6_setpktopts __P((struct mbuf *, struct ip6_pktopts *,
struct ip6_pktopts *, struct ucred *, int));
void ip6_clearpktopts __P((struct ip6_pktopts *, int));
struct ip6_pktopts *ip6_copypktopts __P((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 **, int *, int));
void rip6_ctlinput __P((int, struct sockaddr *, void *));
int rip6_ctloutput __P((struct socket *, struct sockopt *));
int rip6_output __P((struct mbuf *, ...));
int rip6_usrreq __P((struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *, struct thread *));
int dest6_input __P((struct mbuf **, int *, int));
int none_input __P((struct mbuf **, int *, int));
int in6_selectsrc(struct sockaddr_in6 *, struct ip6_pktopts *,
struct inpcb *inp, struct route_in6 *, struct ucred *cred,
struct ifnet **, struct in6_addr *);
int in6_selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
struct rtentry **));
u_int32_t ip6_randomid __P((void));
u_int32_t ip6_randomflowlabel __P((void));
#endif /* _KERNEL */
#endif /* !_NETINET6_IP6_VAR_HH_ */

View File

@@ -0,0 +1,148 @@
/*-
* 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.
*
* $KAME: ip6protosw.h,v 1.25 2001/09/26 06:13:03 keiichi 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.
* 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
* BSDI protosw.h,v 2.3 1996/10/11 16:02:40 pjd Exp
* $FreeBSD$
*/
#ifndef _NETINET6_IP6PROTOSW_HH_
#define _NETINET6_IP6PROTOSW_HH_
/*
* Protocol switch table for IPv6.
* All other definitions should refer to sys/protosw.h
*/
struct mbuf;
struct sockaddr;
struct socket;
struct domain;
struct thread;
struct ip6_hdr;
struct icmp6_hdr;
struct in6_addr;
struct pr_usrreqs;
/*
* argument type for the last arg of pr_ctlinput().
* should be consulted only with AF_INET6 family.
*
* IPv6 ICMP IPv6 [exthdrs] finalhdr payload
* ^ ^ ^ ^
* | | ip6c_ip6 ip6c_off
* | ip6c_icmp6
* ip6c_m
*
* ip6c_finaldst usually points to ip6c_ip6->ip6_dst. if the original
* (internal) packet carries a routing header, it may point the final
* dstination address in the routing header.
*
* ip6c_src: ip6c_ip6->ip6_src + scope info + flowlabel in ip6c_ip6
* (beware of flowlabel, if you try to compare it against others)
* ip6c_dst: ip6c_finaldst + scope info
*/
struct ip6ctlparam {
struct mbuf *ip6c_m; /* start of mbuf chain */
struct icmp6_hdr *ip6c_icmp6; /* icmp6 header of target packet */
struct ip6_hdr *ip6c_ip6; /* ip6 header of target packet */
int ip6c_off; /* offset of the target proto header */
struct sockaddr_in6 *ip6c_src; /* srcaddr w/ additional info */
struct sockaddr_in6 *ip6c_dst; /* (final) dstaddr w/ additional info */
struct in6_addr *ip6c_finaldst; /* final destination address */
void *ip6c_cmdarg; /* control command dependent data */
u_int8_t ip6c_nxt; /* final next header field */
};
struct ip6protosw {
short 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 *));
/* utility hooks */
void (*pr_init) /* initialization hook */
__P((void));
void (*pr_destroy) /* cleanup 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() */
};
#ifdef _KERNEL
extern struct ip6protosw inet6sw[];
#endif
#endif /* !_NETINET6_IP6PROTOSW_HH_ */

3311
freebsd/netinet6/mld6.c Normal file

File diff suppressed because it is too large Load Diff

112
freebsd/netinet6/mld6.h Normal file
View File

@@ -0,0 +1,112 @@
/*-
* Copyright (c) 2009 Bruce Simpson.
*
* 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. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _NETINET6_MLD6_HH_
#define _NETINET6_MLD6_HH_
/*
* Multicast Listener Discovery (MLD) definitions.
*/
/* Minimum length of any MLD protocol message. */
#define MLD_MINLEN sizeof(struct icmp6_hdr)
/*
* MLD v2 query format.
* See <netinet/icmp6.h> for struct mld_hdr
* (MLDv1 query and host report format).
*/
struct mldv2_query {
struct icmp6_hdr mld_icmp6_hdr; /* ICMPv6 header */
struct in6_addr mld_addr; /* address being queried */
uint8_t mld_misc; /* reserved/suppress/robustness */
uint8_t mld_qqi; /* querier's query interval */
uint16_t mld_numsrc; /* number of sources */
/* followed by 1..numsrc source addresses */
} __packed;
#define MLD_V2_QUERY_MINLEN sizeof(struct mldv2_query)
#define MLD_MRC_EXP(x) ((ntohs((x)) >> 12) & 0x0007)
#define MLD_MRC_MANT(x) (ntohs((x)) & 0x0fff)
#define MLD_QQIC_EXP(x) (((x) >> 4) & 0x07)
#define MLD_QQIC_MANT(x) ((x) & 0x0f)
#define MLD_QRESV(x) (((x) >> 4) & 0x0f)
#define MLD_SFLAG(x) (((x) >> 3) & 0x01)
#define MLD_QRV(x) ((x) & 0x07)
/*
* MLDv2 host membership report header.
* mld_type: MLDV2_LISTENER_REPORT
*/
struct mldv2_report {
struct icmp6_hdr mld_icmp6_hdr;
/* followed by 1..numgrps records */
} __packed;
/* overlaid on struct icmp6_hdr. */
#define mld_numrecs mld_icmp6_hdr.icmp6_data16[1]
struct mldv2_record {
uint8_t mr_type; /* record type */
uint8_t mr_datalen; /* length of auxiliary data */
uint16_t mr_numsrc; /* number of sources */
struct in6_addr mr_addr; /* address being reported */
/* followed by 1..numsrc source addresses */
} __packed;
#define MLD_V2_REPORT_MAXRECS 65535
/*
* MLDv2 report modes.
*/
#define MLD_DO_NOTHING 0 /* don't send a record */
#define MLD_MODE_IS_INCLUDE 1 /* MODE_IN */
#define MLD_MODE_IS_EXCLUDE 2 /* MODE_EX */
#define MLD_CHANGE_TO_INCLUDE_MODE 3 /* TO_IN */
#define MLD_CHANGE_TO_EXCLUDE_MODE 4 /* TO_EX */
#define MLD_ALLOW_NEW_SOURCES 5 /* ALLOW_NEW */
#define MLD_BLOCK_OLD_SOURCES 6 /* BLOCK_OLD */
/*
* MLDv2 query types.
*/
#define MLD_V2_GENERAL_QUERY 1
#define MLD_V2_GROUP_QUERY 2
#define MLD_V2_GROUP_SOURCE_QUERY 3
/*
* Maximum report interval for MLDv1 host membership reports.
*/
#define MLD_V1_MAX_RI 10
/*
* MLD_TIMER_SCALE denotes that the MLD code field specifies
* time in milliseconds.
*/
#define MLD_TIMER_SCALE 1000
#endif /* _NETINET6_MLD6_HH_ */

164
freebsd/netinet6/mld6_var.h Normal file
View File

@@ -0,0 +1,164 @@
/*-
* Copyright (c) 2009 Bruce Simpson.
*
* 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. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _NETINET6_MLD6_VAR_HH_
#define _NETINET6_MLD6_VAR_HH_
/*
* Multicast Listener Discovery (MLD)
* implementation-specific definitions.
*/
#ifdef _KERNEL
/*
* Per-link MLD state.
*/
struct mld_ifinfo {
LIST_ENTRY(mld_ifinfo) mli_link;
struct ifnet *mli_ifp; /* interface this instance belongs to */
uint32_t mli_version; /* MLDv1 Host Compatibility Mode */
uint32_t mli_v1_timer; /* MLDv1 Querier Present timer (s) */
uint32_t mli_v2_timer; /* MLDv2 General Query (interface) timer (s)*/
uint32_t mli_flags; /* MLD per-interface flags */
uint32_t mli_rv; /* MLDv2 Robustness Variable */
uint32_t mli_qi; /* MLDv2 Query Interval (s) */
uint32_t mli_qri; /* MLDv2 Query Response Interval (s) */
uint32_t mli_uri; /* MLDv2 Unsolicited Report Interval (s) */
SLIST_HEAD(,in6_multi) mli_relinmhead; /* released groups */
struct ifqueue mli_gq; /* queue of general query responses */
};
#define MLIF_SILENT 0x00000001 /* Do not use MLD on this ifp */
#define MLIF_USEALLOW 0x00000002 /* Use ALLOW/BLOCK for joins/leaves */
#define MLD_RANDOM_DELAY(X) (arc4random() % (X) + 1)
#define MLD_MAX_STATE_CHANGES 24 /* Max pending changes per group */
/*
* MLD per-group states.
*/
#define MLD_NOT_MEMBER 0 /* Can garbage collect group */
#define MLD_SILENT_MEMBER 1 /* Do not perform MLD for group */
#define MLD_REPORTING_MEMBER 2 /* MLDv1 we are reporter */
#define MLD_IDLE_MEMBER 3 /* MLDv1 we reported last */
#define MLD_LAZY_MEMBER 4 /* MLDv1 other member reporting */
#define MLD_SLEEPING_MEMBER 5 /* MLDv1 start query response */
#define MLD_AWAKENING_MEMBER 6 /* MLDv1 group timer will start */
#define MLD_G_QUERY_PENDING_MEMBER 7 /* MLDv2 group query pending */
#define MLD_SG_QUERY_PENDING_MEMBER 8 /* MLDv2 source query pending */
#define MLD_LEAVING_MEMBER 9 /* MLDv2 dying gasp (pending last */
/* retransmission of INCLUDE {}) */
/*
* MLD version tag.
*/
#define MLD_VERSION_NONE 0 /* Invalid */
#define MLD_VERSION_1 1
#define MLD_VERSION_2 2 /* Default */
/*
* MLDv2 protocol control variables.
*/
#define MLD_RV_INIT 2 /* Robustness Variable */
#define MLD_RV_MIN 1
#define MLD_RV_MAX 7
#define MLD_QI_INIT 125 /* Query Interval (s) */
#define MLD_QI_MIN 1
#define MLD_QI_MAX 255
#define MLD_QRI_INIT 10 /* Query Response Interval (s) */
#define MLD_QRI_MIN 1
#define MLD_QRI_MAX 255
#define MLD_URI_INIT 3 /* Unsolicited Report Interval (s) */
#define MLD_URI_MIN 0
#define MLD_URI_MAX 10
#define MLD_MAX_GS_SOURCES 256 /* # of sources in rx GS query */
#define MLD_MAX_G_GS_PACKETS 8 /* # of packets to answer G/GS */
#define MLD_MAX_STATE_CHANGE_PACKETS 8 /* # of packets per state change */
#define MLD_MAX_RESPONSE_PACKETS 16 /* # of packets for general query */
#define MLD_MAX_RESPONSE_BURST 4 /* # of responses to send at once */
#define MLD_RESPONSE_BURST_INTERVAL (PR_FASTHZ / 2) /* 500ms */
/*
* MLD-specific mbuf flags.
*/
#define M_MLDV1 M_PROTO1 /* Packet is MLDv1 */
#define M_GROUPREC M_PROTO3 /* mbuf chain is a group record */
/*
* Leading space for MLDv2 reports inside MTU.
*
* NOTE: This differs from IGMPv3 significantly. KAME IPv6 requires
* that a fully formed mbuf chain *without* the Router Alert option
* is passed to ip6_output(), however we must account for it in the
* MTU if we need to split an MLDv2 report into several packets.
*
* We now put the MLDv2 report header in the initial mbuf containing
* the IPv6 header.
*/
#define MLD_MTUSPACE (sizeof(struct ip6_hdr) + sizeof(struct mld_raopt) + \
sizeof(struct icmp6_hdr))
/*
* Subsystem lock macros.
* The MLD lock is only taken with MLD. Currently it is system-wide.
* VIMAGE: The lock could be pushed to per-VIMAGE granularity in future.
*/
#define MLD_LOCK_INIT() mtx_init(&mld_mtx, "mld_mtx", NULL, MTX_DEF)
#define MLD_LOCK_DESTROY() mtx_destroy(&mld_mtx)
#define MLD_LOCK() mtx_lock(&mld_mtx)
#define MLD_LOCK_ASSERT() mtx_assert(&mld_mtx, MA_OWNED)
#define MLD_UNLOCK() mtx_unlock(&mld_mtx)
#define MLD_UNLOCK_ASSERT() mtx_assert(&mld_mtx, MA_NOTOWNED)
/*
* Per-link MLD context.
*/
#define MLD_IFINFO(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->mld_ifinfo)
int mld_change_state(struct in6_multi *, const int);
struct mld_ifinfo *
mld_domifattach(struct ifnet *);
void mld_domifdetach(struct ifnet *);
void mld_fasttimo(void);
void mld_ifdetach(struct ifnet *);
int mld_input(struct mbuf *, int, int);
void mld_slowtimo(void);
#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet6_mld);
#endif
#endif /* _KERNEL */
#endif /* _NETINET6_MLD6_VAR_HH_ */

2249
freebsd/netinet6/nd6.c Normal file

File diff suppressed because it is too large Load Diff

455
freebsd/netinet6/nd6.h Normal file
View File

@@ -0,0 +1,455 @@
/*-
* 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.
*
* $KAME: nd6.h,v 1.76 2001/12/18 02:10:31 itojun Exp $
* $FreeBSD$
*/
#ifndef _NETINET6_ND6_HH_
#define _NETINET6_ND6_HH_
/* see net/route.h, or net/if_inarp.h */
#ifndef RTF_ANNOUNCE
#define RTF_ANNOUNCE RTF_PROTO2
#endif
#include <rtems/freebsd/sys/queue.h>
#include <rtems/freebsd/sys/callout.h>
struct llentry;
#define ND6_LLINFO_NOSTATE -2
/*
* We don't need the WAITDELETE state any more, but we keep the definition
* in a comment line instead of removing it. This is necessary to avoid
* unintentionally reusing the value for another purpose, which might
* affect backward compatibility with old applications.
* (20000711 jinmei@kame.net)
*/
/* #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
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
#define ND6_LLINFO_PERMANENT(n) (((n)->la_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))
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 */
u_int32_t flags; /* Flags */
int recalctm; /* BaseReacable re-calculation timer */
u_int8_t chlim; /* CurHopLimit */
u_int8_t initialized; /* Flag to see the entry is initialized */
/* the following 3 members are for privacy extension for addrconf */
u_int8_t randomseed0[8]; /* upper 64 bits of MD5 digest */
u_int8_t randomseed1[8]; /* lower 64 bits (usually the EUI64 IFID) */
u_int8_t randomid[8]; /* current random ID */
};
#define ND6_IFF_PERFORMNUD 0x1
#define ND6_IFF_ACCEPT_RTADV 0x2
#define ND6_IFF_PREFER_SOURCE 0x4 /* XXX: not related to ND. */
#define ND6_IFF_IFDISABLED 0x8 /* IPv6 operation is disabled due to
* DAD failure. (XXX: not ND-specific)
*/
#define ND6_IFF_DONT_SET_IFROUTE 0x10
#define ND6_CREATE LLE_CREATE
#define ND6_EXCLUSIVE LLE_EXCLUSIVE
#ifdef _KERNEL
#define ND_IFINFO(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
#define IN6_LINKMTU(ifp) \
((ND_IFINFO(ifp)->linkmtu && ND_IFINFO(ifp)->linkmtu < (ifp)->if_mtu) \
? ND_IFINFO(ifp)->linkmtu \
: ((ND_IFINFO(ifp)->maxmtu && ND_IFINFO(ifp)->maxmtu < (ifp)->if_mtu) \
? ND_IFINFO(ifp)->maxmtu : (ifp)->if_mtu))
#endif
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_defrouter {
struct sockaddr_in6 rtaddr;
u_char flags;
u_short rtlifetime;
u_long expire;
u_short if_index;
};
#ifdef _KERNEL
struct in6_oprlist {
char ifname[IFNAMSIZ];
struct {
struct in6_addr prefix;
struct prf_ra raflags;
u_char prefixlen;
u_char origin;
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];
};
#endif
struct in6_prlist {
char ifname[IFNAMSIZ];
struct {
struct in6_addr prefix;
struct prf_ra raflags;
u_char prefixlen;
u_char origin;
u_int32_t vltime;
u_int32_t pltime;
time_t expire;
u_short if_index;
u_short advrtrs; /* number of advertisement routers */
struct in6_addr advrtr[DRLSTSIZ]; /* XXX: explicit limit */
} prefix[PRLSTSIZ];
};
struct in6_prefix {
struct sockaddr_in6 prefix;
struct prf_ra raflags;
u_char prefixlen;
u_char origin;
u_int32_t vltime;
u_int32_t pltime;
time_t expire;
u_int32_t flags;
int refcnt;
u_short if_index;
u_short advrtrs; /* number of advertisement routers */
/* struct sockaddr_in6 advrtr[] */
};
#ifdef _KERNEL
struct in6_ondireq {
char ifname[IFNAMSIZ];
struct {
u_int32_t linkmtu; /* LinkMTU */
u_int32_t maxmtu; /* Upper bound of LinkMTU */
u_int32_t basereachable; /* BaseReachableTime */
u_int32_t reachable; /* Reachable Time */
u_int32_t retrans; /* Retrans Timer */
u_int32_t flags; /* Flags */
int recalctm; /* BaseReacable re-calculation timer */
u_int8_t chlim; /* CurHopLimit */
u_int8_t receivedra;
} ndi;
};
#endif
struct in6_ndireq {
char ifname[IFNAMSIZ];
struct nd_ifinfo ndi;
};
struct in6_ndifreq {
char ifname[IFNAMSIZ];
u_long ifindex;
};
/* Prefix status */
#define NDPRF_ONLINK 0x1
#define NDPRF_DETACHED 0x2
/* 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 DEF_TEMP_VALID_LIFETIME 604800 /* 1 week */
#define DEF_TEMP_PREFERRED_LIFETIME 86400 /* 1 day */
#define TEMPADDR_REGEN_ADVANCE 5 /* sec */
#define MAX_TEMP_DESYNC_FACTOR 600 /* 10 min */
#define ND_COMPUTE_RTIME(x) \
(((MIN_RANDOM_FACTOR * (x >> 10)) + (arc4random() & \
((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)
TAILQ_HEAD(nd_drhead, nd_defrouter);
struct nd_defrouter {
TAILQ_ENTRY(nd_defrouter) dr_entry;
struct in6_addr rtaddr;
u_char flags; /* flags on RA message */
u_short rtlifetime;
u_long expire;
struct ifnet *ifp;
int installed; /* is installed into kernel routing table */
};
struct nd_prefixctl {
struct ifnet *ndpr_ifp;
/* prefix */
struct sockaddr_in6 ndpr_prefix;
u_char ndpr_plen;
u_int32_t ndpr_vltime; /* advertised valid lifetime */
u_int32_t ndpr_pltime; /* advertised preferred lifetime */
struct prf_ra ndpr_flags;
};
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 */
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 */
time_t ndpr_lastupdate; /* reception time of last advertisement */
struct prf_ra ndpr_flags;
u_int32_t ndpr_stateflags; /* actual state flags */
/* list of routers that advertise the prefix: */
LIST_HEAD(pr_rtrhead, nd_pfxrouter) ndpr_advrtrs;
u_char ndpr_plen;
int ndpr_refcnt; /* reference couter from addresses */
};
#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_raf_router ndpr_flags.router
/*
* 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 compatibility */
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
struct nd_pfxrouter {
LIST_ENTRY(nd_pfxrouter) pfr_entry;
#define pfr_next pfr_entry.le_next
struct nd_defrouter *router;
};
LIST_HEAD(nd_prhead, nd_prefix);
/* nd6.c */
VNET_DECLARE(int, nd6_prune);
VNET_DECLARE(int, nd6_delay);
VNET_DECLARE(int, nd6_umaxtries);
VNET_DECLARE(int, nd6_mmaxtries);
VNET_DECLARE(int, nd6_useloopback);
VNET_DECLARE(int, nd6_maxnudhint);
VNET_DECLARE(int, nd6_gctimer);
VNET_DECLARE(struct nd_drhead, nd_defrouter);
VNET_DECLARE(struct nd_prhead, nd_prefix);
VNET_DECLARE(int, nd6_debug);
VNET_DECLARE(int, nd6_onlink_ns_rfc4861);
#define V_nd6_prune VNET(nd6_prune)
#define V_nd6_delay VNET(nd6_delay)
#define V_nd6_umaxtries VNET(nd6_umaxtries)
#define V_nd6_mmaxtries VNET(nd6_mmaxtries)
#define V_nd6_useloopback VNET(nd6_useloopback)
#define V_nd6_maxnudhint VNET(nd6_maxnudhint)
#define V_nd6_gctimer VNET(nd6_gctimer)
#define V_nd_defrouter VNET(nd_defrouter)
#define V_nd_prefix VNET(nd_prefix)
#define V_nd6_debug VNET(nd6_debug)
#define V_nd6_onlink_ns_rfc4861 VNET(nd6_onlink_ns_rfc4861)
#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0)
VNET_DECLARE(struct callout, nd6_timer_ch);
#define V_nd6_timer_ch VNET(nd6_timer_ch)
/* nd6_rtr.c */
VNET_DECLARE(int, nd6_defifindex);
VNET_DECLARE(int, ip6_desync_factor); /* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */
VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */
VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */
#define V_nd6_defifindex VNET(nd6_defifindex)
#define V_ip6_desync_factor VNET(ip6_desync_factor)
#define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime)
#define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime)
#define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance)
union nd_opts {
struct nd_opt_hdr *nd_opt_array[8]; /* max = target address list */
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));
#ifdef VIMAGE
void nd6_destroy __P((void));
#endif
struct nd_ifinfo *nd6_ifattach __P((struct ifnet *));
void nd6_ifdetach __P((struct nd_ifinfo *));
int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));
void nd6_option_init __P((void *, int, union nd_opts *));
struct nd_opt_hdr *nd6_option __P((union nd_opts *));
int nd6_options __P((union nd_opts *));
struct llentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
void nd6_setmtu __P((struct ifnet *));
void nd6_llinfo_settimer __P((struct llentry *, long));
void nd6_llinfo_settimer_locked __P((struct llentry *, long));
void nd6_timer __P((void *));
void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct rtentry *));
int nd6_output_lle __P((struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct rtentry *, struct llentry *,
struct mbuf **));
int nd6_output_flush __P((struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct route *));
int nd6_need_cache __P((struct ifnet *));
int nd6_storelladdr __P((struct ifnet *, struct mbuf *,
struct sockaddr *, u_char *, struct llentry **));
/* nd6_nbr.c */
void nd6_na_input __P((struct mbuf *, int, int));
void nd6_na_output __P((struct ifnet *, const struct in6_addr *,
const struct in6_addr *, u_long, int, struct sockaddr *));
void nd6_ns_input __P((struct mbuf *, int, int));
void nd6_ns_output __P((struct ifnet *, const struct in6_addr *,
const struct in6_addr *, struct llentry *, int));
caddr_t nd6_ifptomac __P((struct ifnet *));
void nd6_dad_start __P((struct ifaddr *, int));
void nd6_dad_stop __P((struct ifaddr *));
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_reset __P((void));
void defrouter_select __P((void));
void defrtrlist_del __P((struct nd_defrouter *));
void prelist_remove __P((struct nd_prefix *));
int nd6_prelist_add __P((struct nd_prefixctl *, struct nd_defrouter *,
struct nd_prefix **));
int nd6_prefix_onlink __P((struct nd_prefix *));
int nd6_prefix_offlink __P((struct nd_prefix *));
void pfxlist_onlink_check __P((void));
struct nd_defrouter *defrouter_lookup __P((struct in6_addr *, struct ifnet *));
struct nd_prefix *nd6_prefix_lookup __P((struct nd_prefixctl *));
void rt6_flush __P((struct in6_addr *, struct ifnet *));
int nd6_setdefaultiface __P((int));
int in6_tmpifadd __P((const struct in6_ifaddr *, int, int));
#endif /* _KERNEL */
#endif /* _NETINET6_ND6_HH_ */

1514
freebsd/netinet6/nd6_nbr.c Normal file

File diff suppressed because it is too large Load Diff

2162
freebsd/netinet6/nd6_rtr.c Normal file

File diff suppressed because it is too large Load Diff

69
freebsd/netinet6/pim6.h Normal file
View File

@@ -0,0 +1,69 @@
/*-
* 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.
*
* $KAME: pim6.h,v 1.3 2000/03/25 07:23:58 sumikawa Exp $
* $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

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.
*
* $KAME: pim6_var.h,v 1.8 2000/06/06 08:07:43 jinmei Exp $
* $FreeBSD$
*/
/*
* 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
*/
#ifndef _NETINET6_PIM6_VAR_HH_
#define _NETINET6_PIM6_VAR_HH_
struct pim6stat {
u_quad_t pim6s_rcv_total; /* total PIM messages received */
u_quad_t pim6s_rcv_tooshort; /* received with too few bytes */
u_quad_t pim6s_rcv_badsum; /* received with bad checksum */
u_quad_t pim6s_rcv_badversion; /* received bad PIM version */
u_quad_t pim6s_rcv_registers; /* received registers */
u_quad_t pim6s_rcv_badregisters; /* received invalid registers */
u_quad_t pim6s_snd_registers; /* sent registers */
};
#if (defined(KERNEL)) || (defined(_KERNEL))
int pim6_input __P((struct mbuf **, int*, int));
#endif /* KERNEL */
/*
* Names for PIM sysctl objects
*/
#define PIM6CTL_STATS 1 /* statistics (read-only) */
#define PIM6CTL_MAXID 2
#define PIM6CTL_NAMES { \
{ 0, 0 }, \
{ 0, 0 }, \
}
#endif /* _NETINET6_PIM6_VAR_HH_ */

905
freebsd/netinet6/raw_ip6.c Normal file
View File

@@ -0,0 +1,905 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*/
/*-
* 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.
* 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 <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_ipsec.h>
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/errno.h>
#include <rtems/freebsd/sys/jail.h>
#include <rtems/freebsd/sys/lock.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/priv.h>
#include <rtems/freebsd/sys/proc.h>
#include <rtems/freebsd/sys/protosw.h>
#include <rtems/freebsd/sys/signalvar.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/socketvar.h>
#include <rtems/freebsd/sys/sx.h>
#include <rtems/freebsd/sys/syslog.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/if_types.h>
#include <rtems/freebsd/net/route.h>
#include <rtems/freebsd/net/vnet.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/in_var.h>
#include <rtems/freebsd/netinet/in_systm.h>
#include <rtems/freebsd/netinet/in_pcb.h>
#include <rtems/freebsd/netinet/icmp6.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6protosw.h>
#include <rtems/freebsd/netinet6/ip6_mroute.h>
#include <rtems/freebsd/netinet6/in6_pcb.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/nd6.h>
#include <rtems/freebsd/netinet6/raw_ip6.h>
#include <rtems/freebsd/netinet6/scope6_var.h>
#ifdef IPSEC
#include <rtems/freebsd/netipsec/ipsec.h>
#include <rtems/freebsd/netipsec/ipsec6.h>
#endif /* IPSEC */
#include <rtems/freebsd/machine/stdarg.h>
#define satosin6(sa) ((struct sockaddr_in6 *)(sa))
#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
/*
* Raw interface to IP6 protocol.
*/
VNET_DECLARE(struct inpcbhead, ripcb);
VNET_DECLARE(struct inpcbinfo, ripcbinfo);
#define V_ripcb VNET(ripcb)
#define V_ripcbinfo VNET(ripcbinfo)
extern u_long rip_sendspace;
extern u_long rip_recvspace;
VNET_DEFINE(struct rip6stat, rip6stat);
/*
* Hooks for multicast routing. They all default to NULL, so leave them not
* initialized and rely on BSS being set to 0.
*/
/*
* The socket used to communicate with the multicast routing daemon.
*/
VNET_DEFINE(struct socket *, ip6_mrouter);
/*
* The various mrouter functions.
*/
int (*ip6_mrouter_set)(struct socket *, struct sockopt *);
int (*ip6_mrouter_get)(struct socket *, struct sockopt *);
int (*ip6_mrouter_done)(void);
int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *);
int (*mrt6_ioctl)(u_long, caddr_t);
/*
* Setup generic address and protocol structures for raw_input routine, then
* pass them along with mbuf chain.
*/
int
rip6_input(struct mbuf **mp, int *offp, int proto)
{
struct ifnet *ifp;
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 = NULL;
struct sockaddr_in6 fromsa;
V_rip6stat.rip6s_ipackets++;
if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
/* XXX Send icmp6 host/port unreach? */
m_freem(m);
return (IPPROTO_DONE);
}
init_sin6(&fromsa, m); /* general init */
ifp = m->m_pkthdr.rcvif;
INP_INFO_RLOCK(&V_ripcbinfo);
LIST_FOREACH(in6p, &V_ripcb, inp_list) {
/* XXX inp locking */
if ((in6p->inp_vflag & INP_IPV6) == 0)
continue;
if (in6p->inp_ip_p &&
in6p->inp_ip_p != 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 (jailed_without_vnet(in6p->inp_cred)) {
/*
* Allow raw socket in jail to receive multicast;
* assume process had PRIV_NETINET_RAW at attach,
* and fall through into normal filter path if so.
*/
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
prison_check_ip6(in6p->inp_cred,
&ip6->ip6_dst) != 0)
continue;
}
if (in6p->in6p_cksum != -1) {
V_rip6stat.rip6s_isum++;
if (in6_cksum(m, proto, *offp,
m->m_pkthdr.len - *offp)) {
INP_RUNLOCK(in6p);
V_rip6stat.rip6s_badsum++;
continue;
}
}
INP_RLOCK(in6p);
/*
* If this raw socket has multicast state, and we
* have received a multicast, check if this socket
* should receive it, as multicast filtering is now
* the responsibility of the transport layer.
*/
if (in6p->in6p_moptions &&
IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
/*
* If the incoming datagram is for MLD, allow it
* through unconditionally to the raw socket.
*
* Use the M_RTALERT_MLD flag to check for MLD
* traffic without having to inspect the mbuf chain
* more deeply, as all MLDv1/v2 host messages MUST
* contain the Router Alert option.
*
* In the case of MLDv1, we may not have explicitly
* joined the group, and may have set IFF_ALLMULTI
* on the interface. im6o_mc_filter() may discard
* control traffic we actually need to see.
*
* Userland multicast routing daemons should continue
* filter the control traffic appropriately.
*/
int blocked;
blocked = MCAST_PASS;
if ((m->m_flags & M_RTALERT_MLD) == 0) {
struct sockaddr_in6 mcaddr;
bzero(&mcaddr, sizeof(struct sockaddr_in6));
mcaddr.sin6_len = sizeof(struct sockaddr_in6);
mcaddr.sin6_family = AF_INET6;
mcaddr.sin6_addr = ip6->ip6_dst;
blocked = im6o_mc_filter(in6p->in6p_moptions,
ifp,
(struct sockaddr *)&mcaddr,
(struct sockaddr *)&fromsa);
}
if (blocked != MCAST_PASS) {
IP6STAT_INC(ip6s_notmember);
INP_RUNLOCK(in6p);
continue;
}
}
if (last != NULL) {
struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
#ifdef IPSEC
/*
* Check AH/ESP integrity.
*/
if (n && ipsec6_in_reject(n, last)) {
m_freem(n);
V_ipsec6stat.in_polvio++;
/* Do not inject data into pcb. */
} else
#endif /* IPSEC */
if (n) {
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, n, &opts);
/* strip intermediate headers */
m_adj(n, *offp);
if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa,
n, opts) == 0) {
m_freem(n);
if (opts)
m_freem(opts);
V_rip6stat.rip6s_fullsock++;
} else
sorwakeup(last->inp_socket);
opts = NULL;
}
INP_RUNLOCK(last);
}
last = in6p;
}
INP_INFO_RUNLOCK(&V_ripcbinfo);
#ifdef IPSEC
/*
* Check AH/ESP integrity.
*/
if ((last != NULL) && ipsec6_in_reject(m, last)) {
m_freem(m);
V_ipsec6stat.in_polvio++;
V_ip6stat.ip6s_delivered--;
/* Do not inject data into pcb. */
INP_RUNLOCK(last);
} else
#endif /* IPSEC */
if (last != NULL) {
if (last->inp_flags & INP_CONTROLOPTS ||
last->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, m, &opts);
/* Strip intermediate headers. */
m_adj(m, *offp);
if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
V_rip6stat.rip6s_fullsock++;
} else
sorwakeup(last->inp_socket);
INP_RUNLOCK(last);
} else {
V_rip6stat.rip6s_nosock++;
if (m->m_flags & M_MCAST)
V_rip6stat.rip6s_nosockmcast++;
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 *));
}
V_ip6stat.ip6s_delivered--;
}
return (IPPROTO_DONE);
}
void
rip6_ctlinput(int cmd, struct sockaddr *sa, void *d)
{
struct ip6_hdr *ip6;
struct mbuf *m;
int off = 0;
struct ip6ctlparam *ip6cp = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
void *cmdarg;
struct inpcb *(*notify)(struct inpcb *, int) = in6_rtchange;
if (sa->sa_family != AF_INET6 ||
sa->sa_len != sizeof(struct sockaddr_in6))
return;
if ((unsigned)cmd >= PRC_NCMDS)
return;
if (PRC_IS_REDIRECT(cmd))
notify = in6_rtchange, d = NULL;
else if (cmd == PRC_HOSTDEAD)
d = NULL;
else if (inet6ctlerrmap[cmd] == 0)
return;
/*
* If the parameter is from icmp6, decode it.
*/
if (d != NULL) {
ip6cp = (struct ip6ctlparam *)d;
m = ip6cp->ip6c_m;
ip6 = ip6cp->ip6c_ip6;
off = ip6cp->ip6c_off;
cmdarg = ip6cp->ip6c_cmdarg;
sa6_src = ip6cp->ip6c_src;
} else {
m = NULL;
ip6 = NULL;
cmdarg = NULL;
sa6_src = &sa6_any;
}
(void) in6_pcbnotify(&V_ripcbinfo, sa, 0,
(const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify);
}
/*
* 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 mbuf *control;
struct socket *so;
struct sockaddr_in6 *dstsock;
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;
struct ifnet *oifp = NULL;
int type = 0, code = 0; /* for ICMPv6 output statistics only */
int scope_ambiguous = 0;
int use_defzone = 0;
struct in6_addr in6a;
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 = sotoinpcb(so);
INP_WLOCK(in6p);
dst = &dstsock->sin6_addr;
if (control != NULL) {
if ((error = ip6_setpktopts(control, &opt,
in6p->in6p_outputopts, so->so_cred,
so->so_proto->pr_protocol)) != 0) {
goto bad;
}
optp = &opt;
} else
optp = in6p->in6p_outputopts;
/*
* Check and convert scope zone ID into internal form.
*
* XXX: we may still need to determine the zone later.
*/
if (!(so->so_state & SS_ISCONNECTED)) {
if (!optp || !optp->ip6po_pktinfo ||
!optp->ip6po_pktinfo->ipi6_ifindex)
use_defzone = V_ip6_use_defzone;
if (dstsock->sin6_scope_id == 0 && !use_defzone)
scope_ambiguous = 1;
if ((error = sa6_embedscope(dstsock, use_defzone)) != 0)
goto bad;
}
/*
* 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_DONTWAIT);
if (m == NULL) {
error = ENOBUFS;
goto bad;
}
ip6 = mtod(m, struct ip6_hdr *);
/*
* Source address selection.
*/
error = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
&oifp, &in6a);
if (error)
goto bad;
error = prison_check_ip6(in6p->inp_cred, &in6a);
if (error != 0)
goto bad;
ip6->ip6_src = in6a;
if (oifp && scope_ambiguous) {
/*
* Application should provide a proper zone ID or the use of
* default zone IDs should be enabled. Unfortunately, some
* applications do not behave as it should, so we need a
* workaround. Even if an appropriate ID is not determined
* (when it's required), if we can determine the outgoing
* interface. determine the zone ID based on the interface.
*/
error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
if (error != 0)
goto bad;
}
ip6->ip6_dst = dstsock->sin6_addr;
/*
* Fill in the rest of the IPv6 header fields.
*/
ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
(in6p->inp_flow & IPV6_FLOWINFO_MASK);
ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
(IPV6_VERSION & IPV6_VERSION_MASK);
/*
* ip6_plen will be filled in ip6_output, so not fill it here.
*/
ip6->ip6_nxt = in6p->inp_ip_p;
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;
/* 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);
}
error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
if (oifp)
icmp6_ifoutstat_inc(oifp, type, code);
ICMP6STAT_INC(icp6s_outhist[type]);
} else
V_rip6stat.rip6s_opackets++;
goto freectl;
bad:
if (m)
m_freem(m);
freectl:
if (control != NULL) {
ip6_clearpktopts(&opt, -1);
m_freem(control);
}
INP_WUNLOCK(in6p);
return (error);
}
/*
* Raw IPv6 socket option processing.
*/
int
rip6_ctloutput(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) {
case MRT6_INIT:
case MRT6_DONE:
case MRT6_ADD_MIF:
case MRT6_DEL_MIF:
case MRT6_ADD_MFC:
case MRT6_DEL_MFC:
case MRT6_PIM:
error = ip6_mrouter_get ? ip6_mrouter_get(so, sopt) :
EOPNOTSUPP;
break;
case IPV6_CHECKSUM:
error = ip6_raw_ctloutput(so, sopt);
break;
default:
error = ip6_ctloutput(so, sopt);
break;
}
break;
case SOPT_SET:
switch (sopt->sopt_name) {
case MRT6_INIT:
case MRT6_DONE:
case MRT6_ADD_MIF:
case MRT6_DEL_MIF:
case MRT6_ADD_MFC:
case MRT6_DEL_MFC:
case MRT6_PIM:
error = ip6_mrouter_set ? ip6_mrouter_set(so, sopt) :
EOPNOTSUPP;
break;
case IPV6_CHECKSUM:
error = ip6_raw_ctloutput(so, sopt);
break;
default:
error = ip6_ctloutput(so, sopt);
break;
}
break;
}
return (error);
}
static int
rip6_attach(struct socket *so, int proto, struct thread *td)
{
struct inpcb *inp;
struct icmp6_filter *filter;
int error;
inp = sotoinpcb(so);
KASSERT(inp == NULL, ("rip6_attach: inp != NULL"));
error = priv_check(td, PRIV_NETINET_RAW);
if (error)
return (error);
error = soreserve(so, rip_sendspace, rip_recvspace);
if (error)
return (error);
filter = malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
if (filter == NULL)
return (ENOMEM);
INP_INFO_WLOCK(&V_ripcbinfo);
error = in_pcballoc(so, &V_ripcbinfo);
if (error) {
INP_INFO_WUNLOCK(&V_ripcbinfo);
free(filter, M_PCB);
return (error);
}
inp = (struct inpcb *)so->so_pcb;
INP_INFO_WUNLOCK(&V_ripcbinfo);
inp->inp_vflag |= INP_IPV6;
inp->inp_ip_p = (long)proto;
inp->in6p_hops = -1; /* use kernel default */
inp->in6p_cksum = -1;
inp->in6p_icmp6filt = filter;
ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
INP_WUNLOCK(inp);
return (0);
}
static void
rip6_detach(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
if (so == V_ip6_mrouter && ip6_mrouter_done)
ip6_mrouter_done();
/* xxx: RSVP */
INP_INFO_WLOCK(&V_ripcbinfo);
INP_WLOCK(inp);
free(inp->in6p_icmp6filt, M_PCB);
in_pcbdetach(inp);
in_pcbfree(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
}
/* XXXRW: This can't ever be called. */
static void
rip6_abort(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_abort: inp == NULL"));
soisdisconnected(so);
}
static void
rip6_close(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_close: inp == NULL"));
soisdisconnected(so);
}
static int
rip6_disconnect(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_disconnect: inp == NULL"));
if ((so->so_state & SS_ISCONNECTED) == 0)
return (ENOTCONN);
inp->in6p_faddr = in6addr_any;
rip6_abort(so);
return (0);
}
static int
rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
{
struct inpcb *inp;
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
struct ifaddr *ifa = NULL;
int error = 0;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_bind: inp == NULL"));
if (nam->sa_len != sizeof(*addr))
return (EINVAL);
if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0)
return (error);
if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6)
return (EADDRNOTAVAIL);
if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
return (error);
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
(ifa = ifa_ifwithaddr((struct sockaddr *)addr)) == NULL)
return (EADDRNOTAVAIL);
if (ifa != NULL &&
((struct in6_ifaddr *)ifa)->ia6_flags &
(IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
ifa_free(ifa);
return (EADDRNOTAVAIL);
}
if (ifa != NULL)
ifa_free(ifa);
INP_INFO_WLOCK(&V_ripcbinfo);
INP_WLOCK(inp);
inp->in6p_laddr = addr->sin6_addr;
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
return (0);
}
static int
rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
{
struct inpcb *inp;
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
struct in6_addr in6a;
struct ifnet *ifp = NULL;
int error = 0, scope_ambiguous = 0;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_connect: inp == NULL"));
if (nam->sa_len != sizeof(*addr))
return (EINVAL);
if (TAILQ_EMPTY(&V_ifnet))
return (EADDRNOTAVAIL);
if (addr->sin6_family != AF_INET6)
return (EAFNOSUPPORT);
/*
* Application should provide a proper zone ID or the use of default
* zone IDs should be enabled. Unfortunately, some applications do
* not behave as it should, so we need a workaround. Even if an
* appropriate ID is not determined, we'll see if we can determine
* the outgoing interface. If we can, determine the zone ID based on
* the interface below.
*/
if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone)
scope_ambiguous = 1;
if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
return (error);
INP_INFO_WLOCK(&V_ripcbinfo);
INP_WLOCK(inp);
/* Source address selection. XXX: need pcblookup? */
error = in6_selectsrc(addr, inp->in6p_outputopts,
inp, NULL, so->so_cred, &ifp, &in6a);
if (error) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
return (error);
}
/* XXX: see above */
if (ifp && scope_ambiguous &&
(error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
return (error);
}
inp->in6p_faddr = addr->sin6_addr;
inp->in6p_laddr = in6a;
soisconnected(so);
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_ripcbinfo);
return (0);
}
static int
rip6_shutdown(struct socket *so)
{
struct inpcb *inp;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_shutdown: inp == NULL"));
INP_WLOCK(inp);
socantsendmore(so);
INP_WUNLOCK(inp);
return (0);
}
static int
rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct mbuf *control, struct thread *td)
{
struct inpcb *inp;
struct sockaddr_in6 tmp;
struct sockaddr_in6 *dst;
int ret;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_send: inp == NULL"));
/* Always copy sockaddr to avoid overwrites. */
/* Unlocked read. */
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);
INP_RLOCK(inp);
bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
sizeof(struct in6_addr));
INP_RUNLOCK(inp);
dst = &tmp;
} else {
if (nam == NULL) {
m_freem(m);
return (ENOTCONN);
}
if (nam->sa_len != sizeof(struct sockaddr_in6)) {
m_freem(m);
return (EINVAL);
}
tmp = *(struct sockaddr_in6 *)nam;
dst = &tmp;
if (dst->sin6_family == AF_UNSPEC) {
/*
* XXX: we allow this case for backward
* compatibility to buggy applications that
* rely on old (and wrong) kernel behavior.
*/
log(LOG_INFO, "rip6 SEND: address family is "
"unspec. Assume AF_INET6\n");
dst->sin6_family = AF_INET6;
} else if (dst->sin6_family != AF_INET6) {
m_freem(m);
return(EAFNOSUPPORT);
}
}
ret = rip6_output(m, so, dst, control);
return (ret);
}
struct pr_usrreqs rip6_usrreqs = {
.pru_abort = rip6_abort,
.pru_attach = rip6_attach,
.pru_bind = rip6_bind,
.pru_connect = rip6_connect,
.pru_control = in6_control,
.pru_detach = rip6_detach,
.pru_disconnect = rip6_disconnect,
.pru_peeraddr = in6_getpeeraddr,
.pru_send = rip6_send,
.pru_shutdown = rip6_shutdown,
.pru_sockaddr = in6_getsockaddr,
.pru_close = rip6_close,
};

View File

@@ -0,0 +1,55 @@
/*-
* Copyright (C) 2001 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.
*
* $KAME: raw_ip6.h,v 1.2 2001/05/27 13:28:35 itojun Exp $
* $FreeBSD$
*/
#ifndef _NETINET6_RAW_IP6_HH_
#define _NETINET6_RAW_IP6_HH_
/*
* ICMPv6 stat is counted separately. see netinet/icmp6.h
*/
struct rip6stat {
u_quad_t rip6s_ipackets; /* total input packets */
u_quad_t rip6s_isum; /* input checksum computations */
u_quad_t rip6s_badsum; /* of above, checksum error */
u_quad_t rip6s_nosock; /* no matching socket */
u_quad_t rip6s_nosockmcast; /* of above, arrived as multicast */
u_quad_t rip6s_fullsock; /* not delivered, input socket full */
u_quad_t rip6s_opackets; /* total output packets */
};
#ifdef _KERNEL
VNET_DECLARE(struct rip6stat, rip6stat);
#define V_rip6stat VNET(rip6stat)
#endif
#endif

111
freebsd/netinet6/route6.c Normal file
View File

@@ -0,0 +1,111 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* 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.
*
* $KAME: route6.c,v 1.24 2001/03/14 03:07:05 itojun Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/local/opt_inet.h>
#include <rtems/freebsd/local/opt_inet6.h>
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/queue.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet6/in6_var.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/scope6_var.h>
#include <rtems/freebsd/netinet/icmp6.h>
/*
* proto - is unused
*/
int
route6_input(struct mbuf **mp, int *offp, int proto)
{
struct ip6_hdr *ip6;
struct mbuf *m = *mp;
struct ip6_rthdr *rh;
int off = *offp, rhlen;
struct ip6aux *ip6a;
ip6a = ip6_findaux(m);
if (ip6a) {
/* XXX reject home-address option before rthdr */
if (ip6a->ip6a_flags & IP6A_SWAP) {
V_ip6stat.ip6s_badoptions++;
m_freem(m);
return IPPROTO_DONE;
}
}
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, sizeof(*rh), IPPROTO_DONE);
ip6 = mtod(m, struct ip6_hdr *);
rh = (struct ip6_rthdr *)((caddr_t)ip6 + off);
#else
ip6 = mtod(m, struct ip6_hdr *);
IP6_EXTHDR_GET(rh, struct ip6_rthdr *, m, off, sizeof(*rh));
if (rh == NULL) {
V_ip6stat.ip6s_tooshort++;
return IPPROTO_DONE;
}
#endif
/*
* While this switch may look gratuitous, leave it in
* in favour of RH2 implementations, etc.
*/
switch (rh->ip6r_type) {
default:
/* Unknown routing header type. */
if (rh->ip6r_segleft == 0) {
rhlen = (rh->ip6r_len + 1) << 3;
break; /* Final dst. Just ignore the header. */
}
V_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);
}

498
freebsd/netinet6/scope6.c Normal file
View File

@@ -0,0 +1,498 @@
#include <rtems/freebsd/machine/rtems-bsd-config.h>
/*-
* Copyright (C) 2000 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.
*
* $KAME: scope6.c,v 1.10 2000/07/24 13:29:31 itojun Exp $
*/
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <rtems/freebsd/sys/param.h>
#include <rtems/freebsd/sys/malloc.h>
#include <rtems/freebsd/sys/mbuf.h>
#include <rtems/freebsd/sys/socket.h>
#include <rtems/freebsd/sys/systm.h>
#include <rtems/freebsd/sys/queue.h>
#include <rtems/freebsd/sys/syslog.h>
#include <rtems/freebsd/net/if.h>
#include <rtems/freebsd/net/vnet.h>
#include <rtems/freebsd/netinet/in.h>
#include <rtems/freebsd/netinet/ip6.h>
#include <rtems/freebsd/netinet6/in6_var.h>
#include <rtems/freebsd/netinet6/ip6_var.h>
#include <rtems/freebsd/netinet6/scope6_var.h>
#ifdef ENABLE_DEFAULT_SCOPE
VNET_DEFINE(int, ip6_use_defzone) = 1;
#else
VNET_DEFINE(int, ip6_use_defzone) = 0;
#endif
/*
* The scope6_lock protects the global sid default stored in
* sid_default below.
*/
static struct mtx scope6_lock;
#define SCOPE6_LOCK_INIT() mtx_init(&scope6_lock, "scope6_lock", NULL, MTX_DEF)
#define SCOPE6_LOCK() mtx_lock(&scope6_lock)
#define SCOPE6_UNLOCK() mtx_unlock(&scope6_lock)
#define SCOPE6_LOCK_ASSERT() mtx_assert(&scope6_lock, MA_OWNED)
static VNET_DEFINE(struct scope6_id, sid_default);
#define V_sid_default VNET(sid_default)
#define SID(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->scope6_id)
void
scope6_init(void)
{
bzero(&V_sid_default, sizeof(V_sid_default));
if (!IS_DEFAULT_VNET(curvnet))
return;
SCOPE6_LOCK_INIT();
}
struct scope6_id *
scope6_ifattach(struct ifnet *ifp)
{
struct scope6_id *sid;
sid = (struct scope6_id *)malloc(sizeof(*sid), M_IFADDR, M_WAITOK);
bzero(sid, sizeof(*sid));
/*
* XXX: IPV6_ADDR_SCOPE_xxx macros are not standard.
* Should we rather hardcode here?
*/
sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] = ifp->if_index;
sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = ifp->if_index;
#ifdef MULTI_SCOPE
/* by default, we don't care about scope boundary for these scopes. */
sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL] = 1;
sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1;
#endif
return sid;
}
void
scope6_ifdetach(struct scope6_id *sid)
{
free(sid, M_IFADDR);
}
int
scope6_set(struct ifnet *ifp, struct scope6_id *idlist)
{
int i;
int error = 0;
struct scope6_id *sid = NULL;
IF_AFDATA_LOCK(ifp);
sid = SID(ifp);
if (!sid) { /* paranoid? */
IF_AFDATA_UNLOCK(ifp);
return (EINVAL);
}
/*
* XXX: We need more consistency checks of the relationship among
* scopes (e.g. an organization should be larger than a site).
*/
/*
* TODO(XXX): after setting, we should reflect the changes to
* interface addresses, routing table entries, PCB entries...
*/
SCOPE6_LOCK();
for (i = 0; i < 16; i++) {
if (idlist->s6id_list[i] &&
idlist->s6id_list[i] != sid->s6id_list[i]) {
/*
* An interface zone ID must be the corresponding
* interface index by definition.
*/
if (i == IPV6_ADDR_SCOPE_INTFACELOCAL &&
idlist->s6id_list[i] != ifp->if_index) {
IF_AFDATA_UNLOCK(ifp);
SCOPE6_UNLOCK();
return (EINVAL);
}
if (i == IPV6_ADDR_SCOPE_LINKLOCAL &&
idlist->s6id_list[i] > V_if_index) {
/*
* XXX: theoretically, there should be no
* relationship between link IDs and interface
* IDs, but we check the consistency for
* safety in later use.
*/
IF_AFDATA_UNLOCK(ifp);
SCOPE6_UNLOCK();
return (EINVAL);
}
/*
* XXX: we must need lots of work in this case,
* but we simply set the new value in this initial
* implementation.
*/
sid->s6id_list[i] = idlist->s6id_list[i];
}
}
SCOPE6_UNLOCK();
IF_AFDATA_UNLOCK(ifp);
return (error);
}
int
scope6_get(struct ifnet *ifp, struct scope6_id *idlist)
{
/* We only need to lock the interface's afdata for SID() to work. */
IF_AFDATA_LOCK(ifp);
struct scope6_id *sid = SID(ifp);
if (sid == NULL) { /* paranoid? */
IF_AFDATA_UNLOCK(ifp);
return (EINVAL);
}
SCOPE6_LOCK();
*idlist = *sid;
SCOPE6_UNLOCK();
IF_AFDATA_UNLOCK(ifp);
return (0);
}
/*
* Get a scope of the address. Node-local, link-local, site-local or global.
*/
int
in6_addrscope(struct in6_addr *addr)
{
int scope;
if (addr->s6_addr[0] == 0xfe) {
scope = addr->s6_addr[1] & 0xc0;
switch (scope) {
case 0x80:
return IPV6_ADDR_SCOPE_LINKLOCAL;
break;
case 0xc0:
return IPV6_ADDR_SCOPE_SITELOCAL;
break;
default:
return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */
break;
}
}
if (addr->s6_addr[0] == 0xff) {
scope = addr->s6_addr[1] & 0x0f;
/*
* due to other scope such as reserved,
* return scope doesn't work.
*/
switch (scope) {
case IPV6_ADDR_SCOPE_INTFACELOCAL:
return IPV6_ADDR_SCOPE_INTFACELOCAL;
break;
case IPV6_ADDR_SCOPE_LINKLOCAL:
return IPV6_ADDR_SCOPE_LINKLOCAL;
break;
case IPV6_ADDR_SCOPE_SITELOCAL:
return IPV6_ADDR_SCOPE_SITELOCAL;
break;
default:
return IPV6_ADDR_SCOPE_GLOBAL;
break;
}
}
/*
* Regard loopback and unspecified addresses as global, since
* they have no ambiguity.
*/
if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) {
if (addr->s6_addr[15] == 1) /* loopback */
return IPV6_ADDR_SCOPE_LINKLOCAL;
if (addr->s6_addr[15] == 0) /* unspecified */
return IPV6_ADDR_SCOPE_GLOBAL; /* XXX: correct? */
}
return IPV6_ADDR_SCOPE_GLOBAL;
}
/*
* ifp - note that this might be NULL
*/
void
scope6_setdefault(struct ifnet *ifp)
{
/*
* Currently, this function just sets the default "interfaces"
* and "links" according to the given interface.
* We might eventually have to separate the notion of "link" from
* "interface" and provide a user interface to set the default.
*/
SCOPE6_LOCK();
if (ifp) {
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] =
ifp->if_index;
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] =
ifp->if_index;
} else {
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL] = 0;
V_sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0;
}
SCOPE6_UNLOCK();
}
int
scope6_get_default(struct scope6_id *idlist)
{
SCOPE6_LOCK();
*idlist = V_sid_default;
SCOPE6_UNLOCK();
return (0);
}
u_int32_t
scope6_addr2default(struct in6_addr *addr)
{
u_int32_t id;
/*
* special case: The loopback address should be considered as
* link-local, but there's no ambiguity in the syntax.
*/
if (IN6_IS_ADDR_LOOPBACK(addr))
return (0);
/*
* XXX: 32-bit read is atomic on all our platforms, is it OK
* not to lock here?
*/
SCOPE6_LOCK();
id = V_sid_default.s6id_list[in6_addrscope(addr)];
SCOPE6_UNLOCK();
return (id);
}
/*
* Validate the specified scope zone ID in the sin6_scope_id field. If the ID
* is unspecified (=0), needs to be specified, and the default zone ID can be
* used, the default value will be used.
* This routine then generates the kernel-internal form: if the address scope
* of is interface-local or link-local, embed the interface index in the
* address.
*/
int
sa6_embedscope(struct sockaddr_in6 *sin6, int defaultok)
{
struct ifnet *ifp;
u_int32_t zoneid;
if ((zoneid = sin6->sin6_scope_id) == 0 && defaultok)
zoneid = scope6_addr2default(&sin6->sin6_addr);
if (zoneid != 0 &&
(IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr))) {
/*
* At this moment, we only check interface-local and
* link-local scope IDs, and use interface indices as the
* zone IDs assuming a one-to-one mapping between interfaces
* and links.
*/
if (V_if_index < zoneid)
return (ENXIO);
ifp = ifnet_byindex(zoneid);
if (ifp == NULL) /* XXX: this can happen for some OS */
return (ENXIO);
/* XXX assignment to 16bit from 32bit variable */
sin6->sin6_addr.s6_addr16[1] = htons(zoneid & 0xffff);
sin6->sin6_scope_id = 0;
}
return 0;
}
/*
* generate standard sockaddr_in6 from embedded form.
*/
int
sa6_recoverscope(struct sockaddr_in6 *sin6)
{
char ip6buf[INET6_ADDRSTRLEN];
u_int32_t zoneid;
if (sin6->sin6_scope_id != 0) {
log(LOG_NOTICE,
"sa6_recoverscope: assumption failure (non 0 ID): %s%%%d\n",
ip6_sprintf(ip6buf, &sin6->sin6_addr), sin6->sin6_scope_id);
/* XXX: proceed anyway... */
}
if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr) ||
IN6_IS_ADDR_MC_INTFACELOCAL(&sin6->sin6_addr)) {
/*
* KAME assumption: link id == interface id
*/
zoneid = ntohs(sin6->sin6_addr.s6_addr16[1]);
if (zoneid) {
/* sanity check */
if (zoneid < 0 || V_if_index < zoneid)
return (ENXIO);
if (!ifnet_byindex(zoneid))
return (ENXIO);
sin6->sin6_addr.s6_addr16[1] = 0;
sin6->sin6_scope_id = zoneid;
}
}
return 0;
}
/*
* Determine the appropriate scope zone ID for in6 and ifp. If ret_id is
* non NULL, it is set to the zone ID. If the zone ID needs to be embedded
* in the in6_addr structure, in6 will be modified.
*
* ret_id - unnecessary?
*/
int
in6_setscope(struct in6_addr *in6, struct ifnet *ifp, u_int32_t *ret_id)
{
int scope;
u_int32_t zoneid = 0;
struct scope6_id *sid;
IF_AFDATA_LOCK(ifp);
sid = SID(ifp);
#ifdef DIAGNOSTIC
if (sid == NULL) { /* should not happen */
panic("in6_setscope: scope array is NULL");
/* NOTREACHED */
}
#endif
/*
* special case: the loopback address can only belong to a loopback
* interface.
*/
if (IN6_IS_ADDR_LOOPBACK(in6)) {
if (!(ifp->if_flags & IFF_LOOPBACK)) {
IF_AFDATA_UNLOCK(ifp);
return (EINVAL);
} else {
if (ret_id != NULL)
*ret_id = 0; /* there's no ambiguity */
IF_AFDATA_UNLOCK(ifp);
return (0);
}
}
scope = in6_addrscope(in6);
SCOPE6_LOCK();
switch (scope) {
case IPV6_ADDR_SCOPE_INTFACELOCAL: /* should be interface index */
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_INTFACELOCAL];
break;
case IPV6_ADDR_SCOPE_LINKLOCAL:
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL];
break;
case IPV6_ADDR_SCOPE_SITELOCAL:
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL];
break;
case IPV6_ADDR_SCOPE_ORGLOCAL:
zoneid = sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL];
break;
default:
zoneid = 0; /* XXX: treat as global. */
break;
}
SCOPE6_UNLOCK();
IF_AFDATA_UNLOCK(ifp);
if (ret_id != NULL)
*ret_id = zoneid;
if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6))
in6->s6_addr16[1] = htons(zoneid & 0xffff); /* XXX */
return (0);
}
/*
* Just clear the embedded scope identifier. Return 0 if the original address
* is intact; return non 0 if the address is modified.
*/
int
in6_clearscope(struct in6_addr *in6)
{
int modified = 0;
if (IN6_IS_SCOPE_LINKLOCAL(in6) || IN6_IS_ADDR_MC_INTFACELOCAL(in6)) {
if (in6->s6_addr16[1] != 0)
modified = 1;
in6->s6_addr16[1] = 0;
}
return (modified);
}

View File

@@ -0,0 +1,60 @@
/*-
* Copyright (C) 2000 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.
*
* $KAME: scope6_var.h,v 1.4 2000/05/18 15:03:27 jinmei Exp $
* $FreeBSD$
*/
#ifndef _NETINET6_SCOPE6_VAR_HH_
#define _NETINET6_SCOPE6_VAR_HH_
#ifdef _KERNEL
struct scope6_id {
/*
* 16 is correspondent to 4bit multicast scope field.
* i.e. from node-local to global with some reserved/unassigned types.
*/
u_int32_t s6id_list[16];
};
void scope6_init __P((void));
struct scope6_id *scope6_ifattach __P((struct ifnet *));
void scope6_ifdetach __P((struct scope6_id *));
int scope6_set __P((struct ifnet *, struct scope6_id *));
int scope6_get __P((struct ifnet *, struct scope6_id *));
void scope6_setdefault __P((struct ifnet *));
int scope6_get_default __P((struct scope6_id *));
u_int32_t scope6_in6_addrscope __P((struct in6_addr *));
u_int32_t scope6_addr2default __P((struct in6_addr *));
int sa6_embedscope __P((struct sockaddr_in6 *, int));
int sa6_recoverscope __P((struct sockaddr_in6 *));
int in6_setscope __P((struct in6_addr *, struct ifnet *, u_int32_t *));
int in6_clearscope __P((struct in6_addr *));
#endif /* _KERNEL */
#endif /* _NETINET6_SCOPE6_VAR_HH_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
/*-
* Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* b) 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.
*
* c) Neither the name of Cisco Systems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
/* $KAME: sctp6_var.h,v 1.7 2004/08/17 04:06:22 itojun Exp $ */
#ifndef _NETINET6_SCTP6_VAR_HH_
#define _NETINET6_SCTP6_VAR_HH_
#include <rtems/freebsd/sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* TODO __Userspace__ IPv6 stuff... */
#if defined(_KERNEL)
SYSCTL_DECL(_net_inet6_sctp6);
extern struct pr_usrreqs sctp6_usrreqs;
int sctp6_input __P((struct mbuf **, int *, int));
int sctp6_output
__P((struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
struct mbuf *, struct proc *));
void sctp6_ctlinput __P((int, struct sockaddr *, void *));
extern void sctp6_notify(struct sctp_inpcb *inp,
struct icmp6_hdr *icmph,
struct sctphdr *sh,
struct sockaddr *to,
struct sctp_tcb *stcb,
struct sctp_nets *net);
#endif /* _KERNEL */
#endif

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.
*/
/*-
* 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.
* 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_HH_
#define _NETINET_TCP6_VAR_HH_
#ifdef _KERNEL
#ifdef SYSCTL_DECL
SYSCTL_DECL(_net_inet6_tcp6);
VNET_DECLARE(int, tcp_v6mssdflt); /* XXX */
#define V_tcp_v6mssdflt VNET(tcp_v6mssdflt)
#endif
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(struct in_conninfo *);
extern struct pr_usrreqs tcp6_usrreqs;
#endif /* _KERNEL */
#endif /* _NETINET_TCP6_VAR_HH_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,75 @@
/*-
* 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.
*/
/*-
* 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.
* 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
* $FreeBSD$
*/
#ifndef _NETINET6_UDP6_VAR_HH_
#define _NETINET6_UDP6_VAR_HH_
#ifdef _KERNEL
SYSCTL_DECL(_net_inet6_udp6);
extern struct pr_usrreqs udp6_usrreqs;
void udp6_ctlinput(int, struct sockaddr *, void *);
int udp6_input(struct mbuf **, int *, int);
#endif
#endif /*_NETINET6_UDP6_VAR_HH_*/