Author: ae
Date: Tue Jun 14 07:20:16 2011
New Revision: 223073
URL: http://svn.freebsd.org/changeset/base/223073

Log:
  Add IPv6 support to the ipfw uid/gid check. Pass an ip_fw_args structure
  to the check_uidgid() function, since it contains all needed arguments
  and also pointer to mbuf and now it is possible use in_pcblookup_mbuf()
  function.
  
  Since i can not test it for the non-FreeBSD case, i keep this ifdef
  unchanged.
  
  Tested by:    Alexander V. Chernikov
  MFC after:    3 weeks

Modified:
  head/sys/netinet/ipfw/ip_fw2.c

Modified: head/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- head/sys/netinet/ipfw/ip_fw2.c      Tue Jun 14 06:45:48 2011        
(r223072)
+++ head/sys/netinet/ipfw/ip_fw2.c      Tue Jun 14 07:20:16 2011        
(r223073)
@@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip6.h>
 #include <netinet/icmp6.h>
 #ifdef INET6
+#include <netinet6/in6_pcb.h>
 #include <netinet6/scope6_var.h>
 #include <netinet6/ip6_var.h>
 #endif
@@ -646,21 +647,27 @@ send_reject(struct ip_fw_args *args, int
  * we tried and failed, or any other value if successful.
  */
 static int
-check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
-    struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip,
-    u_int16_t src_port, int *ugid_lookupp,
-    struct ucred **uc, struct inpcb *inp)
+check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp,
+    struct ucred **uc)
 {
 #ifndef __FreeBSD__
+       /* XXX */
        return cred_check(insn, proto, oif,
            dst_ip, dst_port, src_ip, src_port,
            (struct bsd_ucred *)uc, ugid_lookupp, ((struct mbuf *)inp)->m_skb);
 #else  /* FreeBSD */
+       struct in_addr src_ip, dst_ip;
        struct inpcbinfo *pi;
+       struct ipfw_flow_id *id;
+       struct inpcb *pcb, *inp;
+       struct ifnet *oif;
        int lookupflags;
-       struct inpcb *pcb;
        int match;
 
+       id = &args->f_id;
+       inp = args->inp;
+       oif = args->oif;
+
        /*
         * Check to see if the UDP or TCP stack supplied us with
         * the PCB. If so, rather then holding a lock and looking
@@ -681,10 +688,10 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
         */
        if (*ugid_lookupp == -1)
                return (0);
-       if (proto == IPPROTO_TCP) {
+       if (id->proto == IPPROTO_TCP) {
                lookupflags = 0;
                pi = &V_tcbinfo;
-       } else if (proto == IPPROTO_UDP) {
+       } else if (id->proto == IPPROTO_UDP) {
                lookupflags = INPLOOKUP_WILDCARD;
                pi = &V_udbinfo;
        } else
@@ -692,19 +699,36 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
        lookupflags |= INPLOOKUP_RLOCKPCB;
        match = 0;
        if (*ugid_lookupp == 0) {
-               /*
-                * XXXRW: If we had the mbuf here, could use
-                * in_pcblookup_mbuf().
-                */
-               pcb =  (oif) ?
-                       in_pcblookup(pi,
-                               dst_ip, htons(dst_port),
-                               src_ip, htons(src_port),
-                               lookupflags, oif) :
-                       in_pcblookup(pi,
-                               src_ip, htons(src_port),
-                               dst_ip, htons(dst_port),
-                               lookupflags, NULL);
+               if (id->addr_type == 6) {
+#ifdef INET6
+                       if (oif == NULL)
+                               pcb = in6_pcblookup_mbuf(pi,
+                                   &id->src_ip6, htons(id->src_port),
+                                   &id->dst_ip6, htons(id->dst_port),
+                                   lookupflags, oif, args->m);
+                       else
+                               pcb = in6_pcblookup_mbuf(pi,
+                                   &id->dst_ip6, htons(id->dst_port),
+                                   &id->src_ip6, htons(id->src_port),
+                                   lookupflags, oif, args->m);
+#else
+                       *ugid_lookupp = -1;
+                       return (0);
+#endif
+               } else {
+                       src_ip.s_addr = htonl(id->src_ip);
+                       dst_ip.s_addr = htonl(id->dst_ip);
+                       if (oif == NULL)
+                               pcb = in_pcblookup_mbuf(pi,
+                                   src_ip, htons(id->src_port),
+                                   dst_ip, htons(id->dst_port),
+                                   lookupflags, oif, args->m);
+                       else
+                               pcb = in_pcblookup_mbuf(pi,
+                                   dst_ip, htons(id->dst_port),
+                                   src_ip, htons(id->src_port),
+                                   lookupflags, oif, args->m);
+               }
                if (pcb != NULL) {
                        INP_RLOCK_ASSERT(pcb);
                        *uc = crhold(pcb->inp_cred);
@@ -719,14 +743,14 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
                        *ugid_lookupp = -1;
                        return (0);
                }
-       } 
+       }
        if (insn->o.opcode == O_UID)
                match = ((*uc)->cr_uid == (uid_t)insn->d[0]);
        else if (insn->o.opcode == O_GID)
                match = groupmember((gid_t)insn->d[0], *uc);
        else if (insn->o.opcode == O_JAIL)
                match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
-       return match;
+       return (match);
 #endif /* __FreeBSD__ */
 }
 
@@ -1264,22 +1288,17 @@ do {                                                    
        \
                                 * as this ensures that we have a
                                 * packet with the ports info.
                                 */
-                               if (offset!=0)
-                                       break;
-                               if (is_ipv6) /* XXX to be fixed later */
+                               if (offset != 0)
                                        break;
                                if (proto == IPPROTO_TCP ||
                                    proto == IPPROTO_UDP)
                                        match = check_uidgid(
                                                    (ipfw_insn_u32 *)cmd,
-                                                   proto, oif,
-                                                   dst_ip, dst_port,
-                                                   src_ip, src_port, 
&ucred_lookup,
+                                                   args, &ucred_lookup,
 #ifdef __FreeBSD__
-                                                   &ucred_cache, args->inp);
+                                                   &ucred_cache);
 #else
-                                                   (void *)&ucred_cache,
-                                                   (struct inpcb *)args->m);
+                                                   (void *)&ucred_cache);
 #endif
                                break;
 
@@ -1394,18 +1413,15 @@ do {                                                    
        \
                                        else if (v == 4 || v == 5) {
                                            check_uidgid(
                                                (ipfw_insn_u32 *)cmd,
-                                               proto, oif,
-                                               dst_ip, dst_port,
-                                               src_ip, src_port, &ucred_lookup,
+                                               args, &ucred_lookup,
 #ifdef __FreeBSD__
-                                               &ucred_cache, args->inp);
+                                               &ucred_cache);
                                            if (v == 4 /* O_UID */)
                                                key = ucred_cache->cr_uid;
                                            else if (v == 5 /* O_JAIL */)
                                                key = 
ucred_cache->cr_prison->pr_id;
 #else /* !__FreeBSD__ */
-                                               (void *)&ucred_cache,
-                                               (struct inpcb *)args->m);
+                                               (void *)&ucred_cache);
                                            if (v ==4 /* O_UID */)
                                                key = ucred_cache.uid;
                                            else if (v == 5 /* O_JAIL */)
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to