1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/module.h>
3 #include <linux/netfilter/nf_tables.h>
4 #include <net/netfilter/nf_tables.h>
5 #include <net/netfilter/nf_tables_core.h>
6 #include <net/netfilter/nf_socket.h>
7 #include <net/inet_sock.h>
11 enum nft_socket_keys key
:8;
13 enum nft_registers dreg
:8;
17 static void nft_socket_eval(const struct nft_expr
*expr
,
18 struct nft_regs
*regs
,
19 const struct nft_pktinfo
*pkt
)
21 const struct nft_socket
*priv
= nft_expr_priv(expr
);
22 struct sk_buff
*skb
= pkt
->skb
;
23 struct sock
*sk
= skb
->sk
;
24 u32
*dest
= ®s
->data
[priv
->dreg
];
26 if (sk
&& !net_eq(nft_net(pkt
), sock_net(sk
)))
32 sk
= nf_sk_lookup_slow_v4(nft_net(pkt
), skb
, nft_in(pkt
));
34 #if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
36 sk
= nf_sk_lookup_slow_v6(nft_net(pkt
), skb
, nft_in(pkt
));
41 regs
->verdict
.code
= NFT_BREAK
;
46 regs
->verdict
.code
= NFT_BREAK
;
51 case NFT_SOCKET_TRANSPARENT
:
52 nft_reg_store8(dest
, inet_sk_transparent(sk
));
55 if (sk_fullsock(sk
)) {
58 regs
->verdict
.code
= NFT_BREAK
;
64 regs
->verdict
.code
= NFT_BREAK
;
71 static const struct nla_policy nft_socket_policy
[NFTA_SOCKET_MAX
+ 1] = {
72 [NFTA_SOCKET_KEY
] = { .type
= NLA_U32
},
73 [NFTA_SOCKET_DREG
] = { .type
= NLA_U32
},
76 static int nft_socket_init(const struct nft_ctx
*ctx
,
77 const struct nft_expr
*expr
,
78 const struct nlattr
* const tb
[])
80 struct nft_socket
*priv
= nft_expr_priv(expr
);
83 if (!tb
[NFTA_SOCKET_DREG
] || !tb
[NFTA_SOCKET_KEY
])
88 #if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
97 priv
->key
= ntohl(nla_get_u32(tb
[NFTA_SOCKET_KEY
]));
99 case NFT_SOCKET_TRANSPARENT
:
102 case NFT_SOCKET_MARK
:
109 priv
->dreg
= nft_parse_register(tb
[NFTA_SOCKET_DREG
]);
110 return nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
111 NFT_DATA_VALUE
, len
);
114 static int nft_socket_dump(struct sk_buff
*skb
,
115 const struct nft_expr
*expr
)
117 const struct nft_socket
*priv
= nft_expr_priv(expr
);
119 if (nla_put_u32(skb
, NFTA_SOCKET_KEY
, htonl(priv
->key
)))
121 if (nft_dump_register(skb
, NFTA_SOCKET_DREG
, priv
->dreg
))
126 static struct nft_expr_type nft_socket_type
;
127 static const struct nft_expr_ops nft_socket_ops
= {
128 .type
= &nft_socket_type
,
129 .size
= NFT_EXPR_SIZE(sizeof(struct nft_socket
)),
130 .eval
= nft_socket_eval
,
131 .init
= nft_socket_init
,
132 .dump
= nft_socket_dump
,
135 static struct nft_expr_type nft_socket_type __read_mostly
= {
137 .ops
= &nft_socket_ops
,
138 .policy
= nft_socket_policy
,
139 .maxattr
= NFTA_SOCKET_MAX
,
140 .owner
= THIS_MODULE
,
143 static int __init
nft_socket_module_init(void)
145 return nft_register_expr(&nft_socket_type
);
148 static void __exit
nft_socket_module_exit(void)
150 nft_unregister_expr(&nft_socket_type
);
153 module_init(nft_socket_module_init
);
154 module_exit(nft_socket_module_exit
);
156 MODULE_LICENSE("GPL");
157 MODULE_AUTHOR("Máté Eckl");
158 MODULE_DESCRIPTION("nf_tables socket match module");
159 MODULE_ALIAS_NFT_EXPR("socket");