当前位置: 技术问答>linux和unix
帮我分析一下这段代码的作用,最好能给出关键部分的注释,来者有分!
来源: 互联网 发布时间:2015-09-02
本文导语: static int inet6_create(struct socket *sock, int protocol) { struct inet_opt *inet; struct ipv6_pinfo *np; struct sock *sk; struct tcp6_sock* tcp6sk; struct list_head *p; struct inet_protosw *answer; struct proto *answer_prot; unsigned char answer_flags; ...
static int inet6_create(struct socket *sock, int protocol)
{
struct inet_opt *inet;
struct ipv6_pinfo *np;
struct sock *sk;
struct tcp6_sock* tcp6sk;
struct list_head *p;
struct inet_protosw *answer;
struct proto *answer_prot;
unsigned char answer_flags;
char answer_no_check;
int rc;
/* Look for the requested type/protocol pair. */
answer = NULL;
rcu_read_lock();
list_for_each_rcu(p, &inetsw6[sock->type])
{
answer = list_entry(p, struct inet_protosw, list);
/* Check the non-wild match. */
if (protocol == answer->protocol)
{
if (protocol != IPPROTO_IP)
break;
}
else
{
/* Check for the two wild cases. */
if (IPPROTO_IP == protocol)
{
protocol = answer->protocol;
break;
}
if (IPPROTO_IP == answer->protocol)
break;
}
answer = NULL;
}
rc = -ESOCKTNOSUPPORT;
if (!answer)
goto out_rcu_unlock;
rc = -EPERM;
if (answer->capability > 0 && !capable(answer->capability))
goto out_rcu_unlock;
rc = -EPROTONOSUPPORT;
if (!protocol)
goto out_rcu_unlock;
sock->ops = answer->ops;
answer_prot = answer->prot;
answer_no_check = answer->no_check;
answer_flags = answer->flags;
rcu_read_unlock();
BUG_TRAP(answer_prot->slab != NULL);
rc = -ENOBUFS;
sk = sk_alloc(PF_INET6, GFP_KERNEL,
answer_prot->slab_obj_size,
answer_prot->slab);
if (sk == NULL)
goto out;
sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
rc = 0;
sk->sk_prot = answer_prot;
sk->sk_no_check = answer_no_check;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
inet = inet_sk(sk);
if (SOCK_RAW == sock->type) {
inet->num = protocol;
if (IPPROTO_RAW == protocol)
inet->hdrincl = 1;
}
sk->sk_destruct = inet6_sock_destruct;
sk->sk_family = PF_INET6;
sk->sk_protocol = protocol;
sk->sk_backlog_rcv = answer->prot->backlog_rcv;
tcp6sk = (struct tcp6_sock *)sk;
tcp6sk->pinet6 = np = inet6_sk_generic(sk);
np->hop_limit = -1;
np->mcast_hops = -1;
np->mc_loop = 1;
np->pmtudisc = IPV6_PMTUDISC_WANT;
np->ipv6only = sysctl_ipv6_bindv6only;
/* Init the ipv4 part of the socket since we can have sockets
* using v6 API for ipv4.
*/
inet->uc_ttl = -1;
inet->mc_loop = 1;
inet->mc_ttl = 1;
inet->mc_index = 0;
inet->mc_list = NULL;
if (ipv4_config.no_pmtu_disc)
inet->pmtudisc = IP_PMTUDISC_DONT;
else
inet->pmtudisc = IP_PMTUDISC_WANT;
#ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr);
atomic_inc(&inet_sock_nr);
#endif
if (inet->num) {
/* It assumes that any protocol which allows
* the user to assign a number at socket
* creation time automatically shares.
*/
inet->sport = ntohs(inet->num);
sk->sk_prot->hash(sk);
}
if (sk->sk_prot->init) {
rc = sk->sk_prot->init(sk);
if (rc) {
sk_common_release(sk);
goto out;
}
}
out:
return rc;
out_rcu_unlock:
rcu_read_unlock();
goto out;
}
{
struct inet_opt *inet;
struct ipv6_pinfo *np;
struct sock *sk;
struct tcp6_sock* tcp6sk;
struct list_head *p;
struct inet_protosw *answer;
struct proto *answer_prot;
unsigned char answer_flags;
char answer_no_check;
int rc;
/* Look for the requested type/protocol pair. */
answer = NULL;
rcu_read_lock();
list_for_each_rcu(p, &inetsw6[sock->type])
{
answer = list_entry(p, struct inet_protosw, list);
/* Check the non-wild match. */
if (protocol == answer->protocol)
{
if (protocol != IPPROTO_IP)
break;
}
else
{
/* Check for the two wild cases. */
if (IPPROTO_IP == protocol)
{
protocol = answer->protocol;
break;
}
if (IPPROTO_IP == answer->protocol)
break;
}
answer = NULL;
}
rc = -ESOCKTNOSUPPORT;
if (!answer)
goto out_rcu_unlock;
rc = -EPERM;
if (answer->capability > 0 && !capable(answer->capability))
goto out_rcu_unlock;
rc = -EPROTONOSUPPORT;
if (!protocol)
goto out_rcu_unlock;
sock->ops = answer->ops;
answer_prot = answer->prot;
answer_no_check = answer->no_check;
answer_flags = answer->flags;
rcu_read_unlock();
BUG_TRAP(answer_prot->slab != NULL);
rc = -ENOBUFS;
sk = sk_alloc(PF_INET6, GFP_KERNEL,
answer_prot->slab_obj_size,
answer_prot->slab);
if (sk == NULL)
goto out;
sock_init_data(sock, sk);
sk_set_owner(sk, THIS_MODULE);
rc = 0;
sk->sk_prot = answer_prot;
sk->sk_no_check = answer_no_check;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
inet = inet_sk(sk);
if (SOCK_RAW == sock->type) {
inet->num = protocol;
if (IPPROTO_RAW == protocol)
inet->hdrincl = 1;
}
sk->sk_destruct = inet6_sock_destruct;
sk->sk_family = PF_INET6;
sk->sk_protocol = protocol;
sk->sk_backlog_rcv = answer->prot->backlog_rcv;
tcp6sk = (struct tcp6_sock *)sk;
tcp6sk->pinet6 = np = inet6_sk_generic(sk);
np->hop_limit = -1;
np->mcast_hops = -1;
np->mc_loop = 1;
np->pmtudisc = IPV6_PMTUDISC_WANT;
np->ipv6only = sysctl_ipv6_bindv6only;
/* Init the ipv4 part of the socket since we can have sockets
* using v6 API for ipv4.
*/
inet->uc_ttl = -1;
inet->mc_loop = 1;
inet->mc_ttl = 1;
inet->mc_index = 0;
inet->mc_list = NULL;
if (ipv4_config.no_pmtu_disc)
inet->pmtudisc = IP_PMTUDISC_DONT;
else
inet->pmtudisc = IP_PMTUDISC_WANT;
#ifdef INET_REFCNT_DEBUG
atomic_inc(&inet6_sock_nr);
atomic_inc(&inet_sock_nr);
#endif
if (inet->num) {
/* It assumes that any protocol which allows
* the user to assign a number at socket
* creation time automatically shares.
*/
inet->sport = ntohs(inet->num);
sk->sk_prot->hash(sk);
}
if (sk->sk_prot->init) {
rc = sk->sk_prot->init(sk);
if (rc) {
sk_common_release(sk);
goto out;
}
}
out:
return rc;
out_rcu_unlock:
rcu_read_unlock();
goto out;
}
|
linux内核源码 具体不懂 我顶一下
|
上 http://linuxipsecvpn.cosoft.org.cn/Linux_network_source_reading/ 这里看看
|
gz