^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2015 Nicira, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/openvswitch.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/tcp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/udp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sctp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/static_key.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <net/ip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <net/netfilter/nf_conntrack_core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <net/netfilter/nf_conntrack_count.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <net/netfilter/nf_conntrack_helper.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <net/netfilter/nf_conntrack_labels.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <net/netfilter/nf_conntrack_seqadj.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <net/netfilter/nf_conntrack_timeout.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <net/netfilter/nf_conntrack_zones.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <net/ipv6_frag.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <net/netfilter/nf_nat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "datapath.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "conntrack.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "flow.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include "flow_netlink.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct ovs_ct_len_tbl {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int maxlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) int minlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* Metadata mark for masked write to conntrack mark */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct md_mark {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u32 value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Metadata label for masked write to conntrack label. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct md_labels {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct ovs_key_ct_labels value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct ovs_key_ct_labels mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) enum ovs_ct_nat {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) OVS_CT_NAT = 1 << 0, /* NAT for committed connections only. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) OVS_CT_SRC_NAT = 1 << 1, /* Source NAT for NEW connections. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) OVS_CT_DST_NAT = 1 << 2, /* Destination NAT for NEW connections. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Conntrack action context for execution. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct ovs_conntrack_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct nf_conntrack_helper *helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct nf_conntrack_zone zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u8 commit : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u8 nat : 3; /* enum ovs_ct_nat */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) u8 force : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u8 have_eventmask : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u16 family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 eventmask; /* Mask of 1 << IPCT_*. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct md_mark mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct md_labels labels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) char timeout[CTNL_TIMEOUT_NAME_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct nf_ct_timeout *nf_ct_timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define OVS_CT_LIMIT_UNLIMITED 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define OVS_CT_LIMIT_DEFAULT OVS_CT_LIMIT_UNLIMITED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define CT_LIMIT_HASH_BUCKETS 512
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static DEFINE_STATIC_KEY_FALSE(ovs_ct_limit_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct ovs_ct_limit {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /* Elements in ovs_ct_limit_info->limits hash table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct hlist_node hlist_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct rcu_head rcu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) u16 zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) u32 limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct ovs_ct_limit_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) u32 default_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct hlist_head *limits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct nf_conncount_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static const struct nla_policy ct_limit_policy[OVS_CT_LIMIT_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) [OVS_CT_LIMIT_ATTR_ZONE_LIMIT] = { .type = NLA_NESTED, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static bool labels_nonzero(const struct ovs_key_ct_labels *labels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static u16 key_to_nfproto(const struct sw_flow_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) switch (ntohs(key->eth.type)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) case ETH_P_IP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return NFPROTO_IPV4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case ETH_P_IPV6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return NFPROTO_IPV6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return NFPROTO_UNSPEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /* Map SKB connection state into the values used by flow definition. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u8 ct_state = OVS_CS_F_TRACKED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) switch (ctinfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case IP_CT_ESTABLISHED_REPLY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case IP_CT_RELATED_REPLY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ct_state |= OVS_CS_F_REPLY_DIR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) switch (ctinfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case IP_CT_ESTABLISHED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case IP_CT_ESTABLISHED_REPLY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ct_state |= OVS_CS_F_ESTABLISHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case IP_CT_RELATED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case IP_CT_RELATED_REPLY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ct_state |= OVS_CS_F_RELATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case IP_CT_NEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) ct_state |= OVS_CS_F_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return ct_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static u32 ovs_ct_get_mark(const struct nf_conn *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return ct ? ct->mark : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Guard against conntrack labels max size shrinking below 128 bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #if NF_CT_LABELS_MAX_SIZE < 16
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #error NF_CT_LABELS_MAX_SIZE must be at least 16 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static void ovs_ct_get_labels(const struct nf_conn *ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct ovs_key_ct_labels *labels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) memcpy(labels, cl->bits, OVS_CT_LABELS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) memset(labels, 0, OVS_CT_LABELS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void __ovs_ct_update_key_orig_tp(struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) const struct nf_conntrack_tuple *orig,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) u8 icmp_proto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) key->ct_orig_proto = orig->dst.protonum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (orig->dst.protonum == icmp_proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) key->ct.orig_tp.src = htons(orig->dst.u.icmp.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) key->ct.orig_tp.dst = htons(orig->dst.u.icmp.code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) key->ct.orig_tp.src = orig->src.u.all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) key->ct.orig_tp.dst = orig->dst.u.all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) const struct nf_conntrack_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) const struct nf_conn *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) key->ct_state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) key->ct_zone = zone->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) key->ct.mark = ovs_ct_get_mark(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ovs_ct_get_labels(ct, &key->ct.labels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (ct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) const struct nf_conntrack_tuple *orig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* Use the master if we have one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (ct->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ct = ct->master;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* IP version must match with the master connection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (key->eth.type == htons(ETH_P_IP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) nf_ct_l3num(ct) == NFPROTO_IPV4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) key->ipv4.ct_orig.src = orig->src.u3.ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) key->ipv4.ct_orig.dst = orig->dst.u3.ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) __ovs_ct_update_key_orig_tp(key, orig, IPPROTO_ICMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) } else if (key->eth.type == htons(ETH_P_IPV6) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) !sw_flow_key_is_nd(key) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) nf_ct_l3num(ct) == NFPROTO_IPV6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) key->ipv6.ct_orig.src = orig->src.u3.in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) key->ipv6.ct_orig.dst = orig->dst.u3.in6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) __ovs_ct_update_key_orig_tp(key, orig, NEXTHDR_ICMP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /* Clear 'ct_orig_proto' to mark the non-existence of conntrack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * original direction key fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) key->ct_orig_proto = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* Update 'key' based on skb->_nfct. If 'post_ct' is true, then OVS has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * previously sent the packet to conntrack via the ct action. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * 'keep_nat_flags' is true, the existing NAT flags retained, else they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * initialized from the connection status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static void ovs_ct_update_key(const struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct sw_flow_key *key, bool post_ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) bool keep_nat_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) enum ip_conntrack_info ctinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) u8 state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ct = nf_ct_get(skb, &ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (ct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) state = ovs_ct_get_state(ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* All unconfirmed entries are NEW connections. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!nf_ct_is_confirmed(ct))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) state |= OVS_CS_F_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* OVS persists the related flag for the duration of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (ct->master)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) state |= OVS_CS_F_RELATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (keep_nat_flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) state |= key->ct_state & OVS_CS_F_NAT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (ct->status & IPS_SRC_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) state |= OVS_CS_F_SRC_NAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (ct->status & IPS_DST_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) state |= OVS_CS_F_DST_NAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) zone = nf_ct_zone(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) } else if (post_ct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) zone = &info->zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) __ovs_ct_update_key(key, state, zone, ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* This is called to initialize CT key fields possibly coming in from the local
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * stack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ovs_ct_update_key(skb, NULL, key, false, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) int ovs_ct_put_key(const struct sw_flow_key *swkey,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) const struct sw_flow_key *output, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, output->ct_state))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) nla_put_u16(skb, OVS_KEY_ATTR_CT_ZONE, output->ct_zone))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) nla_put_u32(skb, OVS_KEY_ATTR_CT_MARK, output->ct.mark))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(output->ct.labels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) &output->ct.labels))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (swkey->ct_orig_proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (swkey->eth.type == htons(ETH_P_IP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct ovs_key_ct_tuple_ipv4 orig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) memset(&orig, 0, sizeof(orig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) orig.ipv4_src = output->ipv4.ct_orig.src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) orig.ipv4_dst = output->ipv4.ct_orig.dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) orig.src_port = output->ct.orig_tp.src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) orig.dst_port = output->ct.orig_tp.dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) orig.ipv4_proto = output->ct_orig_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) sizeof(orig), &orig))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) } else if (swkey->eth.type == htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct ovs_key_ct_tuple_ipv6 orig;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) memset(&orig, 0, sizeof(orig));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) memcpy(orig.ipv6_src, output->ipv6.ct_orig.src.s6_addr32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) sizeof(orig.ipv6_src));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) memcpy(orig.ipv6_dst, output->ipv6.ct_orig.dst.s6_addr32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) sizeof(orig.ipv6_dst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) orig.src_port = output->ct.orig_tp.src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) orig.dst_port = output->ct.orig_tp.dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) orig.ipv6_proto = output->ct_orig_proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) sizeof(orig), &orig))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int ovs_ct_set_mark(struct nf_conn *ct, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u32 ct_mark, u32 mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) u32 new_mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) new_mark = ct_mark | (ct->mark & ~(mask));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (ct->mark != new_mark) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) ct->mark = new_mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (nf_ct_is_confirmed(ct))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) nf_conntrack_event_cache(IPCT_MARK, ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) key->ct.mark = new_mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static struct nf_conn_labels *ovs_ct_get_conn_labels(struct nf_conn *ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct nf_conn_labels *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) cl = nf_ct_labels_find(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!cl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) nf_ct_labels_ext_add(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) cl = nf_ct_labels_find(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* Initialize labels for a new, yet to be committed conntrack entry. Note that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * since the new connection is not yet confirmed, and thus no-one else has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * access to it's labels, we simply write them over.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static int ovs_ct_init_labels(struct nf_conn *ct, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) const struct ovs_key_ct_labels *labels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) const struct ovs_key_ct_labels *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) struct nf_conn_labels *cl, *master_cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) bool have_mask = labels_nonzero(mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* Inherit master's labels to the related connection? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) master_cl = ct->master ? nf_ct_labels_find(ct->master) : NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (!master_cl && !have_mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return 0; /* Nothing to do. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) cl = ovs_ct_get_conn_labels(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (!cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* Inherit the master's labels, if any. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (master_cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) *cl = *master_cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (have_mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) u32 *dst = (u32 *)cl->bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) for (i = 0; i < OVS_CT_LABELS_LEN_32; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) dst[i] = (dst[i] & ~mask->ct_labels_32[i]) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) (labels->ct_labels_32[i]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) & mask->ct_labels_32[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) /* Labels are included in the IPCTNL_MSG_CT_NEW event only if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * IPCT_LABEL bit is set in the event cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) nf_conntrack_event_cache(IPCT_LABEL, ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) memcpy(&key->ct.labels, cl->bits, OVS_CT_LABELS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) static int ovs_ct_set_labels(struct nf_conn *ct, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) const struct ovs_key_ct_labels *labels,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) const struct ovs_key_ct_labels *mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) struct nf_conn_labels *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) cl = ovs_ct_get_conn_labels(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (!cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) err = nf_connlabels_replace(ct, labels->ct_labels_32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) mask->ct_labels_32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) OVS_CT_LABELS_LEN_32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) memcpy(&key->ct.labels, cl->bits, OVS_CT_LABELS_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* 'skb' should already be pulled to nh_ofs. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) const struct nf_conntrack_helper *helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) const struct nf_conn_help *help;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) enum ip_conntrack_info ctinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) unsigned int protoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ct = nf_ct_get(skb, &ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (!ct || ctinfo == IP_CT_RELATED_REPLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return NF_ACCEPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) help = nfct_help(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!help)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return NF_ACCEPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) helper = rcu_dereference(help->helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!helper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return NF_ACCEPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) switch (proto) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) case NFPROTO_IPV4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) protoff = ip_hdrlen(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) case NFPROTO_IPV6: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) u8 nexthdr = ipv6_hdr(skb)->nexthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) __be16 frag_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) int ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) &frag_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (ofs < 0 || (frag_off & htons(~0x7)) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) pr_debug("proto header not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return NF_ACCEPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) protoff = ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) WARN_ONCE(1, "helper invoked on non-IP family!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return NF_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) err = helper->help(skb, protoff, ct, ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (err != NF_ACCEPT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) /* Adjust seqs after helper. This is needed due to some helpers (e.g.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) * FTP with NAT) adusting the TCP payload size when mangling IP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * addresses and/or port numbers in the text-based control connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) !nf_ct_seq_adjust(skb, ct, ctinfo, protoff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return NF_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) return NF_ACCEPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * value if 'skb' is freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) static int handle_fragments(struct net *net, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) u16 zone, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) struct ovs_skb_cb ovs_cb = *OVS_CB(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (key->eth.type == htons(ETH_P_IP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) err = ip_defrag(net, skb, user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ovs_cb.mru = IPCB(skb)->frag_max_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) } else if (key->eth.type == htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) err = nf_ct_frag6_gather(net, skb, user);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (err != -EINPROGRESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) key->ip.proto = ipv6_hdr(skb)->nexthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ovs_cb.mru = IP6CB(skb)->frag_max_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return -EPFNOSUPPORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* The key extracted from the fragment that completed this datagram
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * likely didn't have an L4 header, so regenerate it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ovs_flow_key_update_l3l4(skb, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) key->ip.frag = OVS_FRAG_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) skb_clear_hash(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) skb->ignore_df = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) *OVS_CB(skb) = ovs_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static struct nf_conntrack_expect *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) u16 proto, const struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct nf_conntrack_tuple tuple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct nf_conntrack_expect *exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) exp = __nf_ct_expect_find(net, zone, &tuple);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct nf_conntrack_tuple_hash *h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) /* Delete existing conntrack entry, if it clashes with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * expectation. This can happen since conntrack ALGs do not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) * check for clashes between (new) expectations and existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) * conntrack entries. nf_conntrack_in() will check the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * expectations only if a conntrack entry can not be found,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * which can lead to OVS finding the expectation (here) in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * init direction, but which will not be removed by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * nf_conntrack_in() call, if a matching conntrack entry is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * found instead. In this case all init direction packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * would be reported as new related packets, while reply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * direction packets would be reported as un-related
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) * established packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) h = nf_conntrack_find_get(net, zone, &tuple);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (h) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) nf_ct_delete(ct, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) nf_conntrack_put(&ct->ct_general);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) return exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* This replicates logic from nf_conntrack_core.c that is not exported. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static enum ip_conntrack_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) ovs_ct_get_info(const struct nf_conntrack_tuple_hash *h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return IP_CT_ESTABLISHED_REPLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) /* Once we've had two way comms, always ESTABLISHED. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) return IP_CT_ESTABLISHED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if (test_bit(IPS_EXPECTED_BIT, &ct->status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return IP_CT_RELATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return IP_CT_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /* Find an existing connection which this packet belongs to without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * re-attributing statistics or modifying the connection state. This allows an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * skb->_nfct lost due to an upcall to be recovered during actions execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * Must be called with rcu_read_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * On success, populates skb->_nfct and returns the connection. Returns NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * if there is no existing entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) static struct nf_conn *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) u8 l3num, struct sk_buff *skb, bool natted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct nf_conntrack_tuple tuple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) struct nf_conntrack_tuple_hash *h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), l3num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) net, &tuple)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) pr_debug("ovs_ct_find_existing: Can't get tuple\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) /* Must invert the tuple if skb has been transformed by NAT. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (natted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) struct nf_conntrack_tuple inverse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (!nf_ct_invert_tuple(&inverse, &tuple)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) pr_debug("ovs_ct_find_existing: Inversion failed!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) tuple = inverse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /* look for tuple match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) h = nf_conntrack_find_get(net, zone, &tuple);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) if (!h)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return NULL; /* Not found. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) ct = nf_ct_tuplehash_to_ctrack(h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* Inverted packet tuple matches the reverse direction conntrack tuple,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) * select the other tuplehash to get the right 'ctinfo' bits for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) * packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (natted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) h = &ct->tuplehash[!h->tuple.dst.dir];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) nf_ct_set(skb, ct, ovs_ct_get_info(h));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) struct nf_conn *ovs_ct_executed(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) const struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) bool *ct_executed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) struct nf_conn *ct = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /* If no ct, check if we have evidence that an existing conntrack entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * might be found for this skb. This happens when we lose a skb->_nfct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * due to an upcall, or if the direction is being forced. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * connection was not confirmed, it is not cached and needs to be run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * through conntrack again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) *ct_executed = (key->ct_state & OVS_CS_F_TRACKED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) !(key->ct_state & OVS_CS_F_INVALID) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) (key->ct_zone == info->zone.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (*ct_executed || (!key->ct_state && info->force)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) !!(key->ct_state &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) OVS_CS_F_NAT_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) /* Determine whether skb->_nfct is equal to the result of conntrack lookup. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) static bool skb_nfct_cached(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) const struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) enum ip_conntrack_info ctinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) bool ct_executed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ct = nf_ct_get(skb, &ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (!ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) ct = ovs_ct_executed(net, key, info, skb, &ct_executed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) nf_ct_get(skb, &ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (!net_eq(net, read_pnet(&ct->ct_net)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (!nf_ct_zone_equal_any(info->ct, nf_ct_zone(ct)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (info->helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct nf_conn_help *help;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (help && rcu_access_pointer(help->helper) != info->helper)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (info->nf_ct_timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct nf_conn_timeout *timeout_ext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) timeout_ext = nf_ct_timeout_find(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!timeout_ext || info->nf_ct_timeout !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) rcu_dereference(timeout_ext->timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) /* Force conntrack entry direction to the current packet? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (info->force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) /* Delete the conntrack entry if confirmed, else just release
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * the reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (nf_ct_is_confirmed(ct))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) nf_ct_delete(ct, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) nf_conntrack_put(&ct->ct_general);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) nf_ct_set(skb, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return ct_executed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) static void ovs_nat_update_key(struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) const struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) enum nf_nat_manip_type maniptype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (maniptype == NF_NAT_MANIP_SRC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) __be16 src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) key->ct_state |= OVS_CS_F_SRC_NAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (key->eth.type == htons(ETH_P_IP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) key->ipv4.addr.src = ip_hdr(skb)->saddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) else if (key->eth.type == htons(ETH_P_IPV6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) memcpy(&key->ipv6.addr.src, &ipv6_hdr(skb)->saddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) sizeof(key->ipv6.addr.src));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (key->ip.proto == IPPROTO_UDP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) src = udp_hdr(skb)->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) else if (key->ip.proto == IPPROTO_TCP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) src = tcp_hdr(skb)->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) else if (key->ip.proto == IPPROTO_SCTP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) src = sctp_hdr(skb)->source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) key->tp.src = src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) __be16 dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) key->ct_state |= OVS_CS_F_DST_NAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (key->eth.type == htons(ETH_P_IP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) key->ipv4.addr.dst = ip_hdr(skb)->daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) else if (key->eth.type == htons(ETH_P_IPV6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) memcpy(&key->ipv6.addr.dst, &ipv6_hdr(skb)->daddr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) sizeof(key->ipv6.addr.dst));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (key->ip.proto == IPPROTO_UDP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) dst = udp_hdr(skb)->dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) else if (key->ip.proto == IPPROTO_TCP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) dst = tcp_hdr(skb)->dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) else if (key->ip.proto == IPPROTO_SCTP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) dst = sctp_hdr(skb)->dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) key->tp.dst = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) /* Modelled after nf_nat_ipv[46]_fn().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * range is only used for new, uninitialized NAT state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * Returns either NF_ACCEPT or NF_DROP.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) enum ip_conntrack_info ctinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) const struct nf_nat_range2 *range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) enum nf_nat_manip_type maniptype, struct sw_flow_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) int hooknum, nh_off, err = NF_ACCEPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) nh_off = skb_network_offset(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) skb_pull_rcsum(skb, nh_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) /* See HOOK2MANIP(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (maniptype == NF_NAT_MANIP_SRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) hooknum = NF_INET_LOCAL_IN; /* Source NAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) hooknum = NF_INET_LOCAL_OUT; /* Destination NAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) switch (ctinfo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) case IP_CT_RELATED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) case IP_CT_RELATED_REPLY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (IS_ENABLED(CONFIG_NF_NAT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) skb->protocol == htons(ETH_P_IP) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) ip_hdr(skb)->protocol == IPPROTO_ICMP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) hooknum))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) err = NF_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) goto push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) } else if (IS_ENABLED(CONFIG_IPV6) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) skb->protocol == htons(ETH_P_IPV6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) __be16 frag_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) u8 nexthdr = ipv6_hdr(skb)->nexthdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) int hdrlen = ipv6_skip_exthdr(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) sizeof(struct ipv6hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) &nexthdr, &frag_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (!nf_nat_icmpv6_reply_translation(skb, ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ctinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) hooknum,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) hdrlen))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) err = NF_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) goto push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /* Non-ICMP, fall thru to initialize if needed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) case IP_CT_NEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /* Seen it before? This can happen for loopback, retrans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * or local packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (!nf_nat_initialized(ct, maniptype)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /* Initialize according to the NAT action. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) err = (range && range->flags & NF_NAT_RANGE_MAP_IPS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /* Action is set up to establish a new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ? nf_nat_setup_info(ct, range, maniptype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) : nf_nat_alloc_null_binding(ct, hooknum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (err != NF_ACCEPT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) goto push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) case IP_CT_ESTABLISHED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) case IP_CT_ESTABLISHED_REPLY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) err = NF_DROP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) goto push;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) err = nf_nat_packet(ct, ctinfo, hooknum, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) push:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) skb_push(skb, nh_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) skb_postpush_rcsum(skb, skb->data, nh_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) /* Update the flow key if NAT successful. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (err == NF_ACCEPT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) ovs_nat_update_key(key, skb, maniptype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) /* Returns NF_DROP if the packet should be dropped, NF_ACCEPT otherwise. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct sk_buff *skb, struct nf_conn *ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) enum ip_conntrack_info ctinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) enum nf_nat_manip_type maniptype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /* Add NAT extension if not confirmed yet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) if (!nf_ct_is_confirmed(ct) && !nf_ct_nat_ext_add(ct))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return NF_ACCEPT; /* Can't NAT. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) /* Determine NAT type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * Check if the NAT type can be deduced from the tracked connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * Make sure new expected connections (IP_CT_RELATED) are NATted only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) * when committing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (info->nat & OVS_CT_NAT && ctinfo != IP_CT_NEW &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) ct->status & IPS_NAT_MASK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) (ctinfo != IP_CT_RELATED || info->commit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /* NAT an established or related connection like before. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) /* This is the REPLY direction for a connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) * for which NAT was applied in the forward
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) * direction. Do the reverse NAT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) maniptype = ct->status & IPS_SRC_NAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) ? NF_NAT_MANIP_DST : NF_NAT_MANIP_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) maniptype = ct->status & IPS_SRC_NAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) ? NF_NAT_MANIP_SRC : NF_NAT_MANIP_DST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) } else if (info->nat & OVS_CT_SRC_NAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) maniptype = NF_NAT_MANIP_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) } else if (info->nat & OVS_CT_DST_NAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) maniptype = NF_NAT_MANIP_DST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) return NF_ACCEPT; /* Connection is not NATed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) if (err == NF_ACCEPT && ct->status & IPS_DST_NAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (ct->status & IPS_SRC_NAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (maniptype == NF_NAT_MANIP_SRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) maniptype = NF_NAT_MANIP_DST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) maniptype = NF_NAT_MANIP_SRC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) maniptype, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) } else if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) err = ovs_ct_nat_execute(skb, ct, ctinfo, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) NF_NAT_MANIP_SRC, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) #else /* !CONFIG_NF_NAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct sk_buff *skb, struct nf_conn *ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) enum ip_conntrack_info ctinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return NF_ACCEPT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* Pass 'skb' through conntrack in 'net', using zone configured in 'info', if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) * not done already. Update key with new CT state after passing the packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) * through conntrack.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) * Note that if the packet is deemed invalid by conntrack, skb->_nfct will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) * set to NULL and 0 will be returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /* If we are recirculating packets to match on conntrack fields and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) * committing with a separate conntrack action, then we don't need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * actually run the packet through conntrack twice unless it's for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * different zone.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) bool cached = skb_nfct_cached(net, key, info, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) enum ip_conntrack_info ctinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (!cached) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) struct nf_hook_state state = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) .hook = NF_INET_PRE_ROUTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) .pf = info->family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .net = net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct nf_conn *tmpl = info->ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) /* Associate skb with specified zone. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) if (tmpl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (skb_nfct(skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) nf_conntrack_put(skb_nfct(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) nf_conntrack_get(&tmpl->ct_general);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) nf_ct_set(skb, tmpl, IP_CT_NEW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) err = nf_conntrack_in(skb, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (err != NF_ACCEPT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* Clear CT state NAT flags to mark that we have not yet done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * NAT after the nf_conntrack_in() call. We can actually clear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * the whole state, as it will be re-initialized below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) key->ct_state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) /* Update the key, but keep the NAT flags. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) ovs_ct_update_key(skb, info, key, true, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) ct = nf_ct_get(skb, &ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (ct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) bool add_helper = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /* Packets starting a new connection must be NATted before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * helper, so that the helper knows about the NAT. We enforce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * this by delaying both NAT and helper calls for unconfirmed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) * connections until the committing CT action. For later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) * packets NAT and Helper may be called in either order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) * NAT will be done only if the CT action has NAT, and only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) * once per packet (per zone), as guarded by the NAT bits in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) * the key->ct_state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (info->nat && !(key->ct_state & OVS_CS_F_NAT_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) (nf_ct_is_confirmed(ct) || info->commit) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) ovs_ct_nat(net, key, info, skb, ct, ctinfo) != NF_ACCEPT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) /* Userspace may decide to perform a ct lookup without a helper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * specified followed by a (recirculate and) commit with one,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) * or attach a helper in a later commit. Therefore, for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * connections which we will commit, we may need to attach
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) * the helper here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (info->commit && info->helper && !nfct_help(ct)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) int err = __nf_ct_try_assign_helper(ct, info->ct,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) add_helper = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /* helper installed, add seqadj if NAT is required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (info->nat && !nfct_seqadj(ct)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (!nfct_seqadj_ext_add(ct))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) /* Call the helper only if:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * - nf_conntrack_in() was executed above ("!cached") or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * helper was just attached ("add_helper") for a confirmed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * connection, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * - When committing an unconfirmed connection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) if ((nf_ct_is_confirmed(ct) ? !cached || add_helper :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) info->commit) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) /* Lookup connection and read fields into key. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) struct nf_conntrack_expect *exp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) /* If we pass an expected packet through nf_conntrack_in() the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * expectation is typically removed, but the packet could still be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * lost in upcall processing. To prevent this from happening we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) * perform an explicit expectation lookup. Expected connections are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) * always new, and will be passed through conntrack only when they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * committed, as it is OK to remove the expectation at that time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) exp = ovs_ct_expect_find(net, &info->zone, info->family, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (exp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) u8 state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* NOTE: New connections are NATted and Helped only when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * committed, so we are not calling into NAT here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) state = OVS_CS_F_TRACKED | OVS_CS_F_NEW | OVS_CS_F_RELATED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) __ovs_ct_update_key(key, state, &info->zone, exp->master);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) err = __ovs_ct_lookup(net, key, info, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) ct = (struct nf_conn *)skb_nfct(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) if (ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) nf_ct_deliver_cached_events(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) size_t i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) for (i = 0; i < OVS_CT_LABELS_LEN_32; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (labels->ct_labels_32[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) static struct hlist_head *ct_limit_hash_bucket(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) const struct ovs_ct_limit_info *info, u16 zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return &info->limits[zone & (CT_LIMIT_HASH_BUCKETS - 1)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) /* Call with ovs_mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) static void ct_limit_set(const struct ovs_ct_limit_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct ovs_ct_limit *new_ct_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) struct ovs_ct_limit *ct_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) head = ct_limit_hash_bucket(info, new_ct_limit->zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) hlist_for_each_entry_rcu(ct_limit, head, hlist_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (ct_limit->zone == new_ct_limit->zone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) hlist_replace_rcu(&ct_limit->hlist_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) &new_ct_limit->hlist_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) kfree_rcu(ct_limit, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) hlist_add_head_rcu(&new_ct_limit->hlist_node, head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) /* Call with ovs_mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static void ct_limit_del(const struct ovs_ct_limit_info *info, u16 zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) struct ovs_ct_limit *ct_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) struct hlist_node *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) head = ct_limit_hash_bucket(info, zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) hlist_for_each_entry_safe(ct_limit, n, head, hlist_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (ct_limit->zone == zone) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) hlist_del_rcu(&ct_limit->hlist_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) kfree_rcu(ct_limit, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) /* Call with RCU read lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) static u32 ct_limit_get(const struct ovs_ct_limit_info *info, u16 zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) struct ovs_ct_limit *ct_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) head = ct_limit_hash_bucket(info, zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) hlist_for_each_entry_rcu(ct_limit, head, hlist_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (ct_limit->zone == zone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) return ct_limit->limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) return info->default_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static int ovs_ct_check_limit(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) const struct nf_conntrack_tuple *tuple)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) const struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) u32 per_zone_limit, connections;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) u32 conncount_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) conncount_key = info->zone.id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) per_zone_limit = ct_limit_get(ct_limit_info, info->zone.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (per_zone_limit == OVS_CT_LIMIT_UNLIMITED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) connections = nf_conncount_count(net, ct_limit_info->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) &conncount_key, tuple, &info->zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) if (connections > per_zone_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) /* Lookup connection and confirm if unconfirmed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) enum ip_conntrack_info ctinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) struct nf_conn *ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) err = __ovs_ct_lookup(net, key, info, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) /* The connection could be invalid, in which case this is a no-op.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ct = nf_ct_get(skb, &ctinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (!ct)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (static_branch_unlikely(&ovs_ct_limit_enabled)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (!nf_ct_is_confirmed(ct)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) err = ovs_ct_check_limit(net, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) net_warn_ratelimited("openvswitch: zone: %u "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) "exceeds conntrack limit\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) info->zone.id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) /* Set the conntrack event mask if given. NEW and DELETE events have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) * their own groups, but the NFNLGRP_CONNTRACK_UPDATE group listener
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) * typically would receive many kinds of updates. Setting the event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) * mask allows those events to be filtered. The set event mask will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) * remain in effect for the lifetime of the connection unless changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) * by a further CT action with both the commit flag and the eventmask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * option. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) if (info->have_eventmask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) struct nf_conntrack_ecache *cache = nf_ct_ecache_find(ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) if (cache)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) cache->ctmask = info->eventmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* Apply changes before confirming the connection so that the initial
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * conntrack NEW netlink event carries the values given in the CT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * action.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) if (info->mark.mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) err = ovs_ct_set_mark(ct, key, info->mark.value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) info->mark.mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (!nf_ct_is_confirmed(ct)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) err = ovs_ct_init_labels(ct, key, &info->labels.value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) &info->labels.mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) } else if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) labels_nonzero(&info->labels.mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) err = ovs_ct_set_labels(ct, key, &info->labels.value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) &info->labels.mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) /* This will take care of sending queued events even if the connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * is already confirmed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (nf_conntrack_confirm(skb) != NF_ACCEPT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) /* Trim the skb to the length specified by the IP/IPv6 header,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) * removing any trailing lower-layer padding. This prepares the skb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * for higher-layer processing that assumes skb->len excludes padding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) * (such as nf_ip_checksum). The caller needs to pull the skb to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * network header, and ensure ip_hdr/ipv6_hdr points to valid data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static int ovs_skb_network_trim(struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) unsigned int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) switch (skb->protocol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) case htons(ETH_P_IP):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) len = ntohs(ip_hdr(skb)->tot_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) case htons(ETH_P_IPV6):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) len = sizeof(struct ipv6hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) + ntohs(ipv6_hdr(skb)->payload_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) err = pskb_trim_rcsum(skb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * value if 'skb' is freed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) int ovs_ct_execute(struct net *net, struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) const struct ovs_conntrack_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) int nh_ofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /* The conntrack module expects to be working at L3. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) nh_ofs = skb_network_offset(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) skb_pull_rcsum(skb, nh_ofs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) err = ovs_skb_network_trim(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) err = handle_fragments(net, key, info->zone.id, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) if (info->commit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) err = ovs_ct_commit(net, key, info, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) err = ovs_ct_lookup(net, key, info, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) skb_push(skb, nh_ofs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) skb_postpush_rcsum(skb, skb->data, nh_ofs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) int ovs_ct_clear(struct sk_buff *skb, struct sw_flow_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (skb_nfct(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) nf_conntrack_put(skb_nfct(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) ovs_ct_fill_key(skb, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) const struct sw_flow_key *key, bool log)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) struct nf_conntrack_helper *helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) struct nf_conn_help *help;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) helper = nf_conntrack_helper_try_module_get(name, info->family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) key->ip.proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if (!helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) OVS_NLERR(log, "Unknown helper \"%s\"", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) help = nf_ct_helper_ext_add(info->ct, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) if (!help) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) nf_conntrack_helper_put(helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (info->nat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) ret = nf_nat_helper_try_module_get(name, info->family,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) key->ip.proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) nf_conntrack_helper_put(helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) OVS_NLERR(log, "Failed to load \"%s\" NAT helper, error: %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) name, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) rcu_assign_pointer(help->helper, helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) info->helper = helper;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) static int parse_nat(const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) struct ovs_conntrack_info *info, bool log)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) struct nlattr *a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) int rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) bool have_ip_max = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) bool have_proto_max = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) bool ip_vers = (info->family == NFPROTO_IPV6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) nla_for_each_nested(a, attr, rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) static const int ovs_nat_attr_lens[OVS_NAT_ATTR_MAX + 1][2] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) [OVS_NAT_ATTR_SRC] = {0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) [OVS_NAT_ATTR_DST] = {0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) [OVS_NAT_ATTR_IP_MIN] = {sizeof(struct in_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) sizeof(struct in6_addr)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) [OVS_NAT_ATTR_IP_MAX] = {sizeof(struct in_addr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) sizeof(struct in6_addr)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) [OVS_NAT_ATTR_PROTO_MIN] = {sizeof(u16), sizeof(u16)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) [OVS_NAT_ATTR_PROTO_MAX] = {sizeof(u16), sizeof(u16)},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) [OVS_NAT_ATTR_PERSISTENT] = {0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) [OVS_NAT_ATTR_PROTO_HASH] = {0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) [OVS_NAT_ATTR_PROTO_RANDOM] = {0, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) int type = nla_type(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (type > OVS_NAT_ATTR_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) OVS_NLERR(log, "Unknown NAT attribute (type=%d, max=%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) type, OVS_NAT_ATTR_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) if (nla_len(a) != ovs_nat_attr_lens[type][ip_vers]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) OVS_NLERR(log, "NAT attribute type %d has unexpected length (%d != %d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) type, nla_len(a),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) ovs_nat_attr_lens[type][ip_vers]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) case OVS_NAT_ATTR_SRC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) case OVS_NAT_ATTR_DST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (info->nat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) OVS_NLERR(log, "Only one type of NAT may be specified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) return -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) info->nat |= OVS_CT_NAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) info->nat |= ((type == OVS_NAT_ATTR_SRC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) ? OVS_CT_SRC_NAT : OVS_CT_DST_NAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) case OVS_NAT_ATTR_IP_MIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) nla_memcpy(&info->range.min_addr, a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) sizeof(info->range.min_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) info->range.flags |= NF_NAT_RANGE_MAP_IPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) case OVS_NAT_ATTR_IP_MAX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) have_ip_max = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) nla_memcpy(&info->range.max_addr, a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) sizeof(info->range.max_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) info->range.flags |= NF_NAT_RANGE_MAP_IPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) case OVS_NAT_ATTR_PROTO_MIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) info->range.min_proto.all = htons(nla_get_u16(a));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) info->range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) case OVS_NAT_ATTR_PROTO_MAX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) have_proto_max = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) info->range.max_proto.all = htons(nla_get_u16(a));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) info->range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) case OVS_NAT_ATTR_PERSISTENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) info->range.flags |= NF_NAT_RANGE_PERSISTENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) case OVS_NAT_ATTR_PROTO_HASH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) info->range.flags |= NF_NAT_RANGE_PROTO_RANDOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) case OVS_NAT_ATTR_PROTO_RANDOM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) info->range.flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) OVS_NLERR(log, "Unknown nat attribute (%d)", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (rem > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) OVS_NLERR(log, "NAT attribute has %d unknown bytes", rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (!info->nat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /* Do not allow flags if no type is given. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) if (info->range.flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) OVS_NLERR(log,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) "NAT flags may be given only when NAT range (SRC or DST) is also specified."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) info->nat = OVS_CT_NAT; /* NAT existing connections. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) } else if (!info->commit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) OVS_NLERR(log,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) "NAT attributes may be specified only when CT COMMIT flag is also specified."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) /* Allow missing IP_MAX. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) if (info->range.flags & NF_NAT_RANGE_MAP_IPS && !have_ip_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) memcpy(&info->range.max_addr, &info->range.min_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) sizeof(info->range.max_addr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) /* Allow missing PROTO_MAX. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (info->range.flags & NF_NAT_RANGE_PROTO_SPECIFIED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) !have_proto_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) info->range.max_proto.all = info->range.min_proto.all;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) [OVS_CT_ATTR_COMMIT] = { .minlen = 0, .maxlen = 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) [OVS_CT_ATTR_FORCE_COMMIT] = { .minlen = 0, .maxlen = 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) [OVS_CT_ATTR_ZONE] = { .minlen = sizeof(u16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) .maxlen = sizeof(u16) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) [OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) .maxlen = sizeof(struct md_mark) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) [OVS_CT_ATTR_LABELS] = { .minlen = sizeof(struct md_labels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) .maxlen = sizeof(struct md_labels) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) [OVS_CT_ATTR_HELPER] = { .minlen = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) .maxlen = NF_CT_HELPER_NAME_LEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) /* NAT length is checked when parsing the nested attributes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) [OVS_CT_ATTR_NAT] = { .minlen = 0, .maxlen = INT_MAX },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) [OVS_CT_ATTR_EVENTMASK] = { .minlen = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) .maxlen = sizeof(u32) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) [OVS_CT_ATTR_TIMEOUT] = { .minlen = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) .maxlen = CTNL_TIMEOUT_NAME_MAX },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) const char **helper, bool log)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) struct nlattr *a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) int rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) nla_for_each_nested(a, attr, rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) int type = nla_type(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) int maxlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) int minlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) if (type > OVS_CT_ATTR_MAX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) OVS_NLERR(log,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) "Unknown conntrack attr (type=%d, max=%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) type, OVS_CT_ATTR_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) maxlen = ovs_ct_attr_lens[type].maxlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) minlen = ovs_ct_attr_lens[type].minlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) if (nla_len(a) < minlen || nla_len(a) > maxlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) OVS_NLERR(log,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) type, nla_len(a), maxlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) case OVS_CT_ATTR_FORCE_COMMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) info->force = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) case OVS_CT_ATTR_COMMIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) info->commit = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) #ifdef CONFIG_NF_CONNTRACK_ZONES
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) case OVS_CT_ATTR_ZONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) info->zone.id = nla_get_u16(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) #ifdef CONFIG_NF_CONNTRACK_MARK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) case OVS_CT_ATTR_MARK: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) struct md_mark *mark = nla_data(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) if (!mark->mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) OVS_NLERR(log, "ct_mark mask cannot be 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) info->mark = *mark;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) #ifdef CONFIG_NF_CONNTRACK_LABELS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) case OVS_CT_ATTR_LABELS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) struct md_labels *labels = nla_data(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (!labels_nonzero(&labels->mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) OVS_NLERR(log, "ct_labels mask cannot be 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) info->labels = *labels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) case OVS_CT_ATTR_HELPER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) *helper = nla_data(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) if (!memchr(*helper, '\0', nla_len(a))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) OVS_NLERR(log, "Invalid conntrack helper");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) case OVS_CT_ATTR_NAT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) int err = parse_nat(a, info, log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) case OVS_CT_ATTR_EVENTMASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) info->have_eventmask = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) info->eventmask = nla_get_u32(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) case OVS_CT_ATTR_TIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) memcpy(info->timeout, nla_data(a), nla_len(a));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (!memchr(info->timeout, '\0', nla_len(a))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) OVS_NLERR(log, "Invalid conntrack timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) OVS_NLERR(log, "Unknown conntrack attr (%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) #ifdef CONFIG_NF_CONNTRACK_MARK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (!info->commit && info->mark.mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) OVS_NLERR(log,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) "Setting conntrack mark requires 'commit' flag.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) #ifdef CONFIG_NF_CONNTRACK_LABELS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (!info->commit && labels_nonzero(&info->labels.mask)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) OVS_NLERR(log,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) "Setting conntrack labels requires 'commit' flag.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if (rem > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) if (attr == OVS_KEY_ATTR_CT_STATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) attr == OVS_KEY_ATTR_CT_ZONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) attr == OVS_KEY_ATTR_CT_MARK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) attr == OVS_KEY_ATTR_CT_LABELS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) return ovs_net->xt_label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) const struct sw_flow_key *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) struct sw_flow_actions **sfa, bool log)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) struct ovs_conntrack_info ct_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) const char *helper = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) u16 family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) family = key_to_nfproto(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) if (family == NFPROTO_UNSPEC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) OVS_NLERR(log, "ct family unspecified");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) memset(&ct_info, 0, sizeof(ct_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) ct_info.family = family;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) nf_ct_zone_init(&ct_info.zone, NF_CT_DEFAULT_ZONE_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) NF_CT_DEFAULT_ZONE_DIR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) err = parse_ct(attr, &ct_info, &helper, log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) /* Set up template for tracking connections in specific zones. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) ct_info.ct = nf_ct_tmpl_alloc(net, &ct_info.zone, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) if (!ct_info.ct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) OVS_NLERR(log, "Failed to allocate conntrack template");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) if (ct_info.timeout[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) ct_info.timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) pr_info_ratelimited("Failed to associated timeout "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) "policy `%s'\n", ct_info.timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) ct_info.nf_ct_timeout = rcu_dereference(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) nf_ct_timeout_find(ct_info.ct)->timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) if (helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) err = ovs_ct_add_helper(&ct_info, helper, key, log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) goto err_free_ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) err = ovs_nla_add_action(sfa, OVS_ACTION_ATTR_CT, &ct_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) sizeof(ct_info), log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) goto err_free_ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) nf_conntrack_get(&ct_info.ct->ct_general);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) err_free_ct:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) __ovs_ct_free_action(&ct_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) static bool ovs_ct_nat_to_attr(const struct ovs_conntrack_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct nlattr *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) start = nla_nest_start_noflag(skb, OVS_CT_ATTR_NAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) if (!start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) if (info->nat & OVS_CT_SRC_NAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) if (nla_put_flag(skb, OVS_NAT_ATTR_SRC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) } else if (info->nat & OVS_CT_DST_NAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) if (nla_put_flag(skb, OVS_NAT_ATTR_DST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) if (info->range.flags & NF_NAT_RANGE_MAP_IPS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) if (IS_ENABLED(CONFIG_NF_NAT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) info->family == NFPROTO_IPV4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) if (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) info->range.min_addr.ip) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) (info->range.max_addr.ip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) != info->range.min_addr.ip &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) info->range.max_addr.ip))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) } else if (IS_ENABLED(CONFIG_IPV6) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) info->family == NFPROTO_IPV6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) &info->range.min_addr.in6) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) (memcmp(&info->range.max_addr.in6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) &info->range.min_addr.in6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) sizeof(info->range.max_addr.in6)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) &info->range.max_addr.in6))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) if (info->range.flags & NF_NAT_RANGE_PROTO_SPECIFIED &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) (nla_put_u16(skb, OVS_NAT_ATTR_PROTO_MIN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) ntohs(info->range.min_proto.all)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) (info->range.max_proto.all != info->range.min_proto.all &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) nla_put_u16(skb, OVS_NAT_ATTR_PROTO_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) ntohs(info->range.max_proto.all)))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) if (info->range.flags & NF_NAT_RANGE_PERSISTENT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) nla_put_flag(skb, OVS_NAT_ATTR_PERSISTENT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (info->range.flags & NF_NAT_RANGE_PROTO_RANDOM &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) nla_put_flag(skb, OVS_NAT_ATTR_PROTO_HASH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) if (info->range.flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) nla_put_flag(skb, OVS_NAT_ATTR_PROTO_RANDOM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) nla_nest_end(skb, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) struct nlattr *start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) start = nla_nest_start_noflag(skb, OVS_ACTION_ATTR_CT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (!start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (ct_info->commit && nla_put_flag(skb, ct_info->force
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) ? OVS_CT_ATTR_FORCE_COMMIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) : OVS_CT_ATTR_COMMIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) &ct_info->mark))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) labels_nonzero(&ct_info->labels.mask) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) &ct_info->labels))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) if (ct_info->helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) ct_info->helper->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) if (ct_info->have_eventmask &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) nla_put_u32(skb, OVS_CT_ATTR_EVENTMASK, ct_info->eventmask))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) if (ct_info->timeout[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) if (nla_put_string(skb, OVS_CT_ATTR_TIMEOUT, ct_info->timeout))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) if (ct_info->nat && !ovs_ct_nat_to_attr(ct_info, skb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) nla_nest_end(skb, start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) void ovs_ct_free_action(const struct nlattr *a)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) struct ovs_conntrack_info *ct_info = nla_data(a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) __ovs_ct_free_action(ct_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) if (ct_info->helper) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) #if IS_ENABLED(CONFIG_NF_NAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) if (ct_info->nat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) nf_nat_helper_put(ct_info->helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) nf_conntrack_helper_put(ct_info->helper);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) if (ct_info->ct) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) if (ct_info->timeout[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) nf_ct_destroy_timeout(ct_info->ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) nf_ct_tmpl_free(ct_info->ct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) static int ovs_ct_limit_init(struct net *net, struct ovs_net *ovs_net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) ovs_net->ct_limit_info = kmalloc(sizeof(*ovs_net->ct_limit_info),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) if (!ovs_net->ct_limit_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) ovs_net->ct_limit_info->default_limit = OVS_CT_LIMIT_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) ovs_net->ct_limit_info->limits =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) kmalloc_array(CT_LIMIT_HASH_BUCKETS, sizeof(struct hlist_head),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) if (!ovs_net->ct_limit_info->limits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) kfree(ovs_net->ct_limit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) for (i = 0; i < CT_LIMIT_HASH_BUCKETS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) INIT_HLIST_HEAD(&ovs_net->ct_limit_info->limits[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) ovs_net->ct_limit_info->data =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) nf_conncount_init(net, NFPROTO_INET, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) if (IS_ERR(ovs_net->ct_limit_info->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) err = PTR_ERR(ovs_net->ct_limit_info->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) kfree(ovs_net->ct_limit_info->limits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) kfree(ovs_net->ct_limit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) pr_err("openvswitch: failed to init nf_conncount %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) const struct ovs_ct_limit_info *info = ovs_net->ct_limit_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) nf_conncount_destroy(net, NFPROTO_INET, info->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) struct hlist_head *head = &info->limits[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) struct ovs_ct_limit *ct_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) hlist_for_each_entry_rcu(ct_limit, head, hlist_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) lockdep_ovsl_is_held())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) kfree_rcu(ct_limit, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) kfree(info->limits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) kfree(info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) static struct sk_buff *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) ovs_ct_limit_cmd_reply_start(struct genl_info *info, u8 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) struct ovs_header **ovs_reply_header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) struct ovs_header *ovs_header = info->userhdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) *ovs_reply_header = genlmsg_put(skb, info->snd_portid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) info->snd_seq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) &dp_ct_limit_genl_family, 0, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) if (!*ovs_reply_header) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) nlmsg_free(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) return ERR_PTR(-EMSGSIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) (*ovs_reply_header)->dp_ifindex = ovs_header->dp_ifindex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) static bool check_zone_id(int zone_id, u16 *pzone)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) if (zone_id >= 0 && zone_id <= 65535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) *pzone = (u16)zone_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) static int ovs_ct_limit_set_zone_limit(struct nlattr *nla_zone_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) struct ovs_ct_limit_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) struct ovs_zone_limit *zone_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) int rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) u16 zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) rem = NLA_ALIGN(nla_len(nla_zone_limit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) zone_limit = (struct ovs_zone_limit *)nla_data(nla_zone_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) while (rem >= sizeof(*zone_limit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) if (unlikely(zone_limit->zone_id ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) OVS_ZONE_LIMIT_DEFAULT_ZONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) ovs_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) info->default_limit = zone_limit->limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) ovs_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) } else if (unlikely(!check_zone_id(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) zone_limit->zone_id, &zone))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) OVS_NLERR(true, "zone id is out of range");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) struct ovs_ct_limit *ct_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) ct_limit = kmalloc(sizeof(*ct_limit), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) if (!ct_limit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) ct_limit->zone = zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) ct_limit->limit = zone_limit->limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) ovs_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) ct_limit_set(info, ct_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) ovs_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) rem -= NLA_ALIGN(sizeof(*zone_limit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) zone_limit = (struct ovs_zone_limit *)((u8 *)zone_limit +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) NLA_ALIGN(sizeof(*zone_limit)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) if (rem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) OVS_NLERR(true, "set zone limit has %d unknown bytes", rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) static int ovs_ct_limit_del_zone_limit(struct nlattr *nla_zone_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) struct ovs_ct_limit_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) struct ovs_zone_limit *zone_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) int rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) u16 zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) rem = NLA_ALIGN(nla_len(nla_zone_limit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) zone_limit = (struct ovs_zone_limit *)nla_data(nla_zone_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) while (rem >= sizeof(*zone_limit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) if (unlikely(zone_limit->zone_id ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) OVS_ZONE_LIMIT_DEFAULT_ZONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) ovs_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) info->default_limit = OVS_CT_LIMIT_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) ovs_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) } else if (unlikely(!check_zone_id(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) zone_limit->zone_id, &zone))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) OVS_NLERR(true, "zone id is out of range");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) ovs_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) ct_limit_del(info, zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) ovs_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) rem -= NLA_ALIGN(sizeof(*zone_limit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) zone_limit = (struct ovs_zone_limit *)((u8 *)zone_limit +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) NLA_ALIGN(sizeof(*zone_limit)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) if (rem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) OVS_NLERR(true, "del zone limit has %d unknown bytes", rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) static int ovs_ct_limit_get_default_limit(struct ovs_ct_limit_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) struct sk_buff *reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) struct ovs_zone_limit zone_limit = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) .zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) .limit = info->default_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) return nla_put_nohdr(reply, sizeof(zone_limit), &zone_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) static int __ovs_ct_limit_get_zone_limit(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) struct nf_conncount_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) u16 zone_id, u32 limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) struct sk_buff *reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) struct nf_conntrack_zone ct_zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) struct ovs_zone_limit zone_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) u32 conncount_key = zone_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) zone_limit.zone_id = zone_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) zone_limit.limit = limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) nf_ct_zone_init(&ct_zone, zone_id, NF_CT_DEFAULT_ZONE_DIR, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) zone_limit.count = nf_conncount_count(net, data, &conncount_key, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) &ct_zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) return nla_put_nohdr(reply, sizeof(zone_limit), &zone_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) static int ovs_ct_limit_get_zone_limit(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) struct nlattr *nla_zone_limit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) struct ovs_ct_limit_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) struct sk_buff *reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) struct ovs_zone_limit *zone_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) int rem, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) u32 limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) u16 zone;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) rem = NLA_ALIGN(nla_len(nla_zone_limit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) zone_limit = (struct ovs_zone_limit *)nla_data(nla_zone_limit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) while (rem >= sizeof(*zone_limit)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) if (unlikely(zone_limit->zone_id ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) OVS_ZONE_LIMIT_DEFAULT_ZONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) err = ovs_ct_limit_get_default_limit(info, reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) } else if (unlikely(!check_zone_id(zone_limit->zone_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) &zone))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) OVS_NLERR(true, "zone id is out of range");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) limit = ct_limit_get(info, zone);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) err = __ovs_ct_limit_get_zone_limit(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) net, info->data, zone, limit, reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) rem -= NLA_ALIGN(sizeof(*zone_limit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) zone_limit = (struct ovs_zone_limit *)((u8 *)zone_limit +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) NLA_ALIGN(sizeof(*zone_limit)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) if (rem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) OVS_NLERR(true, "get zone limit has %d unknown bytes", rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) static int ovs_ct_limit_get_all_zone_limit(struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) struct ovs_ct_limit_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) struct sk_buff *reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) struct ovs_ct_limit *ct_limit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) struct hlist_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) int i, err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) err = ovs_ct_limit_get_default_limit(info, reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) head = &info->limits[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) hlist_for_each_entry_rcu(ct_limit, head, hlist_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) err = __ovs_ct_limit_get_zone_limit(net, info->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) ct_limit->zone, ct_limit->limit, reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) exit_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) static int ovs_ct_limit_cmd_set(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) struct nlattr **a = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) struct sk_buff *reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) struct ovs_header *ovs_reply_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) struct ovs_net *ovs_net = net_generic(sock_net(skb->sk), ovs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) reply = ovs_ct_limit_cmd_reply_start(info, OVS_CT_LIMIT_CMD_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) &ovs_reply_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) if (IS_ERR(reply))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) return PTR_ERR(reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) if (!a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) err = ovs_ct_limit_set_zone_limit(a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) ct_limit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) static_branch_enable(&ovs_ct_limit_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) genlmsg_end(reply, ovs_reply_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) return genlmsg_reply(reply, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) exit_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) nlmsg_free(reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) static int ovs_ct_limit_cmd_del(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) struct nlattr **a = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) struct sk_buff *reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) struct ovs_header *ovs_reply_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) struct ovs_net *ovs_net = net_generic(sock_net(skb->sk), ovs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) reply = ovs_ct_limit_cmd_reply_start(info, OVS_CT_LIMIT_CMD_DEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) &ovs_reply_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) if (IS_ERR(reply))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) return PTR_ERR(reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) if (!a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) err = ovs_ct_limit_del_zone_limit(a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) ct_limit_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) genlmsg_end(reply, ovs_reply_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) return genlmsg_reply(reply, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) exit_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) nlmsg_free(reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) static int ovs_ct_limit_cmd_get(struct sk_buff *skb, struct genl_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) struct nlattr **a = info->attrs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) struct nlattr *nla_reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194) struct sk_buff *reply;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) struct ovs_header *ovs_reply_header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) struct net *net = sock_net(skb->sk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) struct ovs_ct_limit_info *ct_limit_info = ovs_net->ct_limit_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) reply = ovs_ct_limit_cmd_reply_start(info, OVS_CT_LIMIT_CMD_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) &ovs_reply_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) if (IS_ERR(reply))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) return PTR_ERR(reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) nla_reply = nla_nest_start_noflag(reply, OVS_CT_LIMIT_ATTR_ZONE_LIMIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) if (!nla_reply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) err = -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) if (a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213) err = ovs_ct_limit_get_zone_limit(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) net, a[OVS_CT_LIMIT_ATTR_ZONE_LIMIT], ct_limit_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) err = ovs_ct_limit_get_all_zone_limit(net, ct_limit_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) goto exit_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) nla_nest_end(reply, nla_reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) genlmsg_end(reply, ovs_reply_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227) return genlmsg_reply(reply, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) exit_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) nlmsg_free(reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) static const struct genl_small_ops ct_limit_genl_ops[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) { .cmd = OVS_CT_LIMIT_CMD_SET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) * privilege. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239) .doit = ovs_ct_limit_cmd_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) { .cmd = OVS_CT_LIMIT_CMD_DEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) * privilege. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245) .doit = ovs_ct_limit_cmd_del,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) { .cmd = OVS_CT_LIMIT_CMD_GET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) .flags = 0, /* OK for unprivileged users. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250) .doit = ovs_ct_limit_cmd_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) static const struct genl_multicast_group ovs_ct_limit_multicast_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255) .name = OVS_CT_LIMIT_MCGROUP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) struct genl_family dp_ct_limit_genl_family __ro_after_init = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) .hdrsize = sizeof(struct ovs_header),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260) .name = OVS_CT_LIMIT_FAMILY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) .version = OVS_CT_LIMIT_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) .maxattr = OVS_CT_LIMIT_ATTR_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) .policy = ct_limit_policy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) .netnsok = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265) .parallel_ops = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) .small_ops = ct_limit_genl_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267) .n_small_ops = ARRAY_SIZE(ct_limit_genl_ops),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) .mcgrps = &ovs_ct_limit_multicast_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) .n_mcgrps = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) .module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) int ovs_ct_init(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277) struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) if (nf_connlabels_get(net, n_bits - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) ovs_net->xt_label = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) OVS_NLERR(true, "Failed to set connlabel length");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) ovs_net->xt_label = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287) return ovs_ct_limit_init(net, ovs_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) void ovs_ct_exit(struct net *net)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) #if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) ovs_ct_limit_exit(net, ovs_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) if (ovs_net->xt_label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302) nf_connlabels_put(net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) }