Deleted Added
full compact
ip_fw2.c (193894) ip_fw2.c (194498)
1/*-
2 * Copyright (c) 2002 Luigi Rizzo, Universita` di Pisa
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 10 unchanged lines hidden (view full) ---

19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2002 Luigi Rizzo, Universita` di Pisa
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 10 unchanged lines hidden (view full) ---

19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <sys/cdefs.h>
27__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 193894 2009-06-10 10:34:59Z luigi $");
27__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw2.c 194498 2009-06-19 17:10:35Z brooks $");
28
29#define DEB(x)
30#define DDB(x) x
31
32/*
33 * Implement IP packet firewall (new version)
34 */
35

--- 94 unchanged lines hidden (view full) ---

130#else
131static int default_to_accept;
132#endif
133static uma_zone_t ipfw_dyn_rule_zone;
134
135struct ip_fw *ip_fw_default_rule;
136
137/*
28
29#define DEB(x)
30#define DDB(x) x
31
32/*
33 * Implement IP packet firewall (new version)
34 */
35

--- 94 unchanged lines hidden (view full) ---

130#else
131static int default_to_accept;
132#endif
133static uma_zone_t ipfw_dyn_rule_zone;
134
135struct ip_fw *ip_fw_default_rule;
136
137/*
138 * Data structure to cache our ucred related
139 * information. This structure only gets used if
140 * the user specified UID/GID based constraints in
141 * a firewall rule.
142 */
143struct ip_fw_ugid {
144 gid_t fw_groups[NGROUPS];
145 int fw_ngroups;
146 uid_t fw_uid;
147 int fw_prid;
148};
149
150/*
151 * list of rules for layer 3
152 */
153#ifdef VIMAGE_GLOBALS
154struct ip_fw_chain layer3_chain;
155#endif
156
157MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
158MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");

--- 1845 unchanged lines hidden (view full) ---

2004 if (tbl->tbl >= IPFW_TABLES_MAX)
2005 return (EINVAL);
2006 rnh = ch->tables[tbl->tbl];
2007 tbl->cnt = 0;
2008 rnh->rnh_walktree(rnh, dump_table_entry, tbl);
2009 return (0);
2010}
2011
138 * list of rules for layer 3
139 */
140#ifdef VIMAGE_GLOBALS
141struct ip_fw_chain layer3_chain;
142#endif
143
144MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
145MALLOC_DEFINE(M_IPFW_TBL, "ipfw_tbl", "IpFw tables");

--- 1845 unchanged lines hidden (view full) ---

1991 if (tbl->tbl >= IPFW_TABLES_MAX)
1992 return (EINVAL);
1993 rnh = ch->tables[tbl->tbl];
1994 tbl->cnt = 0;
1995 rnh->rnh_walktree(rnh, dump_table_entry, tbl);
1996 return (0);
1997}
1998
2012static void
2013fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp)
2014{
2015 struct ucred *cr;
2016
2017 cr = inp->inp_cred;
2018 ugp->fw_prid = jailed(cr) ? cr->cr_prison->pr_id : -1;
2019 ugp->fw_uid = cr->cr_uid;
2020 ugp->fw_ngroups = cr->cr_ngroups;
2021 bcopy(cr->cr_groups, ugp->fw_groups, sizeof(ugp->fw_groups));
2022}
2023
2024static int
2025check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
2026 struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip,
1999static int
2000check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
2001 struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip,
2027 u_int16_t src_port, struct ip_fw_ugid *ugp, int *ugid_lookupp,
2002 u_int16_t src_port, struct ucred **uc, int *ugid_lookupp,
2028 struct inpcb *inp)
2029{
2030 INIT_VNET_INET(curvnet);
2031 struct inpcbinfo *pi;
2032 int wildcard;
2033 struct inpcb *pcb;
2034 int match;
2003 struct inpcb *inp)
2004{
2005 INIT_VNET_INET(curvnet);
2006 struct inpcbinfo *pi;
2007 int wildcard;
2008 struct inpcb *pcb;
2009 int match;
2035 gid_t *gp;
2036
2037 /*
2038 * Check to see if the UDP or TCP stack supplied us with
2039 * the PCB. If so, rather then holding a lock and looking
2040 * up the PCB, we can use the one that was supplied.
2041 */
2042 if (inp && *ugid_lookupp == 0) {
2043 INP_LOCK_ASSERT(inp);
2044 if (inp->inp_socket != NULL) {
2010
2011 /*
2012 * Check to see if the UDP or TCP stack supplied us with
2013 * the PCB. If so, rather then holding a lock and looking
2014 * up the PCB, we can use the one that was supplied.
2015 */
2016 if (inp && *ugid_lookupp == 0) {
2017 INP_LOCK_ASSERT(inp);
2018 if (inp->inp_socket != NULL) {
2045 fill_ugid_cache(inp, ugp);
2019 *uc = crhold(inp->inp_cred);
2046 *ugid_lookupp = 1;
2047 } else
2048 *ugid_lookupp = -1;
2049 }
2050 /*
2051 * If we have already been here and the packet has no
2052 * PCB entry associated with it, then we can safely
2053 * assume that this is a no match.

--- 16 unchanged lines hidden (view full) ---

2070 dst_ip, htons(dst_port),
2071 src_ip, htons(src_port),
2072 wildcard, oif) :
2073 in_pcblookup_hash(pi,
2074 src_ip, htons(src_port),
2075 dst_ip, htons(dst_port),
2076 wildcard, NULL);
2077 if (pcb != NULL) {
2020 *ugid_lookupp = 1;
2021 } else
2022 *ugid_lookupp = -1;
2023 }
2024 /*
2025 * If we have already been here and the packet has no
2026 * PCB entry associated with it, then we can safely
2027 * assume that this is a no match.

--- 16 unchanged lines hidden (view full) ---

2044 dst_ip, htons(dst_port),
2045 src_ip, htons(src_port),
2046 wildcard, oif) :
2047 in_pcblookup_hash(pi,
2048 src_ip, htons(src_port),
2049 dst_ip, htons(dst_port),
2050 wildcard, NULL);
2051 if (pcb != NULL) {
2078 fill_ugid_cache(pcb, ugp);
2052 *uc = crhold(inp->inp_cred);
2079 *ugid_lookupp = 1;
2080 }
2081 INP_INFO_RUNLOCK(pi);
2082 if (*ugid_lookupp == 0) {
2083 /*
2084 * If the lookup did not yield any results, there
2085 * is no sense in coming back and trying again. So
2086 * we can set lookup to -1 and ensure that we wont
2087 * bother the pcb system again.
2088 */
2089 *ugid_lookupp = -1;
2090 return (0);
2091 }
2092 }
2093 if (insn->o.opcode == O_UID)
2053 *ugid_lookupp = 1;
2054 }
2055 INP_INFO_RUNLOCK(pi);
2056 if (*ugid_lookupp == 0) {
2057 /*
2058 * If the lookup did not yield any results, there
2059 * is no sense in coming back and trying again. So
2060 * we can set lookup to -1 and ensure that we wont
2061 * bother the pcb system again.
2062 */
2063 *ugid_lookupp = -1;
2064 return (0);
2065 }
2066 }
2067 if (insn->o.opcode == O_UID)
2094 match = (ugp->fw_uid == (uid_t)insn->d[0]);
2095 else if (insn->o.opcode == O_GID) {
2096 for (gp = ugp->fw_groups;
2097 gp < &ugp->fw_groups[ugp->fw_ngroups]; gp++)
2098 if (*gp == (gid_t)insn->d[0]) {
2099 match = 1;
2100 break;
2101 }
2102 } else if (insn->o.opcode == O_JAIL)
2103 match = (ugp->fw_prid == (int)insn->d[0]);
2068 match = ((*uc)->cr_uid == (uid_t)insn->d[0]);
2069 else if (insn->o.opcode == O_GID)
2070 match = groupmember((gid_t)insn->d[0], *uc);
2071 else if (insn->o.opcode == O_JAIL)
2072 match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
2104 return match;
2105}
2106
2107/*
2108 * The main check routine for the firewall.
2109 *
2110 * All arguments are in args so we can modify them and return them
2111 * back to the caller.

--- 61 unchanged lines hidden (view full) ---

2173
2174 /*
2175 * For rules which contain uid/gid or jail constraints, cache
2176 * a copy of the users credentials after the pcb lookup has been
2177 * executed. This will speed up the processing of rules with
2178 * these types of constraints, as well as decrease contention
2179 * on pcb related locks.
2180 */
2073 return match;
2074}
2075
2076/*
2077 * The main check routine for the firewall.
2078 *
2079 * All arguments are in args so we can modify them and return them
2080 * back to the caller.

--- 61 unchanged lines hidden (view full) ---

2142
2143 /*
2144 * For rules which contain uid/gid or jail constraints, cache
2145 * a copy of the users credentials after the pcb lookup has been
2146 * executed. This will speed up the processing of rules with
2147 * these types of constraints, as well as decrease contention
2148 * on pcb related locks.
2149 */
2181 struct ip_fw_ugid fw_ugid_cache;
2182 int ugid_lookup = 0;
2150 struct ucred *ucred_cache = NULL;
2151 int ucred_lookup = 0;
2183
2184 /*
2185 * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG
2186 * associated with a packet input on a divert socket. This
2187 * will allow to distinguish traffic and its direction when
2188 * it originates from a divert socket.
2189 */
2190 u_int divinput_flags = 0;

--- 445 unchanged lines hidden (view full) ---

2636 if (is_ipv6) /* XXX to be fixed later */
2637 break;
2638 if (proto == IPPROTO_TCP ||
2639 proto == IPPROTO_UDP)
2640 match = check_uidgid(
2641 (ipfw_insn_u32 *)cmd,
2642 proto, oif,
2643 dst_ip, dst_port,
2152
2153 /*
2154 * divinput_flags If non-zero, set to the IP_FW_DIVERT_*_FLAG
2155 * associated with a packet input on a divert socket. This
2156 * will allow to distinguish traffic and its direction when
2157 * it originates from a divert socket.
2158 */
2159 u_int divinput_flags = 0;

--- 445 unchanged lines hidden (view full) ---

2605 if (is_ipv6) /* XXX to be fixed later */
2606 break;
2607 if (proto == IPPROTO_TCP ||
2608 proto == IPPROTO_UDP)
2609 match = check_uidgid(
2610 (ipfw_insn_u32 *)cmd,
2611 proto, oif,
2612 dst_ip, dst_port,
2644 src_ip, src_port, &fw_ugid_cache,
2645 &ugid_lookup, args->inp);
2613 src_ip, src_port, &ucred_cache,
2614 &ucred_lookup, args->inp);
2646 break;
2647
2648 case O_RECV:
2649 match = iface_match(m->m_pkthdr.rcvif,
2650 (ipfw_insn_if *)cmd);
2651 break;
2652
2653 case O_XMIT:

--- 611 unchanged lines hidden (view full) ---

3265 break;
3266 mtag = m_tag_get(PACKET_TAG_DIVERT,
3267 sizeof(struct divert_tag),
3268 M_NOWAIT);
3269 if (mtag == NULL) {
3270 /* XXX statistic */
3271 /* drop packet */
3272 IPFW_RUNLOCK(chain);
2615 break;
2616
2617 case O_RECV:
2618 match = iface_match(m->m_pkthdr.rcvif,
2619 (ipfw_insn_if *)cmd);
2620 break;
2621
2622 case O_XMIT:

--- 611 unchanged lines hidden (view full) ---

3234 break;
3235 mtag = m_tag_get(PACKET_TAG_DIVERT,
3236 sizeof(struct divert_tag),
3237 M_NOWAIT);
3238 if (mtag == NULL) {
3239 /* XXX statistic */
3240 /* drop packet */
3241 IPFW_RUNLOCK(chain);
3242 if (ucred_cache != NULL)
3243 crfree(ucred_cache);
3273 return (IP_FW_DENY);
3274 }
3275 dt = (struct divert_tag *)(mtag+1);
3276 dt->cookie = f->rulenum;
3277 if (cmd->arg1 == IP_FW_TABLEARG)
3278 dt->info = tablearg;
3279 else
3280 dt->info = cmd->arg1;

--- 189 unchanged lines hidden (view full) ---

3470
3471 } /* end of inner for, scan opcodes */
3472
3473next_rule:; /* try next rule */
3474
3475 } /* end of outer for, scan rules */
3476 printf("ipfw: ouch!, skip past end of rules, denying packet\n");
3477 IPFW_RUNLOCK(chain);
3244 return (IP_FW_DENY);
3245 }
3246 dt = (struct divert_tag *)(mtag+1);
3247 dt->cookie = f->rulenum;
3248 if (cmd->arg1 == IP_FW_TABLEARG)
3249 dt->info = tablearg;
3250 else
3251 dt->info = cmd->arg1;

--- 189 unchanged lines hidden (view full) ---

3441
3442 } /* end of inner for, scan opcodes */
3443
3444next_rule:; /* try next rule */
3445
3446 } /* end of outer for, scan rules */
3447 printf("ipfw: ouch!, skip past end of rules, denying packet\n");
3448 IPFW_RUNLOCK(chain);
3449 if (ucred_cache != NULL)
3450 crfree(ucred_cache);
3478 return (IP_FW_DENY);
3479
3480done:
3481 /* Update statistics */
3482 f->pcnt++;
3483 f->bcnt += pktlen;
3484 f->timestamp = time_uptime;
3485 IPFW_RUNLOCK(chain);
3451 return (IP_FW_DENY);
3452
3453done:
3454 /* Update statistics */
3455 f->pcnt++;
3456 f->bcnt += pktlen;
3457 f->timestamp = time_uptime;
3458 IPFW_RUNLOCK(chain);
3459 if (ucred_cache != NULL)
3460 crfree(ucred_cache);
3486 return (retval);
3487
3488pullup_failed:
3489 if (V_fw_verbose)
3490 printf("ipfw: pullup failed\n");
3491 return (IP_FW_DENY);
3492}
3493

--- 1260 unchanged lines hidden ---
3461 return (retval);
3462
3463pullup_failed:
3464 if (V_fw_verbose)
3465 printf("ipfw: pullup failed\n");
3466 return (IP_FW_DENY);
3467}
3468

--- 1260 unchanged lines hidden ---