History

netfilter: nft_osf: Add version option support

Add version option support to the nftables "osf" expression.

Fernando Fernandez Mancera committed 7 years ago

Commit 22c76521 parent 6978cdb4 files · +46 −15Browse files

Unified · Split

4 files
  1. include/linux/netfilter/nfnetlink_osf.h +8 −3
  2. include/uapi/linux/netfilter/nf_tables.h +6 −0
  3. net/netfilter/nfnetlink_osf.c +7 −7
  4. net/netfilter/nft_osf.c +25 −5
include/linux/netfilter/nfnetlink_osf.h+8−3
@@ -21,13 +21,18 @@ struct nf_osf_finger { · 20 unmodified lines
21 struct nf_osf_user_finger finger;21 struct nf_osf_user_finger finger;
22};22};
23 23
24struct nf_osf_data {
25 const char *genre;
26 const char *version;
27};
28
24bool nf_osf_match(const struct sk_buff *skb, u_int8_t family,29bool nf_osf_match(const struct sk_buff *skb, u_int8_t family,
25 int hooknum, struct net_device *in, struct net_device *out,30 int hooknum, struct net_device *in, struct net_device *out,
26 const struct nf_osf_info *info, struct net *net,31 const struct nf_osf_info *info, struct net *net,
27 const struct list_head *nf_osf_fingers);32 const struct list_head *nf_osf_fingers);
28 33
29const char *nf_osf_find(const struct sk_buff *skb,34bool nf_osf_find(const struct sk_buff *skb,
30 const struct list_head *nf_osf_fingers,35 const struct list_head *nf_osf_fingers,
31 const int ttl_check);36 const int ttl_check, struct nf_osf_data *data);
32 37
33#endif /* _NFOSF_H */38#endif /* _NFOSF_H */
include/uapi/linux/netfilter/nf_tables.h+6−0
@@ -1522,15 +1522,21 @@ enum nft_flowtable_hook_attributes { · 1521 unmodified lines
1522 *1522 *
1523 * @NFTA_OSF_DREG: destination register (NLA_U32: nft_registers)1523 * @NFTA_OSF_DREG: destination register (NLA_U32: nft_registers)
1524 * @NFTA_OSF_TTL: Value of the TTL osf option (NLA_U8)1524 * @NFTA_OSF_TTL: Value of the TTL osf option (NLA_U8)
1525 * @NFTA_OSF_FLAGS: flags (NLA_U32)
1525 */1526 */
1526enum nft_osf_attributes {1527enum nft_osf_attributes {
1527 NFTA_OSF_UNSPEC,1528 NFTA_OSF_UNSPEC,
1528 NFTA_OSF_DREG,1529 NFTA_OSF_DREG,
1529 NFTA_OSF_TTL,1530 NFTA_OSF_TTL,
1531 NFTA_OSF_FLAGS,
1530 __NFTA_OSF_MAX,1532 __NFTA_OSF_MAX,
1531};1533};
1532#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)1534#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1)
1533 1535
1536enum nft_osf_flags {
1537 NFT_OSF_F_VERSION = (1 << 0),
1538};
1539
1534/**1540/**
1535 * enum nft_device_attributes - nf_tables device netlink attributes1541 * enum nft_device_attributes - nf_tables device netlink attributes
1536 *1542 *
net/netfilter/nfnetlink_osf.c+7−7
@@ -255,9 +255,9 @@ nf_osf_match(const struct sk_buff *skb, u_int8_t family, · 254 unmodified lines
255}255}
256EXPORT_SYMBOL_GPL(nf_osf_match);256EXPORT_SYMBOL_GPL(nf_osf_match);
257 257
258const char *nf_osf_find(const struct sk_buff *skb,258bool nf_osf_find(const struct sk_buff *skb,
259 const struct list_head *nf_osf_fingers,259 const struct list_head *nf_osf_fingers,
260 const int ttl_check)260 const int ttl_check, struct nf_osf_data *data)
261{261{
262 const struct iphdr *ip = ip_hdr(skb);262 const struct iphdr *ip = ip_hdr(skb);
263 const struct nf_osf_user_finger *f;263 const struct nf_osf_user_finger *f;
@@ -265,24 +265,24 @@ const char *nf_osf_find(const struct sk_buff *skb, · 1 unmodified line
265 const struct nf_osf_finger *kf;265 const struct nf_osf_finger *kf;
266 struct nf_osf_hdr_ctx ctx;266 struct nf_osf_hdr_ctx ctx;
267 const struct tcphdr *tcp;267 const struct tcphdr *tcp;
268 const char *genre = NULL;
269 268
270 memset(&ctx, 0, sizeof(ctx));269 memset(&ctx, 0, sizeof(ctx));
271 270
272 tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts);271 tcp = nf_osf_hdr_ctx_init(&ctx, skb, ip, opts);
273 if (!tcp)272 if (!tcp)
274 return NULL;273 return false;
275 274
276 list_for_each_entry_rcu(kf, &nf_osf_fingers[ctx.df], finger_entry) {275 list_for_each_entry_rcu(kf, &nf_osf_fingers[ctx.df], finger_entry) {
277 f = &kf->finger;276 f = &kf->finger;
278 if (!nf_osf_match_one(skb, f, ttl_check, &ctx))277 if (!nf_osf_match_one(skb, f, ttl_check, &ctx))
279 continue;278 continue;
280 279
281 genre = f->genre;280 data->genre = f->genre;
281 data->version = f->version;
282 break;282 break;
283 }283 }
284 284
285 return genre;285 return true;
286}286}
287EXPORT_SYMBOL_GPL(nf_osf_find);287EXPORT_SYMBOL_GPL(nf_osf_find);
288 288
net/netfilter/nft_osf.c+25−5
@@ -7,11 +7,13 @@ · 6 unmodified lines
7struct nft_osf {7struct nft_osf {
8 enum nft_registers dreg:8;8 enum nft_registers dreg:8;
9 u8 ttl;9 u8 ttl;
10 u32 flags;
10};11};
11 12
12static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = {13static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = {
13 [NFTA_OSF_DREG] = { .type = NLA_U32 },14 [NFTA_OSF_DREG] = { .type = NLA_U32 },
14 [NFTA_OSF_TTL] = { .type = NLA_U8 },15 [NFTA_OSF_TTL] = { .type = NLA_U8 },
16 [NFTA_OSF_FLAGS] = { .type = NLA_U32 },
15};17};
16 18
17static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,19static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs,
@@ -20,9 +22,10 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs, · 2 unmodified lines
20 struct nft_osf *priv = nft_expr_priv(expr);22 struct nft_osf *priv = nft_expr_priv(expr);
21 u32 *dest = &regs->data[priv->dreg];23 u32 *dest = &regs->data[priv->dreg];
22 struct sk_buff *skb = pkt->skb;24 struct sk_buff *skb = pkt->skb;
25 char os_match[NFT_OSF_MAXGENRELEN + 1];
23 const struct tcphdr *tcp;26 const struct tcphdr *tcp;
27 struct nf_osf_data data;
24 struct tcphdr _tcph;28 struct tcphdr _tcph;
25 const char *os_name;
26 29
27 tcp = skb_header_pointer(skb, ip_hdrlen(skb),30 tcp = skb_header_pointer(skb, ip_hdrlen(skb),
28 sizeof(struct tcphdr), &_tcph);31 sizeof(struct tcphdr), &_tcph);
@@ -35,11 +38,17 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs, · 6 unmodified lines
35 return;38 return;
36 }39 }
37 40
38 os_name = nf_osf_find(skb, nf_osf_fingers, priv->ttl);41 if (!nf_osf_find(skb, nf_osf_fingers, priv->ttl, &data)) {
39 if (!os_name)
40 strncpy((char *)dest, "unknown", NFT_OSF_MAXGENRELEN);42 strncpy((char *)dest, "unknown", NFT_OSF_MAXGENRELEN);
41 else43 } else {
42 strncpy((char *)dest, os_name, NFT_OSF_MAXGENRELEN);44 if (priv->flags & NFT_OSF_F_VERSION)
45 snprintf(os_match, NFT_OSF_MAXGENRELEN, "%s:%s",
46 data.genre, data.version);
47 else
48 strlcpy(os_match, data.genre, NFT_OSF_MAXGENRELEN);
49
50 strncpy((char *)dest, os_match, NFT_OSF_MAXGENRELEN);
51 }
43}52}
44 53
45static int nft_osf_init(const struct nft_ctx *ctx,54static int nft_osf_init(const struct nft_ctx *ctx,
@@ -47,6 +56,7 @@ static int nft_osf_init(const struct nft_ctx *ctx, · 1 unmodified line
47 const struct nlattr * const tb[])56 const struct nlattr * const tb[])
48{57{
49 struct nft_osf *priv = nft_expr_priv(expr);58 struct nft_osf *priv = nft_expr_priv(expr);
59 u32 flags;
50 int err;60 int err;
51 u8 ttl;61 u8 ttl;
52 62
@@ -57,6 +67,13 @@ static int nft_osf_init(const struct nft_ctx *ctx, · 4 unmodified lines
57 priv->ttl = ttl;67 priv->ttl = ttl;
58 }68 }
59 69
70 if (tb[NFTA_OSF_FLAGS]) {
71 flags = ntohl(nla_get_be32(tb[NFTA_OSF_FLAGS]));
72 if (flags != NFT_OSF_F_VERSION)
73 return -EINVAL;
74 priv->flags = flags;
75 }
76
60 priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]);77 priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]);
61 err = nft_validate_register_store(ctx, priv->dreg, NULL,78 err = nft_validate_register_store(ctx, priv->dreg, NULL,
62 NFT_DATA_VALUE, NFT_OSF_MAXGENRELEN);79 NFT_DATA_VALUE, NFT_OSF_MAXGENRELEN);
@@ -73,6 +90,9 @@ static int nft_osf_dump(struct sk_buff *skb, const struct nft_expr *expr) · 10 unmodified lines
73 if (nla_put_u8(skb, NFTA_OSF_TTL, priv->ttl))90 if (nla_put_u8(skb, NFTA_OSF_TTL, priv->ttl))
74 goto nla_put_failure;91 goto nla_put_failure;
75 92
93 if (nla_put_be32(skb, NFTA_OSF_FLAGS, ntohl(priv->flags)))
94 goto nla_put_failure;
95
76 if (nft_dump_register(skb, NFTA_OSF_DREG, priv->dreg))96 if (nft_dump_register(skb, NFTA_OSF_DREG, priv->dreg))
77 goto nla_put_failure;97 goto nla_put_failure;
78 98