1 // SPDX-License-Identifier: GPL-2.0-only
5 #include <net/netfilter/nf_tables.h>
6 #include <linux/netfilter/nfnetlink_osf.h>
9 enum nft_registers dreg
:8;
14 static const struct nla_policy nft_osf_policy
[NFTA_OSF_MAX
+ 1] = {
15 [NFTA_OSF_DREG
] = { .type
= NLA_U32
},
16 [NFTA_OSF_TTL
] = { .type
= NLA_U8
},
17 [NFTA_OSF_FLAGS
] = { .type
= NLA_U32
},
20 static void nft_osf_eval(const struct nft_expr
*expr
, struct nft_regs
*regs
,
21 const struct nft_pktinfo
*pkt
)
23 struct nft_osf
*priv
= nft_expr_priv(expr
);
24 u32
*dest
= ®s
->data
[priv
->dreg
];
25 struct sk_buff
*skb
= pkt
->skb
;
26 char os_match
[NFT_OSF_MAXGENRELEN
+ 1];
27 const struct tcphdr
*tcp
;
28 struct nf_osf_data data
;
31 tcp
= skb_header_pointer(skb
, ip_hdrlen(skb
),
32 sizeof(struct tcphdr
), &_tcph
);
34 regs
->verdict
.code
= NFT_BREAK
;
38 regs
->verdict
.code
= NFT_BREAK
;
42 if (!nf_osf_find(skb
, nf_osf_fingers
, priv
->ttl
, &data
)) {
43 strncpy((char *)dest
, "unknown", NFT_OSF_MAXGENRELEN
);
45 if (priv
->flags
& NFT_OSF_F_VERSION
)
46 snprintf(os_match
, NFT_OSF_MAXGENRELEN
, "%s:%s",
47 data
.genre
, data
.version
);
49 strlcpy(os_match
, data
.genre
, NFT_OSF_MAXGENRELEN
);
51 strncpy((char *)dest
, os_match
, NFT_OSF_MAXGENRELEN
);
55 static int nft_osf_init(const struct nft_ctx
*ctx
,
56 const struct nft_expr
*expr
,
57 const struct nlattr
* const tb
[])
59 struct nft_osf
*priv
= nft_expr_priv(expr
);
64 if (tb
[NFTA_OSF_TTL
]) {
65 ttl
= nla_get_u8(tb
[NFTA_OSF_TTL
]);
71 if (tb
[NFTA_OSF_FLAGS
]) {
72 flags
= ntohl(nla_get_be32(tb
[NFTA_OSF_FLAGS
]));
73 if (flags
!= NFT_OSF_F_VERSION
)
78 priv
->dreg
= nft_parse_register(tb
[NFTA_OSF_DREG
]);
79 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
80 NFT_DATA_VALUE
, NFT_OSF_MAXGENRELEN
);
87 static int nft_osf_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
89 const struct nft_osf
*priv
= nft_expr_priv(expr
);
91 if (nla_put_u8(skb
, NFTA_OSF_TTL
, priv
->ttl
))
94 if (nla_put_be32(skb
, NFTA_OSF_FLAGS
, ntohl(priv
->flags
)))
97 if (nft_dump_register(skb
, NFTA_OSF_DREG
, priv
->dreg
))
106 static int nft_osf_validate(const struct nft_ctx
*ctx
,
107 const struct nft_expr
*expr
,
108 const struct nft_data
**data
)
110 return nft_chain_validate_hooks(ctx
->chain
, (1 << NF_INET_LOCAL_IN
) |
111 (1 << NF_INET_PRE_ROUTING
) |
112 (1 << NF_INET_FORWARD
));
115 static struct nft_expr_type nft_osf_type
;
116 static const struct nft_expr_ops nft_osf_op
= {
117 .eval
= nft_osf_eval
,
118 .size
= NFT_EXPR_SIZE(sizeof(struct nft_osf
)),
119 .init
= nft_osf_init
,
120 .dump
= nft_osf_dump
,
121 .type
= &nft_osf_type
,
122 .validate
= nft_osf_validate
,
125 static struct nft_expr_type nft_osf_type __read_mostly
= {
128 .owner
= THIS_MODULE
,
129 .policy
= nft_osf_policy
,
130 .maxattr
= NFTA_OSF_MAX
,
133 static int __init
nft_osf_module_init(void)
135 return nft_register_expr(&nft_osf_type
);
138 static void __exit
nft_osf_module_exit(void)
140 return nft_unregister_expr(&nft_osf_type
);
143 module_init(nft_osf_module_init
);
144 module_exit(nft_osf_module_exit
);
146 MODULE_LICENSE("GPL");
147 MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>");
148 MODULE_ALIAS_NFT_EXPR("osf");