Skip to content

Commit

Permalink
[IPV6]: Load protocol module dynamically.
Browse files Browse the repository at this point in the history
[ Modified to match inet_create() bug fix by Herbert Xu -DaveM ]

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
YOSHIFUJI Hideaki authored and David S. Miller committed Dec 3, 2005
1 parent 86c8f9d commit af1afe8
Showing 1 changed file with 33 additions and 14 deletions.
47 changes: 33 additions & 14 deletions net/ipv6/af_inet6.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,13 @@ static int inet6_create(struct socket *sock, int protocol)
struct proto *answer_prot;
unsigned char answer_flags;
char answer_no_check;
int rc;
int try_loading_module = 0;
int err;

/* Look for the requested type/protocol pair. */
answer = NULL;
lookup_protocol:
err = -ESOCKTNOSUPPORT;
rcu_read_lock();
list_for_each_rcu(p, &inetsw6[sock->type]) {
answer = list_entry(p, struct inet_protosw, list);
Expand All @@ -113,36 +116,52 @@ static int inet6_create(struct socket *sock, int protocol)
if (IPPROTO_IP == answer->protocol)
break;
}
err = -EPROTONOSUPPORT;
answer = NULL;
}

rc = -ESOCKTNOSUPPORT;
if (!answer)
goto out_rcu_unlock;
rc = -EPERM;
if (!answer) {
if (try_loading_module < 2) {
rcu_read_unlock();
/*
* Be more specific, e.g. net-pf-10-proto-132-type-1
* (net-pf-PF_INET6-proto-IPPROTO_SCTP-type-SOCK_STREAM)
*/
if (++try_loading_module == 1)
request_module("net-pf-%d-proto-%d-type-%d",
PF_INET6, protocol, sock->type);
/*
* Fall back to generic, e.g. net-pf-10-proto-132
* (net-pf-PF_INET6-proto-IPPROTO_SCTP)
*/
else
request_module("net-pf-%d-proto-%d",
PF_INET6, protocol);
goto lookup_protocol;
} else
goto out_rcu_unlock;
}

err = -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;
err = -ENOBUFS;
sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1);
if (sk == NULL)
goto out;

sock_init_data(sock, sk);

rc = 0;
err = 0;
sk->sk_no_check = answer_no_check;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
Expand Down Expand Up @@ -202,14 +221,14 @@ static int inet6_create(struct socket *sock, int protocol)
sk->sk_prot->hash(sk);
}
if (sk->sk_prot->init) {
rc = sk->sk_prot->init(sk);
if (rc) {
err = sk->sk_prot->init(sk);
if (err) {
sk_common_release(sk);
goto out;
}
}
out:
return rc;
return err;
out_rcu_unlock:
rcu_read_unlock();
goto out;
Expand Down

0 comments on commit af1afe8

Please sign in to comment.