Linux bind的核心执行函数

描述

bind的核心执行函数

bind系统调用的核心函数调用流程如下:

SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
|
sock- >ops- >bind(sock,
            (struct sockaddr *)
            &address, addrlen);
|
inet_bind
|
inet_csk_get_port

中间的流程暂且不看,本文主要分析最重要的函数:inet_csk_get_port,从该函数出发了解本地绑定端口如何管理。

以下是原函数,通过下文章节逐步分段分析

int inet_csk_get_port(struct sock *sk, unsigned short snum)
{
 bool reuse = sk- >sk_reuse && sk- >sk_state != TCP_LISTEN;
 struct inet_hashinfo *hinfo = sk- >sk_prot- >h.hashinfo;
 int ret = 1, port = snum;
 struct inet_bind_hashbucket *head;
 struct net *net = sock_net(sk);
 struct inet_bind_bucket *tb = NULL;
 kuid_t uid = sock_i_uid(sk);

 if (!port) {
  head = inet_csk_find_open_port(sk, &tb, &port);
  if (!head)
   return ret;
  if (!tb)
   goto tb_not_found;
  goto success;
 }
 head = &hinfo- >bhash[inet_bhashfn(net, port,
       hinfo- >bhash_size)];
 spin_lock_bh(&head- >lock);
 inet_bind_bucket_for_each(tb, &head- >chain)
  if (net_eq(ib_net(tb), net) && tb- >port == port)
   goto tb_found;
tb_not_found:
 tb = inet_bind_bucket_create(hinfo- >bind_bucket_cachep,
         net, head, port);
 if (!tb)
  goto fail_unlock;
tb_found:
 if (!hlist_empty(&tb- >owners)) {
  if (sk- >sk_reuse == SK_FORCE_REUSE)
   goto success;

  if ((tb- >fastreuse > 0 && reuse) ||
      sk_reuseport_match(tb, sk))
   goto success;
  if (inet_csk_bind_conflict(sk, tb, true, true))
   goto fail_unlock;
 }
success:
 if (hlist_empty(&tb- >owners)) {
  tb- >fastreuse = reuse;
  if (sk- >sk_reuseport) {
   tb- >fastreuseport = FASTREUSEPORT_ANY;
   tb- >fastuid = uid;
   tb- >fast_rcv_saddr = sk- >sk_rcv_saddr;
   tb- >fast_ipv6_only = ipv6_only_sock(sk);
   tb- >fast_sk_family = sk- >sk_family;
#if IS_ENABLED(CONFIG_IPV6)
   tb- >fast_v6_rcv_saddr = sk- >sk_v6_rcv_saddr;
#endif
  } else {
   tb- >fastreuseport = 0;
  }
 } else {
  if (!reuse)
   tb- >fastreuse = 0;
  if (sk- >sk_reuseport) {
   if (!sk_reuseport_match(tb, sk)) {
    tb- >fastreuseport = FASTREUSEPORT_STRICT;
    tb- >fastuid = uid;
    tb- >fast_rcv_saddr = sk- >sk_rcv_saddr;
    tb- >fast_ipv6_only = ipv6_only_sock(sk);
    tb- >fast_sk_family = sk- >sk_family;
#if IS_ENABLED(CONFIG_IPV6)
    tb- >fast_v6_rcv_saddr = sk- >sk_v6_rcv_saddr;
#endif
   }
  } else {
   tb- >fastreuseport = 0;
  }
 }
 if (!inet_csk(sk)- >icsk_bind_hash)
  inet_bind_hash(sk, tb, port);
 WARN_ON(inet_csk(sk)- >icsk_bind_hash != tb);
 ret = 0;

fail_unlock:
 spin_unlock_bh(&head- >lock);
 return ret;
}
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分