Author: tuexen
Date: Tue Jun 12 13:57:56 2012
New Revision: 236958
URL: http://svn.freebsd.org/changeset/base/236958

Log:
  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

Modified:
  head/sys/netinet6/ip6_input.c

Modified: head/sys/netinet6/ip6_input.c
==============================================================================
--- head/sys/netinet6/ip6_input.c       Tue Jun 12 13:31:32 2012        
(r236957)
+++ head/sys/netinet6/ip6_input.c       Tue Jun 12 13:57:56 2012        
(r236958)
@@ -1321,19 +1321,28 @@ ip6_savecontrol_v4(struct inpcb *inp, st
        }
 #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, st
        }
 
        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, st
                        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, stru
        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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to