24
24
#include <net/netfilter/nf_conntrack_labels.h>
25
25
#include <net/netfilter/nf_conntrack_timeout.h>
26
26
#include <net/netfilter/nf_conntrack_l4proto.h>
27
+ #include <net/netfilter/nf_conntrack_expect.h>
27
28
28
29
struct nft_ct {
29
30
enum nft_ct_keys key :8 ;
@@ -1156,6 +1157,131 @@ static struct nft_object_type nft_ct_helper_obj_type __read_mostly = {
1156
1157
.owner = THIS_MODULE ,
1157
1158
};
1158
1159
1160
+ struct nft_ct_expect_obj {
1161
+ u16 l3num ;
1162
+ __be16 dport ;
1163
+ u8 l4proto ;
1164
+ u8 size ;
1165
+ u32 timeout ;
1166
+ };
1167
+
1168
+ static int nft_ct_expect_obj_init (const struct nft_ctx * ctx ,
1169
+ const struct nlattr * const tb [],
1170
+ struct nft_object * obj )
1171
+ {
1172
+ struct nft_ct_expect_obj * priv = nft_obj_data (obj );
1173
+
1174
+ if (!tb [NFTA_CT_EXPECT_L4PROTO ] ||
1175
+ !tb [NFTA_CT_EXPECT_DPORT ] ||
1176
+ !tb [NFTA_CT_EXPECT_TIMEOUT ] ||
1177
+ !tb [NFTA_CT_EXPECT_SIZE ])
1178
+ return - EINVAL ;
1179
+
1180
+ priv -> l3num = ctx -> family ;
1181
+ if (tb [NFTA_CT_EXPECT_L3PROTO ])
1182
+ priv -> l3num = ntohs (nla_get_be16 (tb [NFTA_CT_EXPECT_L3PROTO ]));
1183
+
1184
+ priv -> l4proto = nla_get_u8 (tb [NFTA_CT_EXPECT_L4PROTO ]);
1185
+ priv -> dport = nla_get_be16 (tb [NFTA_CT_EXPECT_DPORT ]);
1186
+ priv -> timeout = nla_get_u32 (tb [NFTA_CT_EXPECT_TIMEOUT ]);
1187
+ priv -> size = nla_get_u8 (tb [NFTA_CT_EXPECT_SIZE ]);
1188
+
1189
+ return nf_ct_netns_get (ctx -> net , ctx -> family );
1190
+ }
1191
+
1192
+ static void nft_ct_expect_obj_destroy (const struct nft_ctx * ctx ,
1193
+ struct nft_object * obj )
1194
+ {
1195
+ nf_ct_netns_put (ctx -> net , ctx -> family );
1196
+ }
1197
+
1198
+ static int nft_ct_expect_obj_dump (struct sk_buff * skb ,
1199
+ struct nft_object * obj , bool reset )
1200
+ {
1201
+ const struct nft_ct_expect_obj * priv = nft_obj_data (obj );
1202
+
1203
+ if (nla_put_be16 (skb , NFTA_CT_EXPECT_L3PROTO , htons (priv -> l3num )) ||
1204
+ nla_put_u8 (skb , NFTA_CT_EXPECT_L4PROTO , priv -> l4proto ) ||
1205
+ nla_put_be16 (skb , NFTA_CT_EXPECT_DPORT , priv -> dport ) ||
1206
+ nla_put_u32 (skb , NFTA_CT_EXPECT_TIMEOUT , priv -> timeout ) ||
1207
+ nla_put_u8 (skb , NFTA_CT_EXPECT_SIZE , priv -> size ))
1208
+ return -1 ;
1209
+
1210
+ return 0 ;
1211
+ }
1212
+
1213
+ static void nft_ct_expect_obj_eval (struct nft_object * obj ,
1214
+ struct nft_regs * regs ,
1215
+ const struct nft_pktinfo * pkt )
1216
+ {
1217
+ const struct nft_ct_expect_obj * priv = nft_obj_data (obj );
1218
+ struct nf_conntrack_expect * exp ;
1219
+ enum ip_conntrack_info ctinfo ;
1220
+ struct nf_conn_help * help ;
1221
+ enum ip_conntrack_dir dir ;
1222
+ u16 l3num = priv -> l3num ;
1223
+ struct nf_conn * ct ;
1224
+
1225
+ ct = nf_ct_get (pkt -> skb , & ctinfo );
1226
+ if (!ct || ctinfo == IP_CT_UNTRACKED ) {
1227
+ regs -> verdict .code = NFT_BREAK ;
1228
+ return ;
1229
+ }
1230
+ dir = CTINFO2DIR (ctinfo );
1231
+
1232
+ help = nfct_help (ct );
1233
+ if (!help )
1234
+ help = nf_ct_helper_ext_add (ct , GFP_ATOMIC );
1235
+
1236
+ if (help -> expecting [NF_CT_EXPECT_CLASS_DEFAULT ] >= priv -> size ) {
1237
+ regs -> verdict .code = NFT_BREAK ;
1238
+ return ;
1239
+ }
1240
+ if (l3num == NFPROTO_INET )
1241
+ l3num = nf_ct_l3num (ct );
1242
+
1243
+ exp = nf_ct_expect_alloc (ct );
1244
+ if (exp == NULL ) {
1245
+ regs -> verdict .code = NF_DROP ;
1246
+ return ;
1247
+ }
1248
+ nf_ct_expect_init (exp , NF_CT_EXPECT_CLASS_DEFAULT , l3num ,
1249
+ & ct -> tuplehash [!dir ].tuple .src .u3 ,
1250
+ & ct -> tuplehash [!dir ].tuple .dst .u3 ,
1251
+ priv -> l4proto , NULL , & priv -> dport );
1252
+ exp -> timeout .expires = jiffies + priv -> timeout * HZ ;
1253
+
1254
+ if (nf_ct_expect_related (exp ) != 0 )
1255
+ regs -> verdict .code = NF_DROP ;
1256
+ }
1257
+
1258
+ static const struct nla_policy nft_ct_expect_policy [NFTA_CT_EXPECT_MAX + 1 ] = {
1259
+ [NFTA_CT_EXPECT_L3PROTO ] = { .type = NLA_U16 },
1260
+ [NFTA_CT_EXPECT_L4PROTO ] = { .type = NLA_U8 },
1261
+ [NFTA_CT_EXPECT_DPORT ] = { .type = NLA_U16 },
1262
+ [NFTA_CT_EXPECT_TIMEOUT ] = { .type = NLA_U32 },
1263
+ [NFTA_CT_EXPECT_SIZE ] = { .type = NLA_U8 },
1264
+ };
1265
+
1266
+ static struct nft_object_type nft_ct_expect_obj_type ;
1267
+
1268
+ static const struct nft_object_ops nft_ct_expect_obj_ops = {
1269
+ .type = & nft_ct_expect_obj_type ,
1270
+ .size = sizeof (struct nft_ct_expect_obj ),
1271
+ .eval = nft_ct_expect_obj_eval ,
1272
+ .init = nft_ct_expect_obj_init ,
1273
+ .destroy = nft_ct_expect_obj_destroy ,
1274
+ .dump = nft_ct_expect_obj_dump ,
1275
+ };
1276
+
1277
+ static struct nft_object_type nft_ct_expect_obj_type __read_mostly = {
1278
+ .type = NFT_OBJECT_CT_EXPECT ,
1279
+ .ops = & nft_ct_expect_obj_ops ,
1280
+ .maxattr = NFTA_CT_EXPECT_MAX ,
1281
+ .policy = nft_ct_expect_policy ,
1282
+ .owner = THIS_MODULE ,
1283
+ };
1284
+
1159
1285
static int __init nft_ct_module_init (void )
1160
1286
{
1161
1287
int err ;
@@ -1173,17 +1299,23 @@ static int __init nft_ct_module_init(void)
1173
1299
err = nft_register_obj (& nft_ct_helper_obj_type );
1174
1300
if (err < 0 )
1175
1301
goto err2 ;
1302
+
1303
+ err = nft_register_obj (& nft_ct_expect_obj_type );
1304
+ if (err < 0 )
1305
+ goto err3 ;
1176
1306
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1177
1307
err = nft_register_obj (& nft_ct_timeout_obj_type );
1178
1308
if (err < 0 )
1179
- goto err3 ;
1309
+ goto err4 ;
1180
1310
#endif
1181
1311
return 0 ;
1182
1312
1183
1313
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1314
+ err4 :
1315
+ nft_unregister_obj (& nft_ct_expect_obj_type );
1316
+ #endif
1184
1317
err3 :
1185
1318
nft_unregister_obj (& nft_ct_helper_obj_type );
1186
- #endif
1187
1319
err2 :
1188
1320
nft_unregister_expr (& nft_notrack_type );
1189
1321
err1 :
@@ -1196,6 +1328,7 @@ static void __exit nft_ct_module_exit(void)
1196
1328
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1197
1329
nft_unregister_obj (& nft_ct_timeout_obj_type );
1198
1330
#endif
1331
+ nft_unregister_obj (& nft_ct_expect_obj_type );
1199
1332
nft_unregister_obj (& nft_ct_helper_obj_type );
1200
1333
nft_unregister_expr (& nft_notrack_type );
1201
1334
nft_unregister_expr (& nft_ct_type );
@@ -1210,3 +1343,4 @@ MODULE_ALIAS_NFT_EXPR("ct");
1210
1343
MODULE_ALIAS_NFT_EXPR ("notrack" );
1211
1344
MODULE_ALIAS_NFT_OBJ (NFT_OBJECT_CT_HELPER );
1212
1345
MODULE_ALIAS_NFT_OBJ (NFT_OBJECT_CT_TIMEOUT );
1346
+ MODULE_ALIAS_NFT_OBJ (NFT_OBJECT_CT_EXPECT );
0 commit comments