Linux内核网络协议栈6-socket地址绑定(续)
接上篇《socket地址绑定》
?
?
三、根据不同的协议来完成绑定
上面代码中的第3步是根据应用程序在创建socket时传递到内核的协议域及socket类型来决定调用采用哪个方法,具体可以参考
创建socket
上面代码中的第3步是根据应用程序在创建socket时传递到内核的协议域及socket类型来决定调用采用哪个方法,具体可以参考
创建socket
一文,这里不再赘述;下面以AF_IENT及SOCK_STREAM为例来说明绑定的过程;
1、调用链:
net/Socket.c:sys_bind()->net/ipv4/Af_inet.c:inet_bind();
2
、inet_bind()逻辑:
1) 地址类型检查
chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); if (!sysctl_ip_nonlocal_bind && !inet->freebind && addr->sin_addr.s_addr != htonl(INADDR_ANY) && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) goto out;
?
inet_addr_type()函数根据设置的ip地址检查其类型:
static inline unsigned __inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr) { …… if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr)) return RTN_BROADCAST; if (ipv4_is_multicast(addr)) return RTN_MULTICAST; …… local_table = fib_get_table(net, RT_TABLE_LOCAL); if (local_table) { ret = RTN_UNICAST; if (!local_table->tb_lookup(local_table, &fl, &res)) { if (!dev || dev == res.fi->fib_dev) ret = res.type; fib_res_put(&res); } } return ret; }
?
其中:</