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_DREG
])
67 if (tb
[NFTA_OSF_TTL
]) {
68 ttl
= nla_get_u8(tb
[NFTA_OSF_TTL
]);
74 if (tb
[NFTA_OSF_FLAGS
]) {
75 flags
= ntohl(nla_get_be32(tb
[NFTA_OSF_FLAGS
]));
76 if (flags
!= NFT_OSF_F_VERSION
)
81 priv
->dreg
= nft_parse_register(tb
[NFTA_OSF_DREG
]);
82 err
= nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
83 NFT_DATA_VALUE
, NFT_OSF_MAXGENRELEN
);
90 static int nft_osf_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
92 const struct nft_osf
*priv
= nft_expr_priv(expr
);
94 if (nla_put_u8(skb
, NFTA_OSF_TTL
, priv
->ttl
))
97 if (nla_put_be32(skb
, NFTA_OSF_FLAGS
, ntohl(priv
->flags
)))
100 if (nft_dump_register(skb
, NFTA_OSF_DREG
, priv
->dreg
))
101 goto nla_put_failure
;
109 static int nft_osf_validate(const struct nft_ctx
*ctx
,
110 const struct nft_expr
*expr
,
111 const struct nft_data
**data
)
113 return nft_chain_validate_hooks(ctx
->chain
, (1 << NF_INET_LOCAL_IN
) |
114 (1 << NF_INET_PRE_ROUTING
) |
115 (1 << NF_INET_FORWARD
));
118 static struct nft_expr_type nft_osf_type
;
119 static const struct nft_expr_ops nft_osf_op
= {
120 .eval
= nft_osf_eval
,
121 .size
= NFT_EXPR_SIZE(sizeof(struct nft_osf
)),
122 .init
= nft_osf_init
,
123 .dump
= nft_osf_dump
,
124 .type
= &nft_osf_type
,
125 .validate
= nft_osf_validate
,
128 static struct nft_expr_type nft_osf_type __read_mostly
= {
131 .owner
= THIS_MODULE
,
132 .policy
= nft_osf_policy
,
133 .maxattr
= NFTA_OSF_MAX
,
136 static int __init
nft_osf_module_init(void)
138 return nft_register_expr(&nft_osf_type
);
141 static void __exit
nft_osf_module_exit(void)
143 return nft_unregister_expr(&nft_osf_type
);
146 module_init(nft_osf_module_init
);
147 module_exit(nft_osf_module_exit
);
149 MODULE_LICENSE("GPL");
150 MODULE_AUTHOR("Fernando Fernandez <ffmancera@riseup.net>");
151 MODULE_ALIAS_NFT_EXPR("osf");