前些天开始看netfilter的连接跟踪模块,看了2.4内核后再看2.6内核,发现差别很大,到现在为止还没有弄明白,一点点总结,今天先把这两天理解的东西写出来。我是在Hereltls兄大作指点下对2.6的conntrack进行学习的。参考文章为:http://blog.chinaunix.net/u3/110948/showart_2166654.html
本文内容基于内核2.6.33.2
作者:bbo
conntrack的初始化过程如下,先从nf_conntrack_standalone_init()开始入手
static int __init nf_conntrack_standalone_init(void)
{
return register_pernet_subsys(&nf_conntrack_net_ops);
}
nf_conntrack_net_ops的定义为:
static struct pernet_operations nf_conntrack_net_ops = {
.init = nf_conntrack_net_init, /* 其调用了nf_conntrack_init接口 ,对于每一个 net都要调用这个接口的*/
.exit = nf_conntrack_net_exit,
};
nf_conntrack_init接口的实现如下,
466 static int nf_conntrack_net_init(struct net *net)
467 {
468 int ret;
469
470 ret = nf_conntrack_init(net);//调用了nf_conntrack_init_net()函数,完成对连接跟踪的一些参数的初始化
471 if (ret < 0)
472 goto out_init;
473 ret = nf_conntrack_standalone_init_proc(net);//暂时不清楚这函数和下一个函数的具体作用
474 if (ret < 0)
475 goto out_proc;
476 net->ct.sysctl_checksum = 1;
477 net->ct.sysctl_log_invalid = 0;
478 ret = nf_conntrack_standalone_init_sysctl(net);
479 if (ret < 0)
480 goto out_sysctl;
481 return 0;
482
483 out_sysctl:
484 nf_conntrack_standalone_fini_proc(net);
485 out_proc:
486 nf_conntrack_cleanup(net);
487 out_init:
488 return ret;
489 }
进入nf_conntrack_init函数,函数如下:
1375 int nf_conntrack_init(struct net *net)
1376 {
1377 int ret;
1378
1379 if (net_eq(net, &init_net)) {
1380 ret = nf_conntrack_init_init_net();//初始化hashtable_size , nf_conntrack_max, proto_init(), helper_init()
1381 if (ret < 0)
1382 goto out_init_net;
1383 }
1384 ret = nf_conntrack_init_net(net);
1385 if (ret < 0)
1386 goto out_net;
1387
1388 if (net_eq(net, &init_net)) {
1389 /* For use by REJECT target */
1390 rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);//暂时不清楚其作用
1391 rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
1392
1393 /* Howto get NAT offsets */
1394 rcu_assign_pointer(nf_ct_nat_offset, NULL);
1395 }
1396 return 0;
1397
1398 out_net:
1399 if (net_eq(net, &init_net))
1400 nf_conntrack_cleanup_init_net();
1401 out_init_net:
1402 return ret;
1403 }
static int nf_conntrack_init_init_net(void)
1248 {
1249 int max_factor = 8;
1250 int ret;
1251
1252 //初始化hatables_size,不过本人暂时还没有来得及分析该算法
1254 if (!nf_conntrack_htable_size) {
1255 nf_conntrack_htable_size
1256 = (((totalram_pages << PAGE_SHIFT) / 16384)
1257 / sizeof(struct hlist_head));
1258 if (totalram_pages > (1024 * 1024 * 1024 / PAGE_SIZE))
1259 nf_conntrack_htable_size = 16384;
1260 if (nf_conntrack_htable_size < 32)
1261 nf_conntrack_htable_size = 32;
1262
//默认情况下将max_factor设为4,但当用户给出htable_size的值时则用旧版本中的值8
1267 max_factor = 4;
1268 }
1269 nf_conntrack_max = max_factor * nf_conntrack_htable_size;
1275 ret = nf_conntrack_proto_init();//初始化proto
1278
1279 ret = nf_conntrack_helper_init();//初始化helper
1282
1287 atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
1288 /* - and look it like as a confirmed connection */
1289 set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);
1290
1291 return 0;
1292
1293 err_helper:
1294 nf_conntrack_proto_fini();
1295 err_proto:
1296 return ret;
1297 }
1305 static int nf_conntrack_init_net(struct net *net)
1306 {
1307 int ret;
1308
1309 atomic_set(&net->ct.count, 0);
1310 INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, UNCONFIRMED_NULLS_VAL);
1311 INIT_HLIST_NULLS_HEAD(&net->ct.dying, DYING_NULLS_VAL);
1312 net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
1317
1324 net->ct.nf_conntrack_cachep = kmem_cache_create(net->ct.slabname,
1325 sizeof(struct nf_conn), 0,
1326 SLAB_DESTROY_BY_RCU, NULL);
1332
1333 net->ct.htable_size = nf_conntrack_htable_size;
1334 net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size,
1335 &net->ct.hash_vmalloc, 1);
1341 ret = nf_conntrack_expect_init(net);//初始化expect链表
1344 ret = nf_conntrack_acct_init(net);//初始化acct扩展模块
1347 ret = nf_conntrack_ecache_init(net);
1350
1351 return 0;
1352
1353 err_ecache:
1354 nf_conntrack_acct_fini(net);
1355 err_acct:
1356 nf_conntrack_expect_fini(net);
1357 err_expect:
1358 nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
1359 net->ct.htable_size);
1360 err_hash:
1361 kmem_cache_destroy(net->ct.nf_conntrack_cachep);
1362 err_cache:
1363 kfree(net->ct.slabname);
1364 err_slabname:
1365 free_percpu(net->ct.stat);
1366 err_stat:
1367 return ret;
1368 }
这是第一次正点的写东西,虽然这次基本没有自己的内容。这次只是对初始化的框架进行了总结,并未对具体内容做太多分析,主要是由于鄙人刚开始学,能力暂时有限,望谅解,我会对其进行慢慢改正和补充。给自己打打气,争取早日把netfilter/iptables拿下!加油!
阅读(1714) | 评论(0) | 转发(0) |