Date: Tue, 29 Jul 2014 23:06:06 +0000 (UTC) From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r269277 - projects/ipfw/sys/netpfil/ipfw Message-ID: <201407292306.s6TN660F020755@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: melifaro Date: Tue Jul 29 23:06:06 2014 New Revision: 269277 URL: http://svnweb.freebsd.org/changeset/base/269277 Log: * Introduce ipfw_ctl3() handler and move all IP_FW3 opcodes there. The long-term goal is to switch remaining opcodes to IP_FW3 versions and use ipfw_ctl3() as default handler simplifying ipfw(4) interaction with external world. Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Tue Jul 29 22:44:26 2014 (r269276) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Tue Jul 29 23:06:06 2014 (r269277) @@ -496,6 +496,7 @@ int ipfw_list_ifaces(struct ip_fw_chain /* In ip_fw_sockopt.c */ int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id); int ipfw_ctl(struct sockopt *sopt); +int ipfw_ctl3(struct sockopt *sopt); int ipfw_chk(struct ip_fw_args *args); void ipfw_reap_rules(struct ip_fw *head); void ipfw_init_counters(void); Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Tue Jul 29 22:44:26 2014 (r269276) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Tue Jul 29 23:06:06 2014 (r269277) @@ -1719,28 +1719,26 @@ add_entry(struct ip_fw_chain *chain, str return (error); } -/** - * {set|get}sockopt parser. - */ int -ipfw_ctl(struct sockopt *sopt) +ipfw_ctl3(struct sockopt *sopt) { -#define RULE_MAXSIZE (256*sizeof(u_int32_t)) int error; size_t bsize_max, size, valsize; - struct ip_fw *buf; - struct ip_fw_rule0 *rule; struct ip_fw_chain *chain; - u_int32_t rulenum[2]; uint32_t opt; char xbuf[128]; struct sockopt_data sdata; ip_fw3_opheader *op3 = NULL; - struct rule_check_info ci; + /* Do not check privs twice untile we're called from ipfw_ctl() */ +#if 0 error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW); - if (error) + if (error != 0) return (error); +#endif + + if (sopt->sopt_name != IP_FW3) + return (ENOTSUP); chain = &V_layer3_chain; error = 0; @@ -1749,14 +1747,12 @@ ipfw_ctl(struct sockopt *sopt) valsize = sopt->sopt_valsize; memset(&sdata, 0, sizeof(sdata)); /* Read op3 header first to determine actual operation */ - if ((opt = sopt->sopt_name) == IP_FW3) { - op3 = (ip_fw3_opheader *)xbuf; - error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3)); - if (error != 0) - return (error); - opt = op3->opcode; - sopt->sopt_valsize = valsize; - } + op3 = (ip_fw3_opheader *)xbuf; + error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3)); + if (error != 0) + return (error); + opt = op3->opcode; + sopt->sopt_valsize = valsize; /* * Disallow modifications in really-really secure mode, but still allow @@ -1765,59 +1761,186 @@ ipfw_ctl(struct sockopt *sopt) if (opt == IP_FW_ADD || (sopt->sopt_dir == SOPT_SET && opt != IP_FW_RESETLOG)) { error = securelevel_ge(sopt->sopt_td->td_ucred, 3); - if (error != 0) { - if (sdata.kbuf != xbuf) - free(sdata.kbuf, M_TEMP); + if (error != 0) return (error); - } } - if (op3 != NULL) { + /* + * Determine buffer size: + * use on-stack xbuf for short request, + * allocate sliding-window buf for data export or + * contigious buffer for special ops. + */ + bsize_max = IP_FW3_WRITEBUF; + if (opt == IP_FW_ADD) + bsize_max = IP_FW3_READBUF; - /* - * Determine buffer size: - * use on-stack xbuf for short request, - * allocate sliding-window buf for data export or - * contigious buffer for special ops. - */ - bsize_max = IP_FW3_WRITEBUF; - if (opt == IP_FW_ADD) - bsize_max = IP_FW3_READBUF; + /* + * Fill in sockopt_data structure that may be useful for + * IP_FW3 get requests. + */ - /* - * Fill in sockopt_data structure that may be useful for - * IP_FW3 get requests. - */ + if (valsize <= sizeof(xbuf)) { + sdata.kbuf = xbuf; + sdata.ksize = sizeof(xbuf); + sdata.kavail = valsize; + } else { + if (valsize < bsize_max) + size = valsize; + else + size = bsize_max; + + sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO); + sdata.ksize = size; + sdata.kavail = size; + } + + sdata.sopt = sopt; + sdata.valsize = valsize; + + /* + * Copy either all request (if valsize < bsize_max) + * or first bsize_max bytes to guarantee most consumers + * that all necessary data has been copied). + * Anyway, copy not less than sizeof(ip_fw3_opheader). + */ + if ((error = sooptcopyin(sopt, sdata.kbuf, sdata.ksize, + sizeof(ip_fw3_opheader))) != 0) + return (error); + op3 = (ip_fw3_opheader *)sdata.kbuf; + opt = op3->opcode; + + switch (opt) { + case IP_FW_XGET: + error = dump_config(chain, &sdata); + break; + + case IP_FW_XIFLIST: + error = ipfw_list_ifaces(chain, &sdata); + break; + + case IP_FW_XADD: + error = add_entry(chain, &sdata); + break; + /*--- TABLE opcodes ---*/ + case IP_FW_TABLE_XCREATE: + error = ipfw_create_table(chain, op3, &sdata); + break; + + case IP_FW_TABLE_XDESTROY: + case IP_FW_TABLE_XFLUSH: + error = ipfw_flush_table(chain, op3, &sdata); + break; - if (valsize <= sizeof(xbuf)) { - sdata.kbuf = xbuf; - sdata.ksize = sizeof(xbuf); - sdata.kavail = valsize; - } else { - if (valsize < bsize_max) - size = valsize; - else - size = bsize_max; - - sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO); - sdata.ksize = size; - sdata.kavail = size; + case IP_FW_TABLE_XINFO: + error = ipfw_describe_table(chain, &sdata); + break; + + case IP_FW_TABLES_XGETSIZE: + error = ipfw_listsize_tables(chain, &sdata); + break; + + case IP_FW_TABLES_XLIST: + error = ipfw_list_tables(chain, &sdata); + break; + + case IP_FW_TABLE_XLIST: + error = ipfw_dump_table(chain, op3, &sdata); + break; + + case IP_FW_TABLE_XADD: + case IP_FW_TABLE_XDEL: + error = ipfw_manage_table_ent(chain, op3, &sdata); + break; + + case IP_FW_TABLE_XFIND: + error = ipfw_find_table_entry(chain, op3, &sdata); + break; + + case IP_FW_TABLES_ALIST: + error = ipfw_list_table_algo(chain, &sdata); + break; + + case IP_FW_TABLE_XGETSIZE: + { + uint32_t *tbl; + struct tid_info ti; + + if (IP_FW3_OPLENGTH(sopt) < sizeof(uint32_t)) { + error = EINVAL; + break; + } + + tbl = (uint32_t *)(op3 + 1); + + memset(&ti, 0, sizeof(ti)); + ti.uidx = *tbl; + IPFW_UH_RLOCK(chain); + error = ipfw_count_xtable(chain, &ti, tbl); + IPFW_UH_RUNLOCK(chain); + if (error) + break; + error = sooptcopyout(sopt, op3, sopt->sopt_valsize); } + break; + + default: + printf("ipfw: ipfw_ctl3 invalid option %d\n", opt); + error = EINVAL; + } + + /* Flush state and free buffers */ + if (error == 0) + error = ipfw_flush_sopt_data(&sdata); + else + ipfw_flush_sopt_data(&sdata); - sdata.sopt = sopt; - sdata.valsize = valsize; + if (sdata.kbuf != xbuf) + free(sdata.kbuf, M_TEMP); - /* - * Copy either all request (if valsize < bsize_max) - * or first bsize_max bytes to guarantee most consumers - * that all necessary data has been copied). - * Anyway, copy not less than sizeof(ip_fw3_opheader). - */ - if ((error = sooptcopyin(sopt, sdata.kbuf, sdata.ksize, - sizeof(ip_fw3_opheader))) != 0) + return (error); +} + +/** + * {set|get}sockopt parser. + */ +int +ipfw_ctl(struct sockopt *sopt) +{ +#define RULE_MAXSIZE (256*sizeof(u_int32_t)) + int error; + size_t size, valsize; + struct ip_fw *buf; + struct ip_fw_rule0 *rule; + struct ip_fw_chain *chain; + u_int32_t rulenum[2]; + uint32_t opt; + struct rule_check_info ci; + + error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW); + if (error) + return (error); + + chain = &V_layer3_chain; + error = 0; + + /* Save original valsize before it is altered via sooptcopyin() */ + valsize = sopt->sopt_valsize; + opt = sopt->sopt_name; + + /* Pass IP_FW3 to a new handler */ + if (opt == IP_FW3) + return (ipfw_ctl3(sopt)); + + /* + * Disallow modifications in really-really secure mode, but still allow + * the logging counters to be reset. + */ + if (opt == IP_FW_ADD || + (sopt->sopt_dir == SOPT_SET && opt != IP_FW_RESETLOG)) { + error = securelevel_ge(sopt->sopt_td->td_ucred, 3); + if (error != 0) return (error); - op3 = (ip_fw3_opheader *)sdata.kbuf; - opt = op3->opcode; } switch (opt) { @@ -1855,18 +1978,6 @@ ipfw_ctl(struct sockopt *sopt) } break; - case IP_FW_XGET: /* IP_FW3 */ - error = dump_config(chain, &sdata); - break; - - case IP_FW_XIFLIST: /* IP_FW3 */ - error = ipfw_list_ifaces(chain, &sdata); - break; - - case IP_FW_XADD: /* IP_FW3 */ - error = add_entry(chain, &sdata); - break; - case IP_FW_FLUSH: /* locking is done within del_entry() */ error = del_entry(chain, 0); /* special case, rule=0, cmd=0 means all */ @@ -1969,43 +2080,6 @@ ipfw_ctl(struct sockopt *sopt) break; /*--- TABLE opcodes ---*/ - case IP_FW_TABLE_XCREATE: /* IP_FW3 */ - error = ipfw_create_table(chain, op3, &sdata); - break; - - case IP_FW_TABLE_XDESTROY: /* IP_FW3 */ - case IP_FW_TABLE_XFLUSH: /* IP_FW3 */ - error = ipfw_flush_table(chain, op3, &sdata); - break; - - case IP_FW_TABLE_XINFO: /* IP_FW3 */ - error = ipfw_describe_table(chain, &sdata); - break; - - case IP_FW_TABLES_XGETSIZE: /* IP_FW3 */ - error = ipfw_listsize_tables(chain, &sdata); - break; - - case IP_FW_TABLES_XLIST: /* IP_FW3 */ - error = ipfw_list_tables(chain, &sdata); - break; - - case IP_FW_TABLE_XLIST: /* IP_FW3 */ - error = ipfw_dump_table(chain, op3, &sdata); - break; - - case IP_FW_TABLE_XADD: /* IP_FW3 */ - case IP_FW_TABLE_XDEL: /* IP_FW3 */ - error = ipfw_manage_table_ent(chain, op3, &sdata); - break; - case IP_FW_TABLE_XFIND: /* IP_FW3 */ - error = ipfw_find_table_entry(chain, op3, &sdata); - break; - case IP_FW_TABLES_ALIST: /* IP_FW3 */ - error = ipfw_list_table_algo(chain, &sdata); - break; - - /*--- LEGACY API ---*/ case IP_FW_TABLE_ADD: case IP_FW_TABLE_DEL: { @@ -2100,28 +2174,6 @@ ipfw_ctl(struct sockopt *sopt) } break; - case IP_FW_TABLE_XGETSIZE: /* IP_FW3 */ - { - uint32_t *tbl; - struct tid_info ti; - - if (IP_FW3_OPLENGTH(sopt) < sizeof(uint32_t)) { - error = EINVAL; - break; - } - - tbl = (uint32_t *)(op3 + 1); - - memset(&ti, 0, sizeof(ti)); - ti.uidx = *tbl; - IPFW_UH_RLOCK(chain); - error = ipfw_count_xtable(chain, &ti, tbl); - IPFW_UH_RUNLOCK(chain); - if (error) - break; - error = sooptcopyout(sopt, op3, sopt->sopt_valsize); - } - break; /*--- NAT operations are protected by the IPFW_LOCK ---*/ case IP_FW_NAT_CFG: if (IPFW_NAT_LOADED) @@ -2168,17 +2220,6 @@ ipfw_ctl(struct sockopt *sopt) error = EINVAL; } - if (op3 != NULL) { - /* Flush state and free buffers */ - if (error == 0) - error = ipfw_flush_sopt_data(&sdata); - else - ipfw_flush_sopt_data(&sdata); - - if (sdata.kbuf != xbuf) - free(sdata.kbuf, M_TEMP); - } - return (error); #undef RULE_MAXSIZE }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407292306.s6TN660F020755>