Deleted Added
full compact
ip_fw_sockopt.c (231076) ip_fw_sockopt.c (232865)
1/*-
2 * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
3 *
4 * Supported by: Valeria Paoli
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

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

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

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

21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_sockopt.c 231076 2012-02-06 11:35:29Z glebius $");
29__FBSDID("$FreeBSD: head/sys/netinet/ipfw/ip_fw_sockopt.c 232865 2012-03-12 14:07:57Z melifaro $");
30
31/*
32 * Sockopt support for ipfw. The routines here implement
33 * the upper half of the ipfw code.
34 */
35
36#include "opt_ipfw.h"
37#include "opt_inet.h"

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

662 cmd->arg1);
663 return (EINVAL);
664 }
665 if (cmdlen != F_INSN_SIZE(ipfw_insn) &&
666 cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1 &&
667 cmdlen != F_INSN_SIZE(ipfw_insn_u32))
668 goto bad_size;
669 break;
30
31/*
32 * Sockopt support for ipfw. The routines here implement
33 * the upper half of the ipfw code.
34 */
35
36#include "opt_ipfw.h"
37#include "opt_inet.h"

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

662 cmd->arg1);
663 return (EINVAL);
664 }
665 if (cmdlen != F_INSN_SIZE(ipfw_insn) &&
666 cmdlen != F_INSN_SIZE(ipfw_insn_u32) + 1 &&
667 cmdlen != F_INSN_SIZE(ipfw_insn_u32))
668 goto bad_size;
669 break;
670
671 case O_MACADDR2:
672 if (cmdlen != F_INSN_SIZE(ipfw_insn_mac))
673 goto bad_size;
674 break;
675
676 case O_NOP:
677 case O_IPID:
678 case O_IPTTL:

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

936 dst->timestamp += boot_seconds;
937 bp += l;
938 }
939 ipfw_get_dynamic(&bp, ep); /* protected by the dynamic lock */
940 return (bp - (char *)buf);
941}
942
943
670 case O_MACADDR2:
671 if (cmdlen != F_INSN_SIZE(ipfw_insn_mac))
672 goto bad_size;
673 break;
674
675 case O_NOP:
676 case O_IPID:
677 case O_IPTTL:

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

935 dst->timestamp += boot_seconds;
936 bp += l;
937 }
938 ipfw_get_dynamic(&bp, ep); /* protected by the dynamic lock */
939 return (bp - (char *)buf);
940}
941
942
943#define IP_FW3_OPLENGTH(x) ((x)->sopt_valsize - sizeof(ip_fw3_opheader))
944/**
945 * {set|get}sockopt parser.
946 */
947int
948ipfw_ctl(struct sockopt *sopt)
949{
950#define RULE_MAXSIZE (256*sizeof(u_int32_t))
951 int error;
944/**
945 * {set|get}sockopt parser.
946 */
947int
948ipfw_ctl(struct sockopt *sopt)
949{
950#define RULE_MAXSIZE (256*sizeof(u_int32_t))
951 int error;
952 size_t size;
952 size_t size, len, valsize;
953 struct ip_fw *buf, *rule;
954 struct ip_fw_chain *chain;
955 u_int32_t rulenum[2];
953 struct ip_fw *buf, *rule;
954 struct ip_fw_chain *chain;
955 u_int32_t rulenum[2];
956 uint32_t opt;
957 char xbuf[128];
958 ip_fw3_opheader *op3 = NULL;
956
957 error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
958 if (error)
959 return (error);
960
961 /*
962 * Disallow modifications in really-really secure mode, but still allow
963 * the logging counters to be reset.
964 */
965 if (sopt->sopt_name == IP_FW_ADD ||
966 (sopt->sopt_dir == SOPT_SET && sopt->sopt_name != IP_FW_RESETLOG)) {
967 error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
968 if (error)
969 return (error);
970 }
971
972 chain = &V_layer3_chain;
973 error = 0;
974
959
960 error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
961 if (error)
962 return (error);
963
964 /*
965 * Disallow modifications in really-really secure mode, but still allow
966 * the logging counters to be reset.
967 */
968 if (sopt->sopt_name == IP_FW_ADD ||
969 (sopt->sopt_dir == SOPT_SET && sopt->sopt_name != IP_FW_RESETLOG)) {
970 error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
971 if (error)
972 return (error);
973 }
974
975 chain = &V_layer3_chain;
976 error = 0;
977
975 switch (sopt->sopt_name) {
978 /* Save original valsize before it is altered via sooptcopyin() */
979 valsize = sopt->sopt_valsize;
980 if ((opt = sopt->sopt_name) == IP_FW3) {
981 /*
982 * Copy not less than sizeof(ip_fw3_opheader).
983 * We hope any IP_FW3 command will fit into 128-byte buffer.
984 */
985 if ((error = sooptcopyin(sopt, xbuf, sizeof(xbuf),
986 sizeof(ip_fw3_opheader))) != 0)
987 return (error);
988 op3 = (ip_fw3_opheader *)xbuf;
989 opt = op3->opcode;
990 }
991
992 switch (opt) {
976 case IP_FW_GET:
977 /*
978 * pass up a copy of the current rules. Static rules
979 * come first (the last of which has number IPFW_DEFAULT_RULE),
980 * followed by a possibly empty list of dynamic rule.
981 * The last dynamic rule has NULL in the "next" field.
982 *
983 * Note that the calculated size is used to bound the

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

1106 {
1107 ipfw_table_entry ent;
1108
1109 error = sooptcopyin(sopt, &ent,
1110 sizeof(ent), sizeof(ent));
1111 if (error)
1112 break;
1113 error = ipfw_add_table_entry(chain, ent.tbl,
993 case IP_FW_GET:
994 /*
995 * pass up a copy of the current rules. Static rules
996 * come first (the last of which has number IPFW_DEFAULT_RULE),
997 * followed by a possibly empty list of dynamic rule.
998 * The last dynamic rule has NULL in the "next" field.
999 *
1000 * Note that the calculated size is used to bound the

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

1123 {
1124 ipfw_table_entry ent;
1125
1126 error = sooptcopyin(sopt, &ent,
1127 sizeof(ent), sizeof(ent));
1128 if (error)
1129 break;
1130 error = ipfw_add_table_entry(chain, ent.tbl,
1114 ent.addr, ent.masklen, ent.value);
1131 &ent.addr, sizeof(ent.addr), ent.masklen,
1132 IPFW_TABLE_CIDR, ent.value);
1115 }
1116 break;
1117
1118 case IP_FW_TABLE_DEL:
1119 {
1120 ipfw_table_entry ent;
1121
1122 error = sooptcopyin(sopt, &ent,
1123 sizeof(ent), sizeof(ent));
1124 if (error)
1125 break;
1126 error = ipfw_del_table_entry(chain, ent.tbl,
1133 }
1134 break;
1135
1136 case IP_FW_TABLE_DEL:
1137 {
1138 ipfw_table_entry ent;
1139
1140 error = sooptcopyin(sopt, &ent,
1141 sizeof(ent), sizeof(ent));
1142 if (error)
1143 break;
1144 error = ipfw_del_table_entry(chain, ent.tbl,
1127 ent.addr, ent.masklen);
1145 &ent.addr, sizeof(ent.addr), ent.masklen, IPFW_TABLE_CIDR);
1128 }
1129 break;
1130
1146 }
1147 break;
1148
1149 case IP_FW_TABLE_XADD: /* IP_FW3 */
1150 case IP_FW_TABLE_XDEL: /* IP_FW3 */
1151 {
1152 ipfw_table_xentry *xent = (ipfw_table_xentry *)(op3 + 1);
1153
1154 /* Check minimum header size */
1155 if (IP_FW3_OPLENGTH(sopt) < offsetof(ipfw_table_xentry, k)) {
1156 error = EINVAL;
1157 break;
1158 }
1159
1160 /* Check if len field is valid */
1161 if (xent->len > sizeof(ipfw_table_xentry)) {
1162 error = EINVAL;
1163 break;
1164 }
1165
1166 len = xent->len - offsetof(ipfw_table_xentry, k);
1167
1168 error = (opt == IP_FW_TABLE_XADD) ?
1169 ipfw_add_table_entry(chain, xent->tbl, &xent->k,
1170 len, xent->masklen, xent->type, xent->value) :
1171 ipfw_del_table_entry(chain, xent->tbl, &xent->k,
1172 len, xent->masklen, xent->type);
1173 }
1174 break;
1175
1131 case IP_FW_TABLE_FLUSH:
1132 {
1133 u_int16_t tbl;
1134
1135 error = sooptcopyin(sopt, &tbl,
1136 sizeof(tbl), sizeof(tbl));
1137 if (error)
1138 break;
1176 case IP_FW_TABLE_FLUSH:
1177 {
1178 u_int16_t tbl;
1179
1180 error = sooptcopyin(sopt, &tbl,
1181 sizeof(tbl), sizeof(tbl));
1182 if (error)
1183 break;
1139 IPFW_WLOCK(chain);
1140 error = ipfw_flush_table(chain, tbl);
1184 error = ipfw_flush_table(chain, tbl);
1141 IPFW_WUNLOCK(chain);
1142 }
1143 break;
1144
1145 case IP_FW_TABLE_GETSIZE:
1146 {
1147 u_int32_t tbl, cnt;
1148
1149 if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl),

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

1182 free(tbl, M_TEMP);
1183 break;
1184 }
1185 error = sooptcopyout(sopt, tbl, size);
1186 free(tbl, M_TEMP);
1187 }
1188 break;
1189
1185 }
1186 break;
1187
1188 case IP_FW_TABLE_GETSIZE:
1189 {
1190 u_int32_t tbl, cnt;
1191
1192 if ((error = sooptcopyin(sopt, &tbl, sizeof(tbl),

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

1225 free(tbl, M_TEMP);
1226 break;
1227 }
1228 error = sooptcopyout(sopt, tbl, size);
1229 free(tbl, M_TEMP);
1230 }
1231 break;
1232
1233 case IP_FW_TABLE_XGETSIZE: /* IP_FW3 */
1234 {
1235 uint32_t *tbl;
1236
1237 if (IP_FW3_OPLENGTH(sopt) < sizeof(uint32_t)) {
1238 error = EINVAL;
1239 break;
1240 }
1241
1242 tbl = (uint32_t *)(op3 + 1);
1243
1244 IPFW_RLOCK(chain);
1245 error = ipfw_count_xtable(chain, *tbl, tbl);
1246 IPFW_RUNLOCK(chain);
1247 if (error)
1248 break;
1249 error = sooptcopyout(sopt, op3, sopt->sopt_valsize);
1250 }
1251 break;
1252
1253 case IP_FW_TABLE_XLIST: /* IP_FW3 */
1254 {
1255 ipfw_xtable *tbl;
1256
1257 if ((size = valsize) < sizeof(ipfw_xtable)) {
1258 error = EINVAL;
1259 break;
1260 }
1261
1262 tbl = malloc(size, M_TEMP, M_ZERO | M_WAITOK);
1263 memcpy(tbl, op3, sizeof(ipfw_xtable));
1264
1265 /* Get maximum number of entries we can store */
1266 tbl->size = (size - sizeof(ipfw_xtable)) /
1267 sizeof(ipfw_table_xentry);
1268 IPFW_RLOCK(chain);
1269 error = ipfw_dump_xtable(chain, tbl);
1270 IPFW_RUNLOCK(chain);
1271 if (error) {
1272 free(tbl, M_TEMP);
1273 break;
1274 }
1275
1276 /* Revert size field back to bytes */
1277 tbl->size = tbl->size * sizeof(ipfw_table_xentry) +
1278 sizeof(ipfw_table);
1279 /*
1280 * Since we call sooptcopyin() with small buffer, sopt_valsize is
1281 * decreased to reflect supplied buffer size. Set it back to original value
1282 */
1283 sopt->sopt_valsize = valsize;
1284 error = sooptcopyout(sopt, tbl, size);
1285 free(tbl, M_TEMP);
1286 }
1287 break;
1288
1190 /*--- NAT operations are protected by the IPFW_LOCK ---*/
1191 case IP_FW_NAT_CFG:
1192 if (IPFW_NAT_LOADED)
1193 error = ipfw_nat_cfg_ptr(sopt);
1194 else {
1195 printf("IP_FW_NAT_CFG: %s\n",
1196 "ipfw_nat not present, please load it");
1197 error = EINVAL;

--- 156 unchanged lines hidden ---
1289 /*--- NAT operations are protected by the IPFW_LOCK ---*/
1290 case IP_FW_NAT_CFG:
1291 if (IPFW_NAT_LOADED)
1292 error = ipfw_nat_cfg_ptr(sopt);
1293 else {
1294 printf("IP_FW_NAT_CFG: %s\n",
1295 "ipfw_nat not present, please load it");
1296 error = EINVAL;

--- 156 unchanged lines hidden ---