diff options
author | tuexen <tuexen@FreeBSD.org> | 2012-06-12 13:57:56 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2012-06-12 13:57:56 +0000 |
commit | 66a991aeee1041abe4bfaca27b4d3d2ddaee1161 (patch) | |
tree | 5992974a94485f4516a4dd5612f2701a79f0244c /sys/netinet6/ip6_input.c | |
parent | 7aa509cdffbd790413799924fc3d5f55055e2be0 (diff) | |
download | FreeBSD-src-66a991aeee1041abe4bfaca27b4d3d2ddaee1161.zip FreeBSD-src-66a991aeee1041abe4bfaca27b4d3d2ddaee1161.tar.gz |
Deliver IPV6_TCLASS, IPV6_HOPLIMIT and IPV6_PKTINFO cmsgs (if
requested) on IPV6 sockets, which have been marked to be not IPV6_V6ONLY,
for each received IPV4 packet.
MFC after: 3 days
Diffstat (limited to 'sys/netinet6/ip6_input.c')
-rw-r--r-- | sys/netinet6/ip6_input.c | 90 |
1 files changed, 65 insertions, 25 deletions
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index e984534..f5ec27a 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1321,19 +1321,28 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp, } #endif - if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { - if (v4only != NULL) - *v4only = 1; - return (mp); - } - #define IS2292(inp, x, y) (((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y)) /* RFC 2292 sec. 5 */ if ((inp->inp_flags & IN6P_PKTINFO) != 0) { struct in6_pktinfo pi6; - bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); - in6_clearscope(&pi6.ipi6_addr); /* XXX */ + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { +#ifdef INET + struct ip *ip; + + ip = mtod(m, struct ip *); + pi6.ipi6_addr.s6_addr32[0] = 0; + pi6.ipi6_addr.s6_addr32[1] = 0; + pi6.ipi6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP; + pi6.ipi6_addr.s6_addr32[3] = ip->ip_dst.s_addr; +#else + /* We won't hit this code */ + bzero(&pi6.ipi6_addr, sizeof(struct in6_addr)); +#endif + } else { + bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); + in6_clearscope(&pi6.ipi6_addr); /* XXX */ + } pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0; @@ -1345,8 +1354,21 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp, } if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) { - int hlim = ip6->ip6_hlim & 0xff; + int hlim; + + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { +#ifdef INET + struct ip *ip; + ip = mtod(m, struct ip *); + hlim = ip->ip_ttl; +#else + /* We won't hit this code */ + hlim = 0; +#endif + } else { + hlim = ip6->ip6_hlim & 0xff; + } *mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int), IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), IPPROTO_IPV6); @@ -1354,8 +1376,40 @@ ip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp, mp = &(*mp)->m_next; } - if (v4only != NULL) - *v4only = 0; + if ((inp->inp_flags & IN6P_TCLASS) != 0) { + int tclass; + + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { +#ifdef INET + struct ip *ip; + + ip = mtod(m, struct ip *); + tclass = ip->ip_tos; +#else + /* We won't hit this code */ + tclass = 0; +#endif + } else { + u_int32_t flowinfo; + + flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); + flowinfo >>= 20; + tclass = flowinfo & 0xff; + } + *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(int), + IPV6_TCLASS, IPPROTO_IPV6); + if (*mp) + mp = &(*mp)->m_next; + } + + if (v4only != NULL) { + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { + *v4only = 1; + } else { + *v4only = 0; + } + } + return (mp); } @@ -1369,20 +1423,6 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp) if (v4only) return; - if ((in6p->inp_flags & IN6P_TCLASS) != 0) { - u_int32_t flowinfo; - int tclass; - - flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); - flowinfo >>= 20; - - tclass = flowinfo & 0xff; - *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(tclass), - IPV6_TCLASS, IPPROTO_IPV6); - if (*mp) - mp = &(*mp)->m_next; - } - /* * IPV6_HOPOPTS socket option. Recall that we required super-user * privilege for the option (see ip6_ctloutput), but it might be too |