void add_addr(struct nftnl_rule *r, int offset, void *data, void *mask, size_t len, uint32_t op) { add_payload(r, offset, len, NFT_PAYLOAD_NETWORK_HEADER); add_bitwise(r, mask, len); add_cmp_ptr(r, op, data, len); }
static int build_rule_nat(const char *address, unsigned char prefixlen, const char *interface, struct nftnl_rule **res) { struct nftnl_rule *rule; struct in_addr ipv4_addr, ipv4_mask; struct nftnl_expr *expr; int err; /* * # nft --debug netlink add rule connman nat-postrouting \ * oifname eth0 ip saddr 10.10.0.0/24 masquerade * * ip connman nat-postrouting * [ meta load oifname => reg 1 ] * [ cmp eq reg 1 0x30687465 0x00000000 0x00000000 0x00000000 ] * [ payload load 4b @ network header + 12 => reg 1 ] * [ bitwise reg 1 = (reg=1 & 0x00ffffff ) ^ 0x00000000 ] * [ cmp eq reg 1 0x00000a0a ] * [ masq ] */ rule = nftnl_rule_alloc(); if (!rule) return -ENOMEM; nftnl_rule_set(rule, NFTNL_RULE_TABLE, CONNMAN_TABLE); nftnl_rule_set(rule, NFTNL_RULE_CHAIN, CONNMAN_CHAIN_NAT_POST); /* family ipv4 */ nftnl_rule_set_u32(rule, NFTNL_RULE_FAMILY, NFPROTO_IPV4); /* oifname */ expr = nftnl_expr_alloc("meta"); if (!expr) goto err; nftnl_expr_set_u32(expr, NFTNL_EXPR_META_KEY, NFT_META_OIFNAME); nftnl_expr_set_u32(expr, NFTNL_EXPR_META_DREG, NFT_REG_1); nftnl_rule_add_expr(rule, expr); err = add_cmp(rule, NFT_REG_1, NFT_CMP_EQ, interface, strlen(interface) + 1); if (err < 0) goto err; /* source */ ipv4_mask.s_addr = htonl((0xffffffff << (32 - prefixlen)) & 0xffffffff); ipv4_addr.s_addr = inet_addr(address); ipv4_addr.s_addr &= ipv4_mask.s_addr; err = add_payload(rule, NFT_PAYLOAD_NETWORK_HEADER, NFT_REG_1, offsetof(struct iphdr, saddr), sizeof(struct in_addr)); if (err < 0) goto err; err = add_bitwise(rule, NFT_REG_1, &ipv4_mask.s_addr, sizeof(struct in_addr)); if (err < 0) goto err; err = add_cmp(rule, NFT_REG_1, NFT_CMP_EQ, &ipv4_addr.s_addr, sizeof(struct in_addr)); if (err < 0) goto err; /* masquerade */ expr = nftnl_expr_alloc("masq"); if (!expr) goto err; nftnl_rule_add_expr(rule, expr); *res = rule; return 0; err: nftnl_rule_free(rule); return -ENOMEM; }