三、根据不同的协议来完成绑定  
上面代码中的第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;
}

其中:

a. ipv4_is_zeronet()用于检查地址的高8位是否为0,即地址是否为0.x.x.x,这类地址称为零网地址,零网地址也属于广播地址;

b. ipv4_is_lbcast()用于检查地址是否是广播地址(广播地址有两种,一种是有限广播,即255.255.255.255,它不会被路由但是会发送到物理网段上的所有主机;另一种是直接广播,该类地址的主机字段为255,如192.168.1.255,该广播会路由到192.168.1网段的所有主机上);这里只是检查是否是有限广播地址;

c. ipv4_is_multicast()用于检查地址是否是多播地址,即224.x.x.x的D类地址;

当ip地址既不是多播,也不是广播时,需要通过查找路由表来确定地址的类型(关于路由表,后面再叙述);  
 
拿到地址类型后,inet_bind()函数会检查地址是否是单播、多播或广播地址;否则就直接出错并返回;

2) 端口范围检查

snum = ntohs(addr->sin_port);
if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))  goto out;  /* Sockets 0-1023 can't be bound to unless you are superuser */
#define PROT_SOCK   1024   

这里检查如果端口小于1024,且具有超级用户权限,否则直接出错并返回;

3) 设置源地址和接收地址

if (sk->sk_state != TCP_CLOSE || inet->num)  goto out_release_sock;  inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)  inet->saddr = 0;  /* Use device */ 

这里先检查sock的状态,如果不是TCP_CLOSE或端口为0,则出错返回(这里也映射到创建socket时要将sock结构体变量的状态设置为TCP_CLOSE上了);  
如果地址类型是多播或广播,则源地址设置为0,而接收地址为设置的ip地址;

4) 检查端口是否被占用

if (sk->sk_prot->get_port(sk, snum)) {  inet->saddr = inet->rcv_saddr = 0;  err = -EADDRINUSE;  goto out_release_sock;
} 

这里根据创建socket协议族初始化时设置的sk_prot来判断端口是否被占用,如果被占用则直接出错返回;关于端口是否被占用,后面会有专门的一章来描述;

5) 初始化目标地址和端口

inet->sport = htons(inet->num);
inet->daddr = 0;
inet->dport = 0;  

至此,地址绑定就完成了。  
 
总结:

1、 根据文件描述符从进程描述符中取出相应的文件,再得到socket结构;

2、 检查ip地址的类型是否是单播、多播或广播;

3、 检查端口是否被占用;

Linux内核网络协议栈6-socket地址绑定(2)相关推荐

  1. Linux内核网络协议栈8—socket监听

    几个问题  了解以下几个问题的同学可以直接忽略下文: 1.listen 库函数主要做了什么?  2. 什么是最大并发连接请求数?  3.什么是等待连接队列? socket 监听相对还是比较简单的,先看 ...

  2. Linux内核网络协议栈:udp数据包发送(源码解读)

    <监视和调整Linux网络协议栈:接收数据> <监控和调整Linux网络协议栈的图解指南:接收数据> <Linux网络 - 数据包的接收过程> <Linux网 ...

  3. Linux内核网络协议栈流程及架构

    文章目录 Linux内核网络报文处理流程 Linux内核网络协议栈架构 Linux内核网络报文处理流程 linux网络协议栈是由若干个层组成的,网络数据的处理流程主要是指在协议栈的各个层之间的传递. ...

  4. 深入浅出Linux内核网络协议栈|结构sk_buff|Iptables|Netfilter丨内核源码丨驱动开发丨内核开发丨C/C++Linux服务器开发

    深入浅出Linux内核网络协议栈 视频讲解如下,点击观看: 深入浅出Linux内核网络协议栈|结构sk C/C++Linux服务器开发高级架构师知识点精彩内容包括:C/C++,Linux,Nginx, ...

  5. Linux内核网络协议栈7-socket端口管理

    一.前情回顾 上一节<socket 地址绑定 >中提到,应用程序传递过来的端口在内核中需要检查端口是否可用: if (sk->sk_prot->get_port(sk, snu ...

  6. Linux内核网络协议栈

    一.注册时机 1.在内核初始化时完成: 2.内核初始化过程(init/main.c):kernel_init()->do_basic_setup()->do_initcalls()-> ...

  7. linux内核网络协议栈--linux网络设备理解(十三)

    网络层次 linux网络设备驱动与字符设备和块设备有很大的不同. 字符设备和块设备对应/dev下的一个设备文件.而网络设备不存在这样的设备文件.网络设备使用套接字socket访问,虽然也使用read, ...

  8. Linux 内核网络协议栈运行原理

    封装:当应用程序用 TCP 协议传送数据时,数据首先进入内核网络协议栈中,然后逐一通过 TCP/IP 协议族的每层直到被当作一串比特流送入网络.对于每一层而言,对收到的数据都会封装相应的协议首部信息( ...

  9. Linux内核网络协议栈5-socket地址绑定

    一.socket绑定入口 1.示例代码 struct sockaddr_in server_address; server_address.sin_family = AF_INET; server_a ...

最新文章

  1. ATS 5.3.0中按域名生成日志配置文件log_hosts.config解读
  2. 《HeadFirst设计模式》笔记
  3. 微软 VS Code 有 1400 万用户,而全球开发者才 2400 万
  4. 快速入门PyTorch(3)--训练一个图片分类器和多 GPUs 训练
  5. 各银行汇款手续费之比较
  6. Kibana图形、报表分析
  7. 多个注解可以合并成一个,包括自定义注解
  8. OFFICE工具条的改进
  9. 教你如何认识各种光纤接口类型
  10. 胡适:一个最低限度的国学书目
  11. chrome分辨率测试工具
  12. Spring Security 原理
  13. can总线短距离不用双绞线_CAN总线抗干扰的6条“军规”
  14. 五一南京-无丝竹无案牍
  15. 基本概念学习(7003)---网络流量
  16. 第一道题目:一个美国人在菜市场上做生意。第一次,8美元买了一只鸡,9美元卖掉了;第二次,10美元买了同样的一只鸡,11美元又卖掉了。
  17. java旋转角度_java – 如何确定旋转图像的最终位置或角度
  18. android 系统下拉菜单,【MotoX评测】原生Android5.0下拉菜单和基础设置_Moto X_手机评测-中关村在线...
  19. 宇宙少女-小贾的一时兴起
  20. HTTP之原理,长短连接,响应码,三握四挥,八种方法

热门文章

  1. shardingsphere 分片策略_ShardingSphere系列(二) 分片策略
  2. windows python库安装包下载网站
  3. 程序—java记事本
  4. c语言微秒级延迟程序,C语言中生产随机数及计算运行时间(微秒级)
  5. va_start、va_end、va_arg 实现可变长参数
  6. c#重载和重写及运用
  7. nginx php上传大小设置
  8. 正则表达式 6. 存在(或)
  9. AWK 批量杀进程号,好记性不如烂笔头
  10. 简单博弈论总结加例题解析