aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcauth_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r--net/sunrpc/svcauth_unix.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index d8c041114497..207311610988 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -10,11 +10,13 @@
10#include <linux/seq_file.h> 10#include <linux/seq_file.h>
11#include <linux/hash.h> 11#include <linux/hash.h>
12#include <linux/string.h> 12#include <linux/string.h>
13#include <linux/slab.h>
13#include <net/sock.h> 14#include <net/sock.h>
14#include <net/ipv6.h> 15#include <net/ipv6.h>
15#include <linux/kernel.h> 16#include <linux/kernel.h>
16#define RPCDBG_FACILITY RPCDBG_AUTH 17#define RPCDBG_FACILITY RPCDBG_AUTH
17 18
19#include <linux/sunrpc/clnt.h>
18 20
19/* 21/*
20 * AUTHUNIX and AUTHNULL credentials are both handled here. 22 * AUTHUNIX and AUTHNULL credentials are both handled here.
@@ -187,10 +189,13 @@ static int ip_map_parse(struct cache_detail *cd,
187 * for scratch: */ 189 * for scratch: */
188 char *buf = mesg; 190 char *buf = mesg;
189 int len; 191 int len;
190 int b1, b2, b3, b4, b5, b6, b7, b8;
191 char c;
192 char class[8]; 192 char class[8];
193 struct in6_addr addr; 193 union {
194 struct sockaddr sa;
195 struct sockaddr_in s4;
196 struct sockaddr_in6 s6;
197 } address;
198 struct sockaddr_in6 sin6;
194 int err; 199 int err;
195 200
196 struct ip_map *ipmp; 201 struct ip_map *ipmp;
@@ -209,24 +214,24 @@ static int ip_map_parse(struct cache_detail *cd,
209 len = qword_get(&mesg, buf, mlen); 214 len = qword_get(&mesg, buf, mlen);
210 if (len <= 0) return -EINVAL; 215 if (len <= 0) return -EINVAL;
211 216
212 if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) == 4) { 217 if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0)
213 addr.s6_addr32[0] = 0;
214 addr.s6_addr32[1] = 0;
215 addr.s6_addr32[2] = htonl(0xffff);
216 addr.s6_addr32[3] =
217 htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
218 } else if (sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%c",
219 &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
220 addr.s6_addr16[0] = htons(b1);
221 addr.s6_addr16[1] = htons(b2);
222 addr.s6_addr16[2] = htons(b3);
223 addr.s6_addr16[3] = htons(b4);
224 addr.s6_addr16[4] = htons(b5);
225 addr.s6_addr16[5] = htons(b6);
226 addr.s6_addr16[6] = htons(b7);
227 addr.s6_addr16[7] = htons(b8);
228 } else
229 return -EINVAL; 218 return -EINVAL;
219 switch (address.sa.sa_family) {
220 case AF_INET:
221 /* Form a mapped IPv4 address in sin6 */
222 memset(&sin6, 0, sizeof(sin6));
223 sin6.sin6_family = AF_INET6;
224 sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
225 sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr;
226 break;
227#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
228 case AF_INET6:
229 memcpy(&sin6, &address.s6, sizeof(sin6));
230 break;
231#endif
232 default:
233 return -EINVAL;
234 }
230 235
231 expiry = get_expiry(&mesg); 236 expiry = get_expiry(&mesg);
232 if (expiry ==0) 237 if (expiry ==0)
@@ -243,7 +248,8 @@ static int ip_map_parse(struct cache_detail *cd,
243 } else 248 } else
244 dom = NULL; 249 dom = NULL;
245 250
246 ipmp = ip_map_lookup(class, &addr); 251 /* IPv6 scope IDs are ignored for now */
252 ipmp = ip_map_lookup(class, &sin6.sin6_addr);
247 if (ipmp) { 253 if (ipmp) {
248 err = ip_map_update(ipmp, 254 err = ip_map_update(ipmp,
249 container_of(dom, struct unix_domain, h), 255 container_of(dom, struct unix_domain, h),
@@ -619,7 +625,7 @@ static int unix_gid_show(struct seq_file *m,
619 else 625 else
620 glen = 0; 626 glen = 0;
621 627
622 seq_printf(m, "%d %d:", ug->uid, glen); 628 seq_printf(m, "%u %d:", ug->uid, glen);
623 for (i = 0; i < glen; i++) 629 for (i = 0; i < glen; i++)
624 seq_printf(m, " %d", GROUP_AT(ug->gi, i)); 630 seq_printf(m, " %d", GROUP_AT(ug->gi, i));
625 seq_printf(m, "\n"); 631 seq_printf(m, "\n");