diff options
| author | Steve French <sfrench@us.ibm.com> | 2005-12-05 14:15:30 -0500 | 
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2005-12-05 14:15:30 -0500 | 
| commit | c89a86bb96307019867d11874ef0b86adaa0598e (patch) | |
| tree | c44c1a825e8a143a4c52bcb8692292aeb77fa64e /net/ipv6/af_inet6.c | |
| parent | 07475ffba5800c53573180dd521273642adcd0e9 (diff) | |
| parent | e4f5c82a92c2a546a16af1614114eec19120e40a (diff) | |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'net/ipv6/af_inet6.c')
| -rw-r--r-- | net/ipv6/af_inet6.c | 47 | 
1 files changed, 33 insertions, 14 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index c63b8ce0e1b5..d9546380fa04 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c  | |||
| @@ -92,10 +92,13 @@ static int inet6_create(struct socket *sock, int protocol) | |||
| 92 | struct proto *answer_prot; | 92 | struct proto *answer_prot; | 
| 93 | unsigned char answer_flags; | 93 | unsigned char answer_flags; | 
| 94 | char answer_no_check; | 94 | char answer_no_check; | 
| 95 | int rc; | 95 | int try_loading_module = 0; | 
| 96 | int err; | ||
| 96 | 97 | ||
| 97 | /* Look for the requested type/protocol pair. */ | 98 | /* Look for the requested type/protocol pair. */ | 
| 98 | answer = NULL; | 99 | answer = NULL; | 
| 100 | lookup_protocol: | ||
| 101 | err = -ESOCKTNOSUPPORT; | ||
| 99 | rcu_read_lock(); | 102 | rcu_read_lock(); | 
| 100 | list_for_each_rcu(p, &inetsw6[sock->type]) { | 103 | list_for_each_rcu(p, &inetsw6[sock->type]) { | 
| 101 | answer = list_entry(p, struct inet_protosw, list); | 104 | answer = list_entry(p, struct inet_protosw, list); | 
| @@ -113,21 +116,37 @@ static int inet6_create(struct socket *sock, int protocol) | |||
| 113 | if (IPPROTO_IP == answer->protocol) | 116 | if (IPPROTO_IP == answer->protocol) | 
| 114 | break; | 117 | break; | 
| 115 | } | 118 | } | 
| 119 | err = -EPROTONOSUPPORT; | ||
| 116 | answer = NULL; | 120 | answer = NULL; | 
| 117 | } | 121 | } | 
| 118 | 122 | ||
| 119 | rc = -ESOCKTNOSUPPORT; | 123 | if (!answer) { | 
| 120 | if (!answer) | 124 | if (try_loading_module < 2) { | 
| 121 | goto out_rcu_unlock; | 125 | rcu_read_unlock(); | 
| 122 | rc = -EPERM; | 126 | /* | 
| 127 | * Be more specific, e.g. net-pf-10-proto-132-type-1 | ||
| 128 | * (net-pf-PF_INET6-proto-IPPROTO_SCTP-type-SOCK_STREAM) | ||
| 129 | */ | ||
| 130 | if (++try_loading_module == 1) | ||
| 131 | request_module("net-pf-%d-proto-%d-type-%d", | ||
| 132 | PF_INET6, protocol, sock->type); | ||
| 133 | /* | ||
| 134 | * Fall back to generic, e.g. net-pf-10-proto-132 | ||
| 135 | * (net-pf-PF_INET6-proto-IPPROTO_SCTP) | ||
| 136 | */ | ||
| 137 | else | ||
| 138 | request_module("net-pf-%d-proto-%d", | ||
| 139 | PF_INET6, protocol); | ||
| 140 | goto lookup_protocol; | ||
| 141 | } else | ||
| 142 | goto out_rcu_unlock; | ||
| 143 | } | ||
| 144 | |||
| 145 | err = -EPERM; | ||
| 123 | if (answer->capability > 0 && !capable(answer->capability)) | 146 | if (answer->capability > 0 && !capable(answer->capability)) | 
| 124 | goto out_rcu_unlock; | 147 | goto out_rcu_unlock; | 
| 125 | rc = -EPROTONOSUPPORT; | ||
| 126 | if (!protocol) | ||
| 127 | goto out_rcu_unlock; | ||
| 128 | 148 | ||
| 129 | sock->ops = answer->ops; | 149 | sock->ops = answer->ops; | 
| 130 | |||
| 131 | answer_prot = answer->prot; | 150 | answer_prot = answer->prot; | 
| 132 | answer_no_check = answer->no_check; | 151 | answer_no_check = answer->no_check; | 
| 133 | answer_flags = answer->flags; | 152 | answer_flags = answer->flags; | 
| @@ -135,14 +154,14 @@ static int inet6_create(struct socket *sock, int protocol) | |||
| 135 | 154 | ||
| 136 | BUG_TRAP(answer_prot->slab != NULL); | 155 | BUG_TRAP(answer_prot->slab != NULL); | 
| 137 | 156 | ||
| 138 | rc = -ENOBUFS; | 157 | err = -ENOBUFS; | 
| 139 | sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1); | 158 | sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1); | 
| 140 | if (sk == NULL) | 159 | if (sk == NULL) | 
| 141 | goto out; | 160 | goto out; | 
| 142 | 161 | ||
| 143 | sock_init_data(sock, sk); | 162 | sock_init_data(sock, sk); | 
| 144 | 163 | ||
| 145 | rc = 0; | 164 | err = 0; | 
| 146 | sk->sk_no_check = answer_no_check; | 165 | sk->sk_no_check = answer_no_check; | 
| 147 | if (INET_PROTOSW_REUSE & answer_flags) | 166 | if (INET_PROTOSW_REUSE & answer_flags) | 
| 148 | sk->sk_reuse = 1; | 167 | sk->sk_reuse = 1; | 
| @@ -202,14 +221,14 @@ static int inet6_create(struct socket *sock, int protocol) | |||
| 202 | sk->sk_prot->hash(sk); | 221 | sk->sk_prot->hash(sk); | 
| 203 | } | 222 | } | 
| 204 | if (sk->sk_prot->init) { | 223 | if (sk->sk_prot->init) { | 
| 205 | rc = sk->sk_prot->init(sk); | 224 | err = sk->sk_prot->init(sk); | 
| 206 | if (rc) { | 225 | if (err) { | 
| 207 | sk_common_release(sk); | 226 | sk_common_release(sk); | 
| 208 | goto out; | 227 | goto out; | 
| 209 | } | 228 | } | 
| 210 | } | 229 | } | 
| 211 | out: | 230 | out: | 
| 212 | return rc; | 231 | return err; | 
| 213 | out_rcu_unlock: | 232 | out_rcu_unlock: | 
| 214 | rcu_read_unlock(); | 233 | rcu_read_unlock(); | 
| 215 | goto out; | 234 | goto out; | 
