2424#include <net/netfilter/nf_conntrack_labels.h>
2525#include <net/netfilter/nf_conntrack_timeout.h>
2626#include <net/netfilter/nf_conntrack_l4proto.h>
27+ #include <net/netfilter/nf_conntrack_expect.h>
2728
2829struct nft_ct {
2930 enum nft_ct_keys key :8 ;
@@ -1156,6 +1157,131 @@ static struct nft_object_type nft_ct_helper_obj_type __read_mostly = {
11561157 .owner = THIS_MODULE ,
11571158};
11581159
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+
11591285static int __init nft_ct_module_init (void )
11601286{
11611287 int err ;
@@ -1173,17 +1299,23 @@ static int __init nft_ct_module_init(void)
11731299 err = nft_register_obj (& nft_ct_helper_obj_type );
11741300 if (err < 0 )
11751301 goto err2 ;
1302+
1303+ err = nft_register_obj (& nft_ct_expect_obj_type );
1304+ if (err < 0 )
1305+ goto err3 ;
11761306#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
11771307 err = nft_register_obj (& nft_ct_timeout_obj_type );
11781308 if (err < 0 )
1179- goto err3 ;
1309+ goto err4 ;
11801310#endif
11811311 return 0 ;
11821312
11831313#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1314+ err4 :
1315+ nft_unregister_obj (& nft_ct_expect_obj_type );
1316+ #endif
11841317err3 :
11851318 nft_unregister_obj (& nft_ct_helper_obj_type );
1186- #endif
11871319err2 :
11881320 nft_unregister_expr (& nft_notrack_type );
11891321err1 :
@@ -1196,6 +1328,7 @@ static void __exit nft_ct_module_exit(void)
11961328#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
11971329 nft_unregister_obj (& nft_ct_timeout_obj_type );
11981330#endif
1331+ nft_unregister_obj (& nft_ct_expect_obj_type );
11991332 nft_unregister_obj (& nft_ct_helper_obj_type );
12001333 nft_unregister_expr (& nft_notrack_type );
12011334 nft_unregister_expr (& nft_ct_type );
@@ -1210,3 +1343,4 @@ MODULE_ALIAS_NFT_EXPR("ct");
12101343MODULE_ALIAS_NFT_EXPR ("notrack" );
12111344MODULE_ALIAS_NFT_OBJ (NFT_OBJECT_CT_HELPER );
12121345MODULE_ALIAS_NFT_OBJ (NFT_OBJECT_CT_TIMEOUT );
1346+ MODULE_ALIAS_NFT_OBJ (NFT_OBJECT_CT_EXPECT );
0 commit comments