[IPV6]: Load protocol module dynamically.

[ 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>

authored by YOSHIFUJI Hideaki and committed by David S. Miller af1afe86 86c8f9d1

+33 -14
+33 -14
net/ipv6/af_inet6.c
··· 92 92 struct proto *answer_prot; 93 93 unsigned char answer_flags; 94 94 char answer_no_check; 95 - int rc; 95 + int try_loading_module = 0; 96 + int err; 96 97 97 98 /* Look for the requested type/protocol pair. */ 98 99 answer = NULL; 100 + lookup_protocol: 101 + err = -ESOCKTNOSUPPORT; 99 102 rcu_read_lock(); 100 103 list_for_each_rcu(p, &inetsw6[sock->type]) { 101 104 answer = list_entry(p, struct inet_protosw, list); ··· 116 113 if (IPPROTO_IP == answer->protocol) 117 114 break; 118 115 } 116 + err = -EPROTONOSUPPORT; 119 117 answer = NULL; 120 118 } 121 119 122 - rc = -ESOCKTNOSUPPORT; 123 - if (!answer) 124 - goto out_rcu_unlock; 125 - rc = -EPERM; 120 + if (!answer) { 121 + if (try_loading_module < 2) { 122 + rcu_read_unlock(); 123 + /* 124 + * Be more specific, e.g. net-pf-10-proto-132-type-1 125 + * (net-pf-PF_INET6-proto-IPPROTO_SCTP-type-SOCK_STREAM) 126 + */ 127 + if (++try_loading_module == 1) 128 + request_module("net-pf-%d-proto-%d-type-%d", 129 + PF_INET6, protocol, sock->type); 130 + /* 131 + * Fall back to generic, e.g. net-pf-10-proto-132 132 + * (net-pf-PF_INET6-proto-IPPROTO_SCTP) 133 + */ 134 + else 135 + request_module("net-pf-%d-proto-%d", 136 + PF_INET6, protocol); 137 + goto lookup_protocol; 138 + } else 139 + goto out_rcu_unlock; 140 + } 141 + 142 + err = -EPERM; 126 143 if (answer->capability > 0 && !capable(answer->capability)) 127 - goto out_rcu_unlock; 128 - rc = -EPROTONOSUPPORT; 129 - if (!protocol) 130 144 goto out_rcu_unlock; 131 145 132 146 sock->ops = answer->ops; 133 - 134 147 answer_prot = answer->prot; 135 148 answer_no_check = answer->no_check; 136 149 answer_flags = answer->flags; ··· 154 135 155 136 BUG_TRAP(answer_prot->slab != NULL); 156 137 157 - rc = -ENOBUFS; 138 + err = -ENOBUFS; 158 139 sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1); 159 140 if (sk == NULL) 160 141 goto out; 161 142 162 143 sock_init_data(sock, sk); 163 144 164 - rc = 0; 145 + err = 0; 165 146 sk->sk_no_check = answer_no_check; 166 147 if (INET_PROTOSW_REUSE & answer_flags) 167 148 sk->sk_reuse = 1; ··· 221 202 sk->sk_prot->hash(sk); 222 203 } 223 204 if (sk->sk_prot->init) { 224 - rc = sk->sk_prot->init(sk); 225 - if (rc) { 205 + err = sk->sk_prot->init(sk); 206 + if (err) { 226 207 sk_common_release(sk); 227 208 goto out; 228 209 } 229 210 } 230 211 out: 231 - return rc; 212 + return err; 232 213 out_rcu_unlock: 233 214 rcu_read_unlock(); 234 215 goto out;