summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet6/ip6_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet6/ip6_output.c')
-rw-r--r--freebsd/sys/netinet6/ip6_output.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/freebsd/sys/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c
index d6d7eb6e..19c430a6 100644
--- a/freebsd/sys/netinet6/ip6_output.c
+++ b/freebsd/sys/netinet6/ip6_output.c
@@ -137,7 +137,7 @@ static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
static int ip6_getpmtu __P((struct route_in6 *, struct route_in6 *,
- struct ifnet *, struct in6_addr *, u_long *, int *));
+ struct ifnet *, struct in6_addr *, u_long *, int *, u_int));
static int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
@@ -232,6 +232,9 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
goto bad;
}
+ if (inp != NULL)
+ M_SETFIB(m, inp->inp_inc.inc_fibnum);
+
finaldst = ip6->ip6_dst;
bzero(&exthdrs, sizeof(exthdrs));
@@ -259,11 +262,11 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
}
+#ifdef IPSEC
/*
* IPSec checking which handles several cases.
* FAST IPSEC: We re-injected the packet.
*/
-#ifdef IPSEC
switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp))
{
case 1: /* Bad packet */
@@ -578,8 +581,8 @@ again:
dst_sa.sin6_family = AF_INET6;
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
- if ((error = in6_selectroute(&dst_sa, opt, im6o, ro,
- &ifp, &rt)) != 0) {
+ if ((error = in6_selectroute_fib(&dst_sa, opt, im6o, ro,
+ &ifp, &rt, inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m))) != 0) {
switch (error) {
case EHOSTUNREACH:
V_ip6stat.ip6s_noroute++;
@@ -747,7 +750,7 @@ again:
/* Determine path MTU. */
if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
- &alwaysfrag)) != 0)
+ &alwaysfrag, inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m))) != 0)
goto bad;
/*
@@ -1011,7 +1014,7 @@ passout:
goto sendorfree;
}
m->m_pkthdr.rcvif = NULL;
- m->m_flags = m0->m_flags & M_COPYFLAGS;
+ m->m_flags = m0->m_flags & M_COPYFLAGS; /* incl. FIB */
*mnext = m;
mnext = &m->m_nextpkt;
m->m_data += max_linkhdr;
@@ -1266,7 +1269,7 @@ ip6_insertfraghdr(struct mbuf *m0, struct mbuf *m, int hlen,
static int
ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
struct ifnet *ifp, struct in6_addr *dst, u_long *mtup,
- int *alwaysfragp)
+ int *alwaysfragp, u_int fibnum)
{
u_int32_t mtu = 0;
int alwaysfrag = 0;
@@ -1288,7 +1291,7 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
sa6_dst->sin6_addr = *dst;
- rtalloc((struct route *)ro_pmtu);
+ in6_rtalloc(ro_pmtu, fibnum);
}
}
if (ro_pmtu->ro_rt) {
@@ -1366,7 +1369,23 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
optval = 0;
uproto = (int)so->so_proto->pr_protocol;
- if (level == IPPROTO_IPV6) {
+ if (level != IPPROTO_IPV6) {
+ error = EINVAL;
+
+ if (sopt->sopt_level == SOL_SOCKET &&
+ sopt->sopt_dir == SOPT_SET) {
+ switch (sopt->sopt_name) {
+ case SO_SETFIB:
+ INP_WLOCK(in6p);
+ in6p->inp_inc.inc_fibnum = so->so_fibnum;
+ INP_WUNLOCK(in6p);
+ error = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
switch (op) {
case SOPT_SET:
@@ -1455,18 +1474,22 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
break;
#define OPTSET(bit) \
do { \
+ INP_WLOCK(in6p); \
if (optval) \
in6p->inp_flags |= (bit); \
else \
in6p->inp_flags &= ~(bit); \
+ INP_WUNLOCK(in6p); \
} while (/*CONSTCOND*/ 0)
#define OPTSET2292(bit) \
do { \
+ INP_WLOCK(in6p); \
in6p->inp_flags |= IN6P_RFC2292; \
if (optval) \
in6p->inp_flags |= (bit); \
else \
in6p->inp_flags &= ~(bit); \
+ INP_WUNLOCK(in6p); \
} while (/*CONSTCOND*/ 0)
#define OPTBIT(bit) (in6p->inp_flags & (bit) ? 1 : 0)
@@ -1720,6 +1743,7 @@ do { \
if (error)
break;
+ INP_WLOCK(in6p);
switch (optval) {
case IPV6_PORTRANGE_DEFAULT:
in6p->inp_flags &= ~(INP_LOWPORT);
@@ -1740,6 +1764,7 @@ do { \
error = EINVAL;
break;
}
+ INP_WUNLOCK(in6p);
break;
#ifdef IPSEC
@@ -1889,7 +1914,8 @@ do { \
* the outgoing interface.
*/
error = ip6_getpmtu(&sro, NULL, NULL,
- &in6p->in6p_faddr, &pmtu, NULL);
+ &in6p->in6p_faddr, &pmtu, NULL,
+ so->so_fibnum);
if (sro.ro_rt)
RTFREE(sro.ro_rt);
if (error)
@@ -1989,8 +2015,6 @@ do { \
}
break;
}
- } else { /* level != IPPROTO_IPV6 */
- error = EINVAL;
}
return (error);
}
@@ -2312,6 +2336,8 @@ copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src, int canwait)
dst->ip6po_hlim = src->ip6po_hlim;
dst->ip6po_tclass = src->ip6po_tclass;
dst->ip6po_flags = src->ip6po_flags;
+ dst->ip6po_minmtu = src->ip6po_minmtu;
+ dst->ip6po_prefer_tempaddr = src->ip6po_prefer_tempaddr;
if (src->ip6po_pktinfo) {
dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo),
M_IP6OPT, canwait);