Lines Matching +full:current +full:- +full:regulated
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2017-2025 Yandex LLC
5 * Copyright (c) 2017-2025 Andrey V. Elsukov <ae@FreeBSD.org>
93 * + in-kernel NAT (not implemented yet)
95 * The lifetime of dynamic states is regulated by dyn_*_lifetime,
109 * There are some limitations with dynamic rules -- we do not
118 (d)->pcnt_ ## dir++; \
119 (d)->bcnt_ ## dir += pktlen; \
154 MPASS(p->count > 0); \
155 ck_pr_dec_32(&(p)->count); \
157 #define DPARENT_COUNT_INC(p) ck_pr_inc_32(&(p)->count)
158 #define DPARENT_COUNT(p) ck_pr_load_32(&(p)->count)
220 * Per-CPU pointer indicates that specified state is currently in use
288 #define DYN_BUCKET(h, b) ((h) & (b - 1))
395 if ((error != 0) || (req->newptr == NULL)) in sysctl_dyn_max()
412 if ((error != 0) || (req->newptr == NULL)) in sysctl_dyn_parent_max()
429 if ((error != 0) || (req->newptr == NULL)) in sysctl_dyn_buckets()
433 V_dyn_buckets_max = 1 << fls(nbuckets - 1); in sysctl_dyn_buckets()
443 "Current number of dynamic states.");
446 "Current number of parent states. ");
449 "Current number of buckets for states hash table.");
452 "Current maximum length of states chains in hash buckets.");
595 DYN_DEBUG("opcode %u, kidx %u", cmd0->opcode, cmd->kidx); in dyn_classify()
596 /* Don't rewrite "check-state any" */ in dyn_classify()
597 if (cmd->kidx == 0 && in dyn_classify()
598 cmd0->opcode == O_CHECK_STATE) in dyn_classify()
601 *puidx = cmd->kidx; in dyn_classify()
610 insntod(cmd0, kidx)->kidx = idx; in dyn_update()
611 DYN_DEBUG("opcode %u, kidx %u", cmd0->opcode, idx); in dyn_update()
621 DYN_DEBUG("uidx %u", ti->uidx); in dyn_findbyname()
622 if (ti->uidx != 0) { in dyn_findbyname()
623 if (ti->tlvs == NULL) in dyn_findbyname()
626 ntlv = ipfw_find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, in dyn_findbyname()
630 name = ntlv->name; in dyn_findbyname()
635 * Since states objects are global - ignore the set value in dyn_findbyname()
666 DYN_DEBUG("uidx %u", ti->uidx); in dyn_create()
667 if (ti->uidx != 0) { in dyn_create()
668 if (ti->tlvs == NULL) in dyn_create()
670 ntlv = ipfw_find_name_tlv_type(ti->tlvs, ti->tlen, ti->uidx, in dyn_create()
674 name = ntlv->name; in dyn_create()
680 obj->no.name = obj->name; in dyn_create()
681 obj->no.etlv = IPFW_TLV_STATE_NAME; in dyn_create()
682 strlcpy(obj->name, name, sizeof(obj->name)); in dyn_create()
692 *pkidx = no->kidx; in dyn_create()
693 no->refcnt++; in dyn_create()
696 DYN_DEBUG("\tfound kidx %u for name '%s'", *pkidx, no->name); in dyn_create()
699 if (ipfw_objhash_alloc_idx(ni, &obj->no.kidx) != 0) { in dyn_create()
705 ipfw_objhash_add(ni, &obj->no); in dyn_create()
706 SRV_OBJECT(ch, obj->no.kidx) = obj; in dyn_create()
707 obj->no.refcnt++; in dyn_create()
708 *pkidx = obj->no.kidx; in dyn_create()
721 KASSERT(no->etlv == IPFW_TLV_STATE_NAME, in dyn_destroy()
722 ("%s: wrong object type %u", __func__, no->etlv)); in dyn_destroy()
723 KASSERT(no->refcnt == 1, in dyn_destroy()
725 no->name, no->etlv, no->kidx, no->refcnt)); in dyn_destroy()
726 DYN_DEBUG("kidx %u", no->kidx); in dyn_destroy()
727 obj = SRV_OBJECT(ch, no->kidx); in dyn_destroy()
728 SRV_OBJECT(ch, no->kidx) = NULL; in dyn_destroy()
730 ipfw_objhash_free_idx(CHAIN_TO_SRV(ch), no->kidx); in dyn_destroy()
775 i = ntohl((id->dst_ip6.__u6_addr.__u6_addr32[2]) ^ in hash_packet()
776 (id->dst_ip6.__u6_addr.__u6_addr32[3]) ^ in hash_packet()
777 (id->src_ip6.__u6_addr.__u6_addr32[2]) ^ in hash_packet()
778 (id->src_ip6.__u6_addr.__u6_addr32[3])); in hash_packet()
781 i = (id->dst_ip) ^ (id->src_ip); in hash_packet()
782 i ^= (id->dst_port) ^ (id->src_port); in hash_packet()
802 if (id->src_ip < id->dst_ip) in addrcmp4()
804 if (id->src_ip > id->dst_ip) in addrcmp4()
806 if (id->src_port <= id->dst_port) in addrcmp4()
817 ret = memcmp(&id->src_ip6, &id->dst_ip6, sizeof(struct in6_addr)); in addrcmp6()
822 if (id->src_port <= id->dst_port) in addrcmp6()
836 t6.addr[0] = id->src_ip6; in hash_packet6()
837 t6.addr[1] = id->dst_ip6; in hash_packet6()
838 t6.port[0] = id->src_port; in hash_packet6()
839 t6.port[1] = id->dst_port; in hash_packet6()
841 t6.addr[0] = id->dst_ip6; in hash_packet6()
842 t6.addr[1] = id->src_ip6; in hash_packet6()
843 t6.port[0] = id->dst_port; in hash_packet6()
844 t6.port[1] = id->src_port; in hash_packet6()
862 t4.addr[0] = id->src_ip; in hash_packet()
863 t4.addr[1] = id->dst_ip; in hash_packet()
864 t4.port[0] = id->src_port; in hash_packet()
865 t4.port[1] = id->dst_port; in hash_packet()
867 t4.addr[0] = id->dst_ip; in hash_packet()
868 t4.addr[1] = id->src_ip; in hash_packet()
869 t4.port[0] = id->dst_port; in hash_packet()
870 t4.port[1] = id->src_port; in hash_packet()
907 ip6_sprintf(src, &id->src_ip6); in print_dyn_rule_flags()
908 ip6_sprintf(dst, &id->dst_ip6); in print_dyn_rule_flags()
912 da.s_addr = htonl(id->src_ip); in print_dyn_rule_flags()
914 da.s_addr = htonl(id->dst_ip); in print_dyn_rule_flags()
917 log(log_flags, "ipfw: %s type %d %s %d -> %s %d, %d %s\n", in print_dyn_rule_flags()
918 prefix, dyn_type, src, id->src_port, dst, in print_dyn_rule_flags()
919 id->dst_port, V_dyn_count, postfix); in print_dyn_rule_flags()
925 #define TIME_LEQ(a,b) ((int)((a)-(b)) <= 0)
926 #define TIME_LE(a,b) ((int)((a)-(b)) < 0)
927 #define _SEQ_GE(a,b) ((int)((a)-(b)) >= 0)
944 expire = data->expire; in dyn_update_tcp_state()
945 old = state = data->state; in dyn_update_tcp_state()
946 th_flags = pkt->_flags & (TH_FIN | TH_SYN | TH_RST); in dyn_update_tcp_state()
958 ack = ntohl(tcp->th_ack); in dyn_update_tcp_state()
960 if (data->ack_fwd == 0 || in dyn_update_tcp_state()
961 _SEQ_GE(ack, data->ack_fwd)) { in dyn_update_tcp_state()
963 if (data->ack_fwd != ack) in dyn_update_tcp_state()
964 ck_pr_store_32(&data->ack_fwd, ack); in dyn_update_tcp_state()
967 if (data->ack_rev == 0 || in dyn_update_tcp_state()
968 _SEQ_GE(ack, data->ack_rev)) { in dyn_update_tcp_state()
970 if (data->ack_rev != ack) in dyn_update_tcp_state()
971 ck_pr_store_32(&data->ack_rev, ack); in dyn_update_tcp_state()
982 ck_pr_xor_32(&data->state, ACK_BOTH); in dyn_update_tcp_state()
983 } else if ((data->state & ACK_BOTH) != (state & ACK_BOTH)) in dyn_update_tcp_state()
984 ck_pr_or_32(&data->state, state & ACK_BOTH); in dyn_update_tcp_state()
989 V_dyn_fin_lifetime = V_dyn_keepalive_period - 1; in dyn_update_tcp_state()
996 V_dyn_rst_lifetime = V_dyn_keepalive_period - 1; in dyn_update_tcp_state()
1001 ck_pr_or_32(&data->state, state & TCP_FLAGS); in dyn_update_tcp_state()
1018 switch (pkt->proto) { in dyn_update_proto_state()
1030 * Expiration timer has the per-second granularity, no need to update in dyn_update_proto_state()
1033 if (data->expire != expire) in dyn_update_proto_state()
1034 ck_pr_store_32(&data->expire, expire); in dyn_update_proto_state()
1053 bucket = DYN_BUCKET(info->hashval, V_curr_dyn_buckets); in dyn_lookup_ipv4_state()
1054 info->version = DYN_BUCKET_VERSION(bucket, ipv4_add); in dyn_lookup_ipv4_state()
1061 if (s->proto != pkt->proto) in dyn_lookup_ipv4_state()
1063 if (info->kidx != 0 && s->kidx != info->kidx) in dyn_lookup_ipv4_state()
1065 if (s->sport == pkt->src_port && s->dport == pkt->dst_port && in dyn_lookup_ipv4_state()
1066 s->src == pkt->src_ip && s->dst == pkt->dst_ip) { in dyn_lookup_ipv4_state()
1067 info->direction = MATCH_FORWARD; in dyn_lookup_ipv4_state()
1070 if (s->sport == pkt->dst_port && s->dport == pkt->src_port && in dyn_lookup_ipv4_state()
1071 s->src == pkt->dst_ip && s->dst == pkt->src_ip) { in dyn_lookup_ipv4_state()
1072 info->direction = MATCH_REVERSE; in dyn_lookup_ipv4_state()
1078 dyn_update_proto_state(s->data, pkt, ulp, pktlen, in dyn_lookup_ipv4_state()
1079 info->direction); in dyn_lookup_ipv4_state()
1097 if (s->proto != pkt->proto || in dyn_lookup_ipv4_state_locked()
1098 s->kidx != kidx) in dyn_lookup_ipv4_state_locked()
1100 if (s->sport == pkt->src_port && in dyn_lookup_ipv4_state_locked()
1101 s->dport == pkt->dst_port && in dyn_lookup_ipv4_state_locked()
1102 s->src == pkt->src_ip && s->dst == pkt->dst_ip) { in dyn_lookup_ipv4_state_locked()
1106 if (s->sport == pkt->dst_port && s->dport == pkt->src_port && in dyn_lookup_ipv4_state_locked()
1107 s->src == pkt->dst_ip && s->dst == pkt->src_ip) { in dyn_lookup_ipv4_state_locked()
1113 dyn_update_proto_state(s->data, pkt, ulp, pktlen, dir); in dyn_lookup_ipv4_state_locked()
1136 if (s->limit->parent == rule && in dyn_lookup_ipv4_parent()
1137 s->limit->ruleid == ruleid && in dyn_lookup_ipv4_parent()
1138 s->limit->rulenum == rulenum && in dyn_lookup_ipv4_parent()
1139 s->proto == pkt->proto && in dyn_lookup_ipv4_parent()
1140 s->sport == pkt->src_port && in dyn_lookup_ipv4_parent()
1141 s->dport == pkt->dst_port && in dyn_lookup_ipv4_parent()
1142 s->src == pkt->src_ip && s->dst == pkt->dst_ip) { in dyn_lookup_ipv4_parent()
1143 if (s->limit->expire != time_uptime + in dyn_lookup_ipv4_parent()
1145 ck_pr_store_32(&s->limit->expire, in dyn_lookup_ipv4_parent()
1161 if (s->limit->parent == rule && in dyn_lookup_ipv4_parent_locked()
1162 s->limit->ruleid == ruleid && in dyn_lookup_ipv4_parent_locked()
1163 s->limit->rulenum == rulenum && in dyn_lookup_ipv4_parent_locked()
1164 s->proto == pkt->proto && in dyn_lookup_ipv4_parent_locked()
1165 s->sport == pkt->src_port && in dyn_lookup_ipv4_parent_locked()
1166 s->dport == pkt->dst_port && in dyn_lookup_ipv4_parent_locked()
1167 s->src == pkt->src_ip && s->dst == pkt->dst_ip) in dyn_lookup_ipv4_parent_locked()
1182 if (IN6_IS_ADDR_LINKLOCAL(&args->f_id.src_ip6) || in dyn_getscopeid()
1183 IN6_IS_ADDR_LINKLOCAL(&args->f_id.dst_ip6)) in dyn_getscopeid()
1184 return (in6_getscopezone(args->ifp, IPV6_ADDR_SCOPE_LINKLOCAL)); in dyn_getscopeid()
1200 bucket = DYN_BUCKET(info->hashval, V_curr_dyn_buckets); in dyn_lookup_ipv6_state()
1201 info->version = DYN_BUCKET_VERSION(bucket, ipv6_add); in dyn_lookup_ipv6_state()
1208 if (s->proto != pkt->proto || s->zoneid != zoneid) in dyn_lookup_ipv6_state()
1210 if (info->kidx != 0 && s->kidx != info->kidx) in dyn_lookup_ipv6_state()
1212 if (s->sport == pkt->src_port && s->dport == pkt->dst_port && in dyn_lookup_ipv6_state()
1213 IN6_ARE_ADDR_EQUAL(&s->src, &pkt->src_ip6) && in dyn_lookup_ipv6_state()
1214 IN6_ARE_ADDR_EQUAL(&s->dst, &pkt->dst_ip6)) { in dyn_lookup_ipv6_state()
1215 info->direction = MATCH_FORWARD; in dyn_lookup_ipv6_state()
1218 if (s->sport == pkt->dst_port && s->dport == pkt->src_port && in dyn_lookup_ipv6_state()
1219 IN6_ARE_ADDR_EQUAL(&s->src, &pkt->dst_ip6) && in dyn_lookup_ipv6_state()
1220 IN6_ARE_ADDR_EQUAL(&s->dst, &pkt->src_ip6)) { in dyn_lookup_ipv6_state()
1221 info->direction = MATCH_REVERSE; in dyn_lookup_ipv6_state()
1226 dyn_update_proto_state(s->data, pkt, ulp, pktlen, in dyn_lookup_ipv6_state()
1227 info->direction); in dyn_lookup_ipv6_state()
1245 if (s->proto != pkt->proto || s->kidx != kidx || in dyn_lookup_ipv6_state_locked()
1246 s->zoneid != zoneid) in dyn_lookup_ipv6_state_locked()
1248 if (s->sport == pkt->src_port && s->dport == pkt->dst_port && in dyn_lookup_ipv6_state_locked()
1249 IN6_ARE_ADDR_EQUAL(&s->src, &pkt->src_ip6) && in dyn_lookup_ipv6_state_locked()
1250 IN6_ARE_ADDR_EQUAL(&s->dst, &pkt->dst_ip6)) { in dyn_lookup_ipv6_state_locked()
1254 if (s->sport == pkt->dst_port && s->dport == pkt->src_port && in dyn_lookup_ipv6_state_locked()
1255 IN6_ARE_ADDR_EQUAL(&s->src, &pkt->dst_ip6) && in dyn_lookup_ipv6_state_locked()
1256 IN6_ARE_ADDR_EQUAL(&s->dst, &pkt->src_ip6)) { in dyn_lookup_ipv6_state_locked()
1262 dyn_update_proto_state(s->data, pkt, ulp, pktlen, dir); in dyn_lookup_ipv6_state_locked()
1285 if (s->limit->parent == rule && in dyn_lookup_ipv6_parent()
1286 s->limit->ruleid == ruleid && in dyn_lookup_ipv6_parent()
1287 s->limit->rulenum == rulenum && in dyn_lookup_ipv6_parent()
1288 s->proto == pkt->proto && in dyn_lookup_ipv6_parent()
1289 s->sport == pkt->src_port && in dyn_lookup_ipv6_parent()
1290 s->dport == pkt->dst_port && s->zoneid == zoneid && in dyn_lookup_ipv6_parent()
1291 IN6_ARE_ADDR_EQUAL(&s->src, &pkt->src_ip6) && in dyn_lookup_ipv6_parent()
1292 IN6_ARE_ADDR_EQUAL(&s->dst, &pkt->dst_ip6)) { in dyn_lookup_ipv6_parent()
1293 if (s->limit->expire != time_uptime + in dyn_lookup_ipv6_parent()
1295 ck_pr_store_32(&s->limit->expire, in dyn_lookup_ipv6_parent()
1311 if (s->limit->parent == rule && in dyn_lookup_ipv6_parent_locked()
1312 s->limit->ruleid == ruleid && in dyn_lookup_ipv6_parent_locked()
1313 s->limit->rulenum == rulenum && in dyn_lookup_ipv6_parent_locked()
1314 s->proto == pkt->proto && in dyn_lookup_ipv6_parent_locked()
1315 s->sport == pkt->src_port && in dyn_lookup_ipv6_parent_locked()
1316 s->dport == pkt->dst_port && s->zoneid == zoneid && in dyn_lookup_ipv6_parent_locked()
1317 IN6_ARE_ADDR_EQUAL(&s->src, &pkt->src_ip6) && in dyn_lookup_ipv6_parent_locked()
1318 IN6_ARE_ADDR_EQUAL(&s->dst, &pkt->dst_ip6)) in dyn_lookup_ipv6_parent_locked()
1328 * pkt - filled by ipfw_chk() ipfw_flow_id;
1329 * ulp - determined by ipfw_chk() upper level protocol header;
1330 * dyn_info - info about matched state to return back;
1347 info->kidx = insntoc(cmd, kidx)->kidx; in ipfw_dyn_lookup_state()
1348 info->direction = MATCH_NONE; in ipfw_dyn_lookup_state()
1349 info->hashval = hash_packet(&args->f_id); in ipfw_dyn_lookup_state()
1352 if (IS_IP4_FLOW_ID(&args->f_id)) { in ipfw_dyn_lookup_state()
1355 s = dyn_lookup_ipv4_state(&args->f_id, ulp, info, pktlen); in ipfw_dyn_lookup_state()
1358 * Dynamic states are created using the same 5-tuple, in ipfw_dyn_lookup_state()
1362 data = s->data; in ipfw_dyn_lookup_state()
1363 if (s->type == O_LIMIT) { in ipfw_dyn_lookup_state()
1364 s = data->parent; in ipfw_dyn_lookup_state()
1365 rule = s->limit->parent; in ipfw_dyn_lookup_state()
1367 rule = data->parent; in ipfw_dyn_lookup_state()
1371 else if (IS_IP6_FLOW_ID(&args->f_id)) { in ipfw_dyn_lookup_state()
1374 s = dyn_lookup_ipv6_state(&args->f_id, dyn_getscopeid(args), in ipfw_dyn_lookup_state()
1377 data = s->data; in ipfw_dyn_lookup_state()
1378 if (s->type == O_LIMIT) { in ipfw_dyn_lookup_state()
1379 s = data->parent; in ipfw_dyn_lookup_state()
1380 rule = s->limit->parent; in ipfw_dyn_lookup_state()
1382 rule = data->parent; in ipfw_dyn_lookup_state()
1391 * update the same state, because chain->id can be changed in ipfw_dyn_lookup_state()
1394 if (data->chain_id != V_layer3_chain.id) { in ipfw_dyn_lookup_state()
1395 data->f_pos = ipfw_find_rule(&V_layer3_chain, in ipfw_dyn_lookup_state()
1396 data->rulenum, data->ruleid); in ipfw_dyn_lookup_state()
1399 * When chain->id being changed the parent in ipfw_dyn_lookup_state()
1418 * will be the last one - the default rule. in ipfw_dyn_lookup_state()
1420 if (V_layer3_chain.map[data->f_pos] == rule) { in ipfw_dyn_lookup_state()
1421 data->chain_id = V_layer3_chain.id; in ipfw_dyn_lookup_state()
1429 data->chain_id = V_layer3_chain.id; in ipfw_dyn_lookup_state()
1430 data->f_pos = V_layer3_chain.n_rules - 2; in ipfw_dyn_lookup_state()
1433 info->direction = MATCH_NONE; in ipfw_dyn_lookup_state()
1435 "invalid in data %p", rule, data->ruleid, in ipfw_dyn_lookup_state()
1436 data->rulenum, data); in ipfw_dyn_lookup_state()
1437 /* info->f_pos doesn't matter here. */ in ipfw_dyn_lookup_state()
1440 info->f_pos = data->f_pos; in ipfw_dyn_lookup_state()
1452 if (rule != NULL && (V_set_disable & (1 << rule->set))) { in ipfw_dyn_lookup_state()
1454 info->direction = MATCH_NONE; in ipfw_dyn_lookup_state()
1478 limit->parent = parent; in dyn_alloc_parent()
1479 limit->ruleid = ruleid; in dyn_alloc_parent()
1480 limit->rulenum = rulenum; in dyn_alloc_parent()
1481 limit->hashval = hashval; in dyn_alloc_parent()
1482 limit->expire = time_uptime + V_dyn_short_lifetime; in dyn_alloc_parent()
1504 data->parent = parent; in dyn_alloc_dyndata()
1505 data->ruleid = ruleid; in dyn_alloc_dyndata()
1506 data->rulenum = rulenum; in dyn_alloc_dyndata()
1507 data->fibnum = fibnum; in dyn_alloc_dyndata()
1508 data->hashval = hashval; in dyn_alloc_dyndata()
1509 data->expire = time_uptime + V_dyn_syn_lifetime; in dyn_alloc_dyndata()
1524 s->type = type; in dyn_alloc_ipv4_state()
1525 s->kidx = kidx; in dyn_alloc_ipv4_state()
1526 s->proto = pkt->proto; in dyn_alloc_ipv4_state()
1527 s->sport = pkt->src_port; in dyn_alloc_ipv4_state()
1528 s->dport = pkt->dst_port; in dyn_alloc_ipv4_state()
1529 s->src = pkt->src_ip; in dyn_alloc_ipv4_state()
1530 s->dst = pkt->dst_ip; in dyn_alloc_ipv4_state()
1584 s->limit = limit; in dyn_add_ipv4_parent()
1606 if (info->direction == MATCH_UNKNOWN || in dyn_add_ipv4_state()
1607 info->kidx != kidx || in dyn_add_ipv4_state()
1608 info->hashval != hashval || in dyn_add_ipv4_state()
1609 info->version != DYN_BUCKET_VERSION(bucket, ipv4_add)) { in dyn_add_ipv4_state()
1635 s->data = data; in dyn_add_ipv4_state()
1654 s->type = type; in dyn_alloc_ipv6_state()
1655 s->kidx = kidx; in dyn_alloc_ipv6_state()
1656 s->zoneid = zoneid; in dyn_alloc_ipv6_state()
1657 s->proto = pkt->proto; in dyn_alloc_ipv6_state()
1658 s->sport = pkt->src_port; in dyn_alloc_ipv6_state()
1659 s->dport = pkt->dst_port; in dyn_alloc_ipv6_state()
1660 s->src = pkt->src_ip6; in dyn_alloc_ipv6_state()
1661 s->dst = pkt->dst_ip6; in dyn_alloc_ipv6_state()
1715 s->limit = limit; in dyn_add_ipv6_parent()
1737 if (info->direction == MATCH_UNKNOWN || in dyn_add_ipv6_state()
1738 info->kidx != kidx || in dyn_add_ipv6_state()
1739 info->hashval != hashval || in dyn_add_ipv6_state()
1740 info->version != DYN_BUCKET_VERSION(bucket, ipv6_add)) { in dyn_add_ipv6_state()
1766 s->data = data; in dyn_add_ipv6_state()
1792 s = dyn_lookup_ipv4_parent(pkt, rule, rule->id, in dyn_get_parent_state()
1793 rule->rulenum, bucket); in dyn_get_parent_state()
1801 s = dyn_add_ipv4_parent(rule, rule->id, in dyn_get_parent_state()
1802 rule->rulenum, pkt, hashval, version, kidx); in dyn_get_parent_state()
1808 p = s->limit; in dyn_get_parent_state()
1815 s = dyn_lookup_ipv6_parent(pkt, zoneid, rule, rule->id, in dyn_get_parent_state()
1816 rule->rulenum, bucket); in dyn_get_parent_state()
1824 s = dyn_add_ipv6_parent(rule, rule->id, in dyn_get_parent_state()
1825 rule->rulenum, pkt, zoneid, hashval, version, in dyn_get_parent_state()
1832 p = s->limit; in dyn_get_parent_state()
1846 rule->rulenum); in dyn_get_parent_state()
1879 ruleid = rule->id; in dyn_install_state()
1880 rulenum = rule->rulenum; in dyn_install_state()
1883 id.addr_type = pkt->addr_type; in dyn_install_state()
1884 id.proto = pkt->proto; in dyn_install_state()
1887 pkt->src_port: 0; in dyn_install_state()
1889 pkt->dst_port: 0; in dyn_install_state()
1892 pkt->src_ip: 0; in dyn_install_state()
1894 pkt->dst_ip: 0; in dyn_install_state()
1899 id.src_ip6 = pkt->src_ip6; in dyn_install_state()
1903 id.dst_ip6 = pkt->dst_ip6; in dyn_install_state()
1919 "%u drop session", rule->rulenum); in dyn_install_state()
1959 ((struct dyn_ipv4_state *)rule)->limit); in dyn_install_state()
1963 ((struct dyn_ipv6_state *)rule)->limit); in dyn_install_state()
1980 * chain - ipfw's instance;
1981 * rule - the parent rule that installs the state;
1982 * cmd - opcode that installs the state;
1983 * args - ipfw arguments;
1984 * ulp - upper level protocol header;
1985 * pktlen - packet length;
1986 * info - dynamic state lookup info;
1987 * tablearg - tablearg id.
1989 * Returns non-zero value (failure) if state is not installed because
2001 if (cmd->o.opcode == O_LIMIT) { in ipfw_dyn_install_state()
2002 limit = IP_FW_ARG_TABLEARG(chain, cmd->conn_limit, limit); in ipfw_dyn_install_state()
2003 limit_mask = cmd->limit_mask; in ipfw_dyn_install_state()
2012 return (dyn_install_state(&args->f_id, in ipfw_dyn_install_state()
2014 IS_IP6_FLOW_ID(&args->f_id) ? dyn_getscopeid(args): in ipfw_dyn_install_state()
2016 0, M_GETFIB(args->m), ulp, pktlen, rule, info, limit, in ipfw_dyn_install_state()
2017 limit_mask, cmd->kidx, cmd->o.opcode)); in ipfw_dyn_install_state()
2034 * in the per-cpu dyn_hp pointer. When object is going to be in dyn_free_states()
2078 if (s->type == O_LIMIT_PARENT && \ in dyn_free_states()
2079 s->limit->count != 0) { \ in dyn_free_states()
2085 if (s->type == O_LIMIT_PARENT) \ in dyn_free_states()
2086 uma_zfree(V_dyn_parent_zone, s->limit); \ in dyn_free_states()
2088 uma_zfree(V_dyn_data_zone, s->data); \ in dyn_free_states()
2126 if (rt->flags & IPFW_RCFLAG_ALL) { in dyn_match_range()
2127 if (rt->flags & IPFW_RCFLAG_DYNAMIC) in dyn_match_range()
2131 if ((rt->flags & IPFW_RCFLAG_SET) != 0 && set != rt->set) in dyn_match_range()
2133 if ((rt->flags & IPFW_RCFLAG_RANGE) != 0 && in dyn_match_range()
2134 (rulenum < rt->start_rule || rulenum > rt->end_rule)) in dyn_match_range()
2136 if (rt->flags & IPFW_RCFLAG_DYNAMIC) in dyn_match_range()
2152 if (data->flags & DYN_REFERENCED) in dyn_acquire_rule()
2158 data->flags |= DYN_REFERENCED; in dyn_acquire_rule()
2161 obj->no.refcnt++; in dyn_acquire_rule()
2162 MPASS(obj->no.etlv == IPFW_TLV_STATE_NAME); in dyn_acquire_rule()
2165 rule->refcnt++; in dyn_acquire_rule()
2178 if (obj->no.refcnt == 1) in dyn_release_rule()
2179 dyn_destroy(ch, &obj->no); in dyn_release_rule()
2181 obj->no.refcnt--; in dyn_release_rule()
2183 if (--rule->refcnt == 1) in dyn_release_rule()
2202 if (s->type == O_LIMIT_PARENT) { in dyn_match_ipv4_state()
2203 rule = s->limit->parent; in dyn_match_ipv4_state()
2204 return (dyn_match_range(s->limit->rulenum, rule->set, rt)); in dyn_match_ipv4_state()
2207 rule = s->data->parent; in dyn_match_ipv4_state()
2208 if (s->type == O_LIMIT) in dyn_match_ipv4_state()
2209 rule = ((struct dyn_ipv4_state *)rule)->limit->parent; in dyn_match_ipv4_state()
2211 ret = dyn_match_range(s->data->rulenum, rule->set, rt); in dyn_match_ipv4_state()
2215 dyn_acquire_rule(ch, s->data, rule, s->kidx); in dyn_match_ipv4_state()
2227 if (s->type == O_LIMIT_PARENT) { in dyn_match_ipv6_state()
2228 rule = s->limit->parent; in dyn_match_ipv6_state()
2229 return (dyn_match_range(s->limit->rulenum, rule->set, rt)); in dyn_match_ipv6_state()
2232 rule = s->data->parent; in dyn_match_ipv6_state()
2233 if (s->type == O_LIMIT) in dyn_match_ipv6_state()
2234 rule = ((struct dyn_ipv6_state *)rule)->limit->parent; in dyn_match_ipv6_state()
2236 ret = dyn_match_range(s->data->rulenum, rule->set, rt); in dyn_match_ipv6_state()
2240 dyn_acquire_rule(ch, s->data, rule, s->kidx); in dyn_match_ipv6_state()
2286 if ((TIME_LEQ((s)->exp, time_uptime) && extra) || \ in dyn_expire_states()
2296 if (s->type == O_LIMIT_PARENT) \ in dyn_expire_states()
2300 if (s->data->flags & DYN_REFERENCED) { \ in dyn_expire_states()
2301 rule = s->data->parent; \ in dyn_expire_states()
2302 if (s->type == O_LIMIT) \ in dyn_expire_states()
2304 rule)->limit->parent;\ in dyn_expire_states()
2305 dyn_release_rule(ch, s->data, \ in dyn_expire_states()
2306 rule, s->kidx); \ in dyn_expire_states()
2308 if (s->type == O_LIMIT) { \ in dyn_expire_states()
2309 s = s->data->parent; \ in dyn_expire_states()
2310 DPARENT_COUNT_DEC(s->limit); \ in dyn_expire_states()
2332 DYN_UNLINK_STATES(s4, s4p, s4n, data->expire, ipv4, ipv4, 1); in dyn_expire_states()
2333 DYN_UNLINK_STATES(s4, s4p, s4n, limit->expire, ipv4, in dyn_expire_states()
2334 ipv4_parent, (s4->limit->count == 0)); in dyn_expire_states()
2336 DYN_UNLINK_STATES(s6, s6p, s6n, data->expire, ipv6, ipv6, 1); in dyn_expire_states()
2337 DYN_UNLINK_STATES(s6, s6p, s6n, limit->expire, ipv6, in dyn_expire_states()
2338 ipv6_parent, (s6->limit->count == 0)); in dyn_expire_states()
2371 m->m_data += max_linkhdr; in dyn_mgethdr()
2372 m->m_flags |= M_SKIP_FIREWALL; in dyn_mgethdr()
2373 m->m_len = m->m_pkthdr.len = len; in dyn_mgethdr()
2374 bzero(m->m_data, len); in dyn_mgethdr()
2386 ip->ip_v = 4; in dyn_make_keepalive_ipv4()
2387 ip->ip_hl = sizeof(*ip) >> 2; in dyn_make_keepalive_ipv4()
2388 ip->ip_tos = IPTOS_LOWDELAY; in dyn_make_keepalive_ipv4()
2389 ip->ip_len = htons(m->m_len); in dyn_make_keepalive_ipv4()
2390 ip->ip_off |= htons(IP_DF); in dyn_make_keepalive_ipv4()
2391 ip->ip_ttl = V_ip_defttl; in dyn_make_keepalive_ipv4()
2392 ip->ip_p = IPPROTO_TCP; in dyn_make_keepalive_ipv4()
2393 ip->ip_src.s_addr = htonl(src); in dyn_make_keepalive_ipv4()
2394 ip->ip_dst.s_addr = htonl(dst); in dyn_make_keepalive_ipv4()
2397 tcp->th_sport = htons(sport); in dyn_make_keepalive_ipv4()
2398 tcp->th_dport = htons(dport); in dyn_make_keepalive_ipv4()
2399 tcp->th_off = sizeof(struct tcphdr) >> 2; in dyn_make_keepalive_ipv4()
2400 tcp->th_seq = htonl(seq); in dyn_make_keepalive_ipv4()
2401 tcp->th_ack = htonl(ack); in dyn_make_keepalive_ipv4()
2403 tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, in dyn_make_keepalive_ipv4()
2406 m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); in dyn_make_keepalive_ipv4()
2407 m->m_pkthdr.csum_flags = CSUM_TCP; in dyn_make_keepalive_ipv4()
2415 if ((s->data->state & ACK_FWD) == 0 && s->data->ack_fwd > 0) { in dyn_enqueue_keepalive_ipv4()
2417 s->data->fibnum); in dyn_enqueue_keepalive_ipv4()
2419 dyn_make_keepalive_ipv4(m, s->dst, s->src, in dyn_enqueue_keepalive_ipv4()
2420 s->data->ack_fwd - 1, s->data->ack_rev, in dyn_enqueue_keepalive_ipv4()
2421 s->dport, s->sport); in dyn_enqueue_keepalive_ipv4()
2431 if ((s->data->state & ACK_REV) == 0 && s->data->ack_rev > 0) { in dyn_enqueue_keepalive_ipv4()
2433 s->data->fibnum); in dyn_enqueue_keepalive_ipv4()
2435 dyn_make_keepalive_ipv4(m, s->src, s->dst, in dyn_enqueue_keepalive_ipv4()
2436 s->data->ack_rev - 1, s->data->ack_fwd, in dyn_enqueue_keepalive_ipv4()
2437 s->sport, s->dport); in dyn_enqueue_keepalive_ipv4()
2449 * Prepare and send keep-alive packets.
2472 if (s->proto != IPPROTO_TCP || in dyn_send_keepalive_ipv4()
2473 (s->data->state & BOTH_SYN) != BOTH_SYN || in dyn_send_keepalive_ipv4()
2475 s->data->expire)) in dyn_send_keepalive_ipv4()
2495 ip6->ip6_vfc |= IPV6_VERSION; in dyn_make_keepalive_ipv6()
2496 ip6->ip6_plen = htons(sizeof(struct tcphdr)); in dyn_make_keepalive_ipv6()
2497 ip6->ip6_nxt = IPPROTO_TCP; in dyn_make_keepalive_ipv6()
2498 ip6->ip6_hlim = IPV6_DEFHLIM; in dyn_make_keepalive_ipv6()
2499 ip6->ip6_src = *src; in dyn_make_keepalive_ipv6()
2501 ip6->ip6_src.s6_addr16[1] = htons(zoneid & 0xffff); in dyn_make_keepalive_ipv6()
2502 ip6->ip6_dst = *dst; in dyn_make_keepalive_ipv6()
2504 ip6->ip6_dst.s6_addr16[1] = htons(zoneid & 0xffff); in dyn_make_keepalive_ipv6()
2507 tcp->th_sport = htons(sport); in dyn_make_keepalive_ipv6()
2508 tcp->th_dport = htons(dport); in dyn_make_keepalive_ipv6()
2509 tcp->th_off = sizeof(struct tcphdr) >> 2; in dyn_make_keepalive_ipv6()
2510 tcp->th_seq = htonl(seq); in dyn_make_keepalive_ipv6()
2511 tcp->th_ack = htonl(ack); in dyn_make_keepalive_ipv6()
2513 tcp->th_sum = in6_cksum_pseudo(ip6, sizeof(struct tcphdr), in dyn_make_keepalive_ipv6()
2516 m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); in dyn_make_keepalive_ipv6()
2517 m->m_pkthdr.csum_flags = CSUM_TCP_IPV6; in dyn_make_keepalive_ipv6()
2525 if ((s->data->state & ACK_FWD) == 0 && s->data->ack_fwd > 0) { in dyn_enqueue_keepalive_ipv6()
2527 sizeof(struct tcphdr), s->data->fibnum); in dyn_enqueue_keepalive_ipv6()
2529 dyn_make_keepalive_ipv6(m, &s->dst, &s->src, in dyn_enqueue_keepalive_ipv6()
2530 s->zoneid, s->data->ack_fwd - 1, s->data->ack_rev, in dyn_enqueue_keepalive_ipv6()
2531 s->dport, s->sport); in dyn_enqueue_keepalive_ipv6()
2541 if ((s->data->state & ACK_REV) == 0 && s->data->ack_rev > 0) { in dyn_enqueue_keepalive_ipv6()
2543 sizeof(struct tcphdr), s->data->fibnum); in dyn_enqueue_keepalive_ipv6()
2545 dyn_make_keepalive_ipv6(m, &s->src, &s->dst, in dyn_enqueue_keepalive_ipv6()
2546 s->zoneid, s->data->ack_rev - 1, s->data->ack_fwd, in dyn_enqueue_keepalive_ipv6()
2547 s->sport, s->dport); in dyn_enqueue_keepalive_ipv6()
2579 if (s->proto != IPPROTO_TCP || in dyn_send_keepalive_ipv6()
2580 (s->data->state & BOTH_SYN) != BOTH_SYN || in dyn_send_keepalive_ipv6()
2582 s->data->expire)) in dyn_send_keepalive_ipv6()
2609 DYN_DEBUG("grow hash size %u -> %u", V_curr_dyn_buckets, new); in dyn_grow_hashtable()
2684 CK_SLIST_INSERT_HEAD(&head[DYN_BUCKET(s->hval, new)], \ in dyn_grow_hashtable()
2697 /* Re-link all dynamic states */ in dyn_grow_hashtable()
2699 DYN_RELINK_STATES(s4, data->hashval, bucket, ipv4, ipv4); in dyn_grow_hashtable()
2700 DYN_RELINK_STATES(s4, limit->hashval, bucket, ipv4_parent, in dyn_grow_hashtable()
2703 DYN_RELINK_STATES(s6, data->hashval, bucket, ipv6, ipv6); in dyn_grow_hashtable()
2704 DYN_RELINK_STATES(s6, limit->hashval, bucket, ipv6_parent, in dyn_grow_hashtable()
2738 while (bucket-- != 0) in dyn_grow_hashtable()
2797 * if current number of states exceeds number of buckets in hash, in dyn_tick()
2800 * than current states count. in dyn_tick()
2844 if ((s->data->flags & DYN_REFERENCED) == 0) \ in ipfw_dyn_reset_eaction()
2846 rule = s->data->parent; \ in ipfw_dyn_reset_eaction()
2847 if (s->type == O_LIMIT) \ in ipfw_dyn_reset_eaction()
2848 rule = ((__typeof(s))rule)->limit->parent; \ in ipfw_dyn_reset_eaction()
2878 * Used by dump format v1 (current).
2891 MPASS(s->kidx != 0); \ in ipfw_dyn_get_count()
2893 s->kidx) != 0) \ in ipfw_dyn_get_count()
2925 l = rule->cmd_len; in ipfw_is_dyn_rule()
2926 cmd = rule->cmd; in ipfw_is_dyn_rule()
2928 for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { in ipfw_is_dyn_rule()
2931 switch (cmd->opcode) { in ipfw_is_dyn_rule()
2948 dst->type = O_LIMIT_PARENT; in dyn_export_parent()
2949 dst->set = set; in dyn_export_parent()
2950 dst->kidx = kidx; in dyn_export_parent()
2951 dst->rulenum = p->rulenum; in dyn_export_parent()
2952 dst->count = DPARENT_COUNT(p); in dyn_export_parent()
2953 dst->expire = TIME_LEQ(p->expire, time_uptime) ? 0: in dyn_export_parent()
2954 p->expire - time_uptime; in dyn_export_parent()
2955 dst->hashval = p->hashval; in dyn_export_parent()
2958 dst->pad = 0; in dyn_export_parent()
2959 dst->pcnt = 0; in dyn_export_parent()
2960 dst->bcnt = 0; in dyn_export_parent()
2961 dst->ack_fwd = 0; in dyn_export_parent()
2962 dst->ack_rev = 0; in dyn_export_parent()
2970 dst->type = type; in dyn_export_data()
2971 dst->set = set; in dyn_export_data()
2972 dst->kidx = kidx; in dyn_export_data()
2973 dst->rulenum = data->rulenum; in dyn_export_data()
2974 dst->pcnt = data->pcnt_fwd + data->pcnt_rev; in dyn_export_data()
2975 dst->bcnt = data->bcnt_fwd + data->bcnt_rev; in dyn_export_data()
2976 dst->expire = TIME_LEQ(data->expire, time_uptime) ? 0: in dyn_export_data()
2977 data->expire - time_uptime; in dyn_export_data()
2978 dst->state = data->state; in dyn_export_data()
2979 if (data->flags & DYN_REFERENCED) in dyn_export_data()
2980 dst->state |= IPFW_DYN_ORPHANED; in dyn_export_data()
2982 dst->ack_fwd = data->ack_fwd; in dyn_export_data()
2983 dst->ack_rev = data->ack_rev; in dyn_export_data()
2984 dst->hashval = data->hashval; in dyn_export_data()
2992 switch (s->type) { in dyn_export_ipv4_state()
2994 rule = s->limit->parent; in dyn_export_ipv4_state()
2995 dyn_export_parent(s->limit, s->kidx, rule->set, dst); in dyn_export_ipv4_state()
2998 rule = s->data->parent; in dyn_export_ipv4_state()
2999 if (s->type == O_LIMIT) in dyn_export_ipv4_state()
3000 rule = ((struct dyn_ipv4_state *)rule)->limit->parent; in dyn_export_ipv4_state()
3001 dyn_export_data(s->data, s->kidx, s->type, rule->set, dst); in dyn_export_ipv4_state()
3004 dst->id.dst_ip = s->dst; in dyn_export_ipv4_state()
3005 dst->id.src_ip = s->src; in dyn_export_ipv4_state()
3006 dst->id.dst_port = s->dport; in dyn_export_ipv4_state()
3007 dst->id.src_port = s->sport; in dyn_export_ipv4_state()
3008 dst->id.fib = s->data->fibnum; in dyn_export_ipv4_state()
3009 dst->id.proto = s->proto; in dyn_export_ipv4_state()
3010 dst->id._flags = 0; in dyn_export_ipv4_state()
3011 dst->id.addr_type = 4; in dyn_export_ipv4_state()
3013 memset(&dst->id.dst_ip6, 0, sizeof(dst->id.dst_ip6)); in dyn_export_ipv4_state()
3014 memset(&dst->id.src_ip6, 0, sizeof(dst->id.src_ip6)); in dyn_export_ipv4_state()
3015 dst->id.flow_id6 = dst->id.extra = 0; in dyn_export_ipv4_state()
3024 switch (s->type) { in dyn_export_ipv6_state()
3026 rule = s->limit->parent; in dyn_export_ipv6_state()
3027 dyn_export_parent(s->limit, s->kidx, rule->set, dst); in dyn_export_ipv6_state()
3030 rule = s->data->parent; in dyn_export_ipv6_state()
3031 if (s->type == O_LIMIT) in dyn_export_ipv6_state()
3032 rule = ((struct dyn_ipv6_state *)rule)->limit->parent; in dyn_export_ipv6_state()
3033 dyn_export_data(s->data, s->kidx, s->type, rule->set, dst); in dyn_export_ipv6_state()
3036 dst->id.src_ip6 = s->src; in dyn_export_ipv6_state()
3037 dst->id.dst_ip6 = s->dst; in dyn_export_ipv6_state()
3038 dst->id.dst_port = s->dport; in dyn_export_ipv6_state()
3039 dst->id.src_port = s->sport; in dyn_export_ipv6_state()
3040 dst->id.fib = s->data->fibnum; in dyn_export_ipv6_state()
3041 dst->id.proto = s->proto; in dyn_export_ipv6_state()
3042 dst->id._flags = 0; in dyn_export_ipv6_state()
3043 dst->id.addr_type = 6; in dyn_export_ipv6_state()
3045 dst->id.dst_ip = dst->id.src_ip = 0; in dyn_export_ipv6_state()
3046 dst->id.flow_id6 = dst->id.extra = 0; in dyn_export_ipv6_state()
3052 * Used by dump format v1 (current).
3080 ctlv->head.type = IPFW_TLV_DYNSTATE_LIST; in ipfw_dump_states()
3081 ctlv->objsize = sizeof(ipfw_obj_dyntlv); in ipfw_dump_states()
3090 dyn_export_ ## af ## _state(s, &dst->state); \ in ipfw_dump_states()
3091 dst->head.length = sizeof(ipfw_obj_dyntlv); \ in ipfw_dump_states()
3092 dst->head.type = IPFW_TLV_DYN_ENT; \ in ipfw_dump_states()
3107 last->head.flags = IPFW_DF_LAST; /* XXX: unused */ in ipfw_dump_states()
3195 if (s->type == O_LIMIT_PARENT) \ in ipfw_dyn_uninit()
3196 uma_zfree(V_dyn_parent_zone, s->limit); \ in ipfw_dyn_uninit()
3198 uma_zfree(V_dyn_data_zone, s->data); \ in ipfw_dyn_uninit()