1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2012-2016 Pablo Neira Ayuso <pablo@netfilter.org> 4 */ 5 6 #include <linux/init.h> 7 #include <linux/module.h> 8 #include <linux/skbuff.h> 9 #include <linux/netlink.h> 10 #include <linux/netfilter.h> 11 #include <linux/netfilter/nf_tables.h> 12 #include <net/netfilter/nf_tables_core.h> 13 14 #define nft_objref_priv(expr) *((struct nft_object **)nft_expr_priv(expr)) 15 16 void nft_objref_eval(const struct nft_expr *expr, 17 struct nft_regs *regs, 18 const struct nft_pktinfo *pkt) 19 { 20 struct nft_object *obj = nft_objref_priv(expr); 21 22 obj->ops->eval(obj, regs, pkt); 23 } 24 25 static int nft_objref_validate_obj_type(const struct nft_ctx *ctx, u32 type) 26 { 27 unsigned int hooks; 28 29 switch (type) { 30 case NFT_OBJECT_SYNPROXY: 31 if (ctx->family != NFPROTO_IPV4 && 32 ctx->family != NFPROTO_IPV6 && 33 ctx->family != NFPROTO_INET) 34 return -EOPNOTSUPP; 35 36 hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD); 37 38 return nft_chain_validate_hooks(ctx->chain, hooks); 39 default: 40 break; 41 } 42 43 return 0; 44 } 45 46 static int nft_objref_validate(const struct nft_ctx *ctx, 47 const struct nft_expr *expr) 48 { 49 struct nft_object *obj = nft_objref_priv(expr); 50 51 return nft_objref_validate_obj_type(ctx, obj->ops->type->type); 52 } 53 54 static int nft_objref_init(const struct nft_ctx *ctx, 55 const struct nft_expr *expr, 56 const struct nlattr * const tb[]) 57 { 58 struct nft_object *obj = nft_objref_priv(expr); 59 u8 genmask = nft_genmask_next(ctx->net); 60 u32 objtype; 61 62 if (!tb[NFTA_OBJREF_IMM_NAME] || 63 !tb[NFTA_OBJREF_IMM_TYPE]) 64 return -EINVAL; 65 66 objtype = ntohl(nla_get_be32(tb[NFTA_OBJREF_IMM_TYPE])); 67 obj = nft_obj_lookup(ctx->net, ctx->table, 68 tb[NFTA_OBJREF_IMM_NAME], objtype, 69 genmask); 70 if (IS_ERR(obj)) 71 return -ENOENT; 72 73 if (!nft_use_inc(&obj->use)) 74 return -EMFILE; 75 76 nft_objref_priv(expr) = obj; 77 78 return 0; 79 } 80 81 static int nft_objref_dump(struct sk_buff *skb, 82 const struct nft_expr *expr, bool reset) 83 { 84 const struct nft_object *obj = nft_objref_priv(expr); 85 86 if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->key.name) || 87 nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE, 88 htonl(obj->ops->type->type))) 89 goto nla_put_failure; 90 91 return 0; 92 93 nla_put_failure: 94 return -1; 95 } 96 97 static void nft_objref_deactivate(const struct nft_ctx *ctx, 98 const struct nft_expr *expr, 99 enum nft_trans_phase phase) 100 { 101 struct nft_object *obj = nft_objref_priv(expr); 102 103 if (phase == NFT_TRANS_COMMIT) 104 return; 105 106 nft_use_dec(&obj->use); 107 } 108 109 static void nft_objref_activate(const struct nft_ctx *ctx, 110 const struct nft_expr *expr) 111 { 112 struct nft_object *obj = nft_objref_priv(expr); 113 114 nft_use_inc_restore(&obj->use); 115 } 116 117 static const struct nft_expr_ops nft_objref_ops = { 118 .type = &nft_objref_type, 119 .size = NFT_EXPR_SIZE(sizeof(struct nft_object *)), 120 .eval = nft_objref_eval, 121 .init = nft_objref_init, 122 .activate = nft_objref_activate, 123 .deactivate = nft_objref_deactivate, 124 .dump = nft_objref_dump, 125 .validate = nft_objref_validate, 126 }; 127 128 struct nft_objref_map { 129 struct nft_set *set; 130 u8 sreg; 131 struct nft_set_binding binding; 132 }; 133 134 void nft_objref_map_eval(const struct nft_expr *expr, 135 struct nft_regs *regs, 136 const struct nft_pktinfo *pkt) 137 { 138 struct nft_objref_map *priv = nft_expr_priv(expr); 139 const struct nft_set *set = priv->set; 140 struct net *net = nft_net(pkt); 141 const struct nft_set_ext *ext; 142 struct nft_object *obj; 143 144 ext = nft_set_do_lookup(net, set, ®s->data[priv->sreg]); 145 if (!ext) { 146 ext = nft_set_catchall_lookup(net, set); 147 if (!ext) { 148 regs->verdict.code = NFT_BREAK; 149 return; 150 } 151 } 152 obj = *nft_set_ext_obj(ext); 153 obj->ops->eval(obj, regs, pkt); 154 } 155 156 static int nft_objref_map_init(const struct nft_ctx *ctx, 157 const struct nft_expr *expr, 158 const struct nlattr * const tb[]) 159 { 160 struct nft_objref_map *priv = nft_expr_priv(expr); 161 u8 genmask = nft_genmask_next(ctx->net); 162 struct nft_set *set; 163 int err; 164 165 set = nft_set_lookup_global(ctx->net, ctx->table, 166 tb[NFTA_OBJREF_SET_NAME], 167 tb[NFTA_OBJREF_SET_ID], genmask); 168 if (IS_ERR(set)) 169 return PTR_ERR(set); 170 171 if (!(set->flags & NFT_SET_OBJECT)) 172 return -EINVAL; 173 174 err = nft_parse_register_load(ctx, tb[NFTA_OBJREF_SET_SREG], &priv->sreg, 175 set->klen); 176 if (err < 0) 177 return err; 178 179 priv->binding.flags = set->flags & NFT_SET_OBJECT; 180 181 err = nf_tables_bind_set(ctx, set, &priv->binding); 182 if (err < 0) 183 return err; 184 185 priv->set = set; 186 return 0; 187 } 188 189 static int nft_objref_map_dump(struct sk_buff *skb, 190 const struct nft_expr *expr, bool reset) 191 { 192 const struct nft_objref_map *priv = nft_expr_priv(expr); 193 194 if (nft_dump_register(skb, NFTA_OBJREF_SET_SREG, priv->sreg) || 195 nla_put_string(skb, NFTA_OBJREF_SET_NAME, priv->set->name)) 196 goto nla_put_failure; 197 198 return 0; 199 200 nla_put_failure: 201 return -1; 202 } 203 204 static void nft_objref_map_deactivate(const struct nft_ctx *ctx, 205 const struct nft_expr *expr, 206 enum nft_trans_phase phase) 207 { 208 struct nft_objref_map *priv = nft_expr_priv(expr); 209 210 nf_tables_deactivate_set(ctx, priv->set, &priv->binding, phase); 211 } 212 213 static void nft_objref_map_activate(const struct nft_ctx *ctx, 214 const struct nft_expr *expr) 215 { 216 struct nft_objref_map *priv = nft_expr_priv(expr); 217 218 nf_tables_activate_set(ctx, priv->set); 219 } 220 221 static void nft_objref_map_destroy(const struct nft_ctx *ctx, 222 const struct nft_expr *expr) 223 { 224 struct nft_objref_map *priv = nft_expr_priv(expr); 225 226 nf_tables_destroy_set(ctx, priv->set); 227 } 228 229 static int nft_objref_map_validate(const struct nft_ctx *ctx, 230 const struct nft_expr *expr) 231 { 232 const struct nft_objref_map *priv = nft_expr_priv(expr); 233 234 return nft_objref_validate_obj_type(ctx, priv->set->objtype); 235 } 236 237 static const struct nft_expr_ops nft_objref_map_ops = { 238 .type = &nft_objref_type, 239 .size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)), 240 .eval = nft_objref_map_eval, 241 .init = nft_objref_map_init, 242 .activate = nft_objref_map_activate, 243 .deactivate = nft_objref_map_deactivate, 244 .destroy = nft_objref_map_destroy, 245 .dump = nft_objref_map_dump, 246 .validate = nft_objref_map_validate, 247 }; 248 249 static const struct nft_expr_ops * 250 nft_objref_select_ops(const struct nft_ctx *ctx, 251 const struct nlattr * const tb[]) 252 { 253 if (tb[NFTA_OBJREF_SET_SREG] && 254 (tb[NFTA_OBJREF_SET_NAME] || 255 tb[NFTA_OBJREF_SET_ID])) 256 return &nft_objref_map_ops; 257 else if (tb[NFTA_OBJREF_IMM_NAME] && 258 tb[NFTA_OBJREF_IMM_TYPE]) 259 return &nft_objref_ops; 260 261 return ERR_PTR(-EOPNOTSUPP); 262 } 263 264 static const struct nla_policy nft_objref_policy[NFTA_OBJREF_MAX + 1] = { 265 [NFTA_OBJREF_IMM_NAME] = { .type = NLA_STRING, 266 .len = NFT_OBJ_MAXNAMELEN - 1 }, 267 [NFTA_OBJREF_IMM_TYPE] = { .type = NLA_U32 }, 268 [NFTA_OBJREF_SET_SREG] = NLA_POLICY_MAX(NLA_BE32, NFT_REG32_MAX), 269 [NFTA_OBJREF_SET_NAME] = { .type = NLA_STRING, 270 .len = NFT_SET_MAXNAMELEN - 1 }, 271 [NFTA_OBJREF_SET_ID] = { .type = NLA_U32 }, 272 }; 273 274 struct nft_expr_type nft_objref_type __read_mostly = { 275 .name = "objref", 276 .select_ops = nft_objref_select_ops, 277 .policy = nft_objref_policy, 278 .maxattr = NFTA_OBJREF_MAX, 279 .owner = THIS_MODULE, 280 }; 281