网络子系统10_inet模块初始化

本文详细介绍了Linux内核中inet模块的初始化过程,包括sock_register()在socket层注册inet地址族,inet_protosw结构体在l4层表示协议操作,net_protocol结构体在l3层作为协议回调函数,以及inet_add_protocol()用于注册协议处理函数。inet_init()函数中,初始化了如TCP、UDP、ICMP等协议,并设置了相应的协议栈缓存。同时,还涉及了arp、ip、tcp、icmp子系统的初始化。
摘要由CSDN通过智能技术生成
//inet模块初始化
//inet功能以模块的形式提供
//1.sock_register(inet_family_ops)向socket注册地址族,保存在net_families数组中,socket通过地址族查找对应的inet_family_ops
//2.struct inet_protosw 由l4使用,表示地址族(协议族)中某一具体协议的操作,保存在inetsw链表数组中,通过协议类型查找对应的协议操作
//3.struct net_protocol 由l3使用,表示l4协议的回调函数,l3通过l3报头中的协议字段,在inet_protos数组中查找对应l4回调函数。
static int __init inet_init(void)
{
	struct sk_buff *dummy_skb;
	struct inet_protosw *q;
	struct list_head *r;
	int rc = -EINVAL;
	//如果inet控制块的大小 > skb提供的控制块的大小
	if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
		printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
		goto out;
	}
	//tcp sock SLAB 缓存
	rc = sk_alloc_slab(&tcp_prot, "tcp_sock");
	if (rc) {
		sk_alloc_slab_error(&tcp_prot);
		goto out;
	}
	//udp sock SLAB 缓存
	rc = sk_alloc_slab(&udp_prot, "udp_sock");
	if (rc) {
		sk_alloc_slab_error(&udp_prot);
		goto out_tcp_free_slab;
	}
	//raw sock SLBA缓存
	rc = sk_alloc_slab(&raw_prot, "raw_sock");
	if (rc) {
		sk_alloc_slab_error(&raw_prot);
		goto out_udp_free_slab;
	}

	//向sock注册af_inet服务
  	(void)sock_register(&inet_family_ops);

  	//注册l4协议,l3接收到数据包时,通过协议字段,找到对应的上层协议的回调函数
  	//xxx_protocol用于向下提供服务
	if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)//icmp
		printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n");
	if (inet_add_prot
在某些系统编程环境中,你可能会遇到不支持 `RES_USE_INET6` 宏的问题。这个宏通常用于指定在DNS解析时,如果存在IPv4和IPv6地址,优先使用IPv6地址。为了解决这个问题,你可以采取以下步骤: 1. 确认你的系统和编译器是否支持IPv6。在一些老旧的系统或编译器中,可能没有对IPv6的支持。 2. 如果你的系统支持IPv6,但是当前的库或工具链不支持 `RES_USE_INET6` 宏,你可能需要更新你的系统库或者编译器到支持IPv6的版本。 3. 如果无法更新库或编译器,你可以在代码中进行条件编译检查,使用 `#ifdef` 等预处理指令来判断宏是否定义,然后采取相应的措施。例如: ```c #ifdef RES_USE_INET6 // 如果支持RES_USE_INET6,使用它 int res = res_init(); if (res == 0) { res.options |= RES_USE_INET6; res_init(); } #else // 如果不支持RES_USE_INET6,可以尝试其他方式 // 比如直接在getaddrinfo调用时指定AI_V4MAPPED | AI_ALL标志来请求IPv6地址 #endif ``` 4. 使用 `getaddrinfo` 函数代替老式的 DNS 解析函数。`getaddrinfo` 支持 IPv6,并且更加灵活。你可以指定 `AI_V4MAPPED` 标志来允许IPv4映射到IPv6地址,`AI_ALL` 标志来尝试解析IPv4和IPv6地址。 ```c struct addrinfo hints; struct addrinfo *res; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; // AF_INET 或 AF_INET6 hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_V4MAPPED | AI_ALL; int status = getaddrinfo("example.com", "http", &hints, &res); ``` 5. 如果你的应用程序依赖于 `res_init` 和 `res_query` 等函数,你可能需要寻找替代方案或者实现一套兼容代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值