Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/compat/linux/common Allow the old-style sockaddr_in6 for...
details: https://anonhg.NetBSD.org/src/rev/b7ab92521211
branches: trunk
changeset: 514686:b7ab92521211
user: fvdl <fvdl%NetBSD.org@localhost>
date: Sat Sep 08 14:19:09 2001 +0000
description:
Allow the old-style sockaddr_in6 for v6 addresses for which the
scope id is irrelevant. Makes netscape6 for Linux work again,
which uses v4-mapped addresses to connect to v4 sites.
diffstat:
sys/compat/linux/common/linux_socket.c | 92 +++++++++++++++++++++++----------
1 files changed, 64 insertions(+), 28 deletions(-)
diffs (208 lines):
diff -r a3e17a832e1d -r b7ab92521211 sys/compat/linux/common/linux_socket.c
--- a/sys/compat/linux/common/linux_socket.c Sat Sep 08 13:23:09 2001 +0000
+++ b/sys/compat/linux/common/linux_socket.c Sat Sep 08 14:19:09 2001 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_socket.c,v 1.33 2001/07/04 10:24:18 jdolecek Exp $ */
+/* $NetBSD: linux_socket.c,v 1.34 2001/09/08 14:19:09 fvdl Exp $ */
/*-
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
@@ -104,7 +104,7 @@
int linux_to_bsd_udp_sockopt __P((int));
int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *));
static int linux_sa_get __P((caddr_t *sgp, struct sockaddr **sap,
- const struct osockaddr *osa, int osalen));
+ const struct osockaddr *osa, int *osalen));
static int linux_sa_put __P((struct osockaddr *osa));
static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
@@ -254,24 +254,25 @@
syscallarg(int) tolen;
} */ *uap = v;
struct sys_sendto_args bsa;
+ int tolen;
SCARG(&bsa, s) = SCARG(uap, s);
SCARG(&bsa, buf) = SCARG(uap, msg);
SCARG(&bsa, len) = (size_t) SCARG(uap, len);
SCARG(&bsa, flags) = SCARG(uap, flags);
+ tolen = SCARG(uap, tolen);
if (SCARG(uap, to)) {
struct sockaddr *sa;
int error;
caddr_t sg = stackgap_init(p->p_emul);
- if ((error = linux_sa_get(&sg, &sa, SCARG(uap, to),
- SCARG(uap, tolen))))
+ if ((error = linux_sa_get(&sg, &sa, SCARG(uap, to), &tolen)))
return (error);
SCARG(&bsa, to) = sa;
} else
SCARG(&bsa, to) = NULL;
- SCARG(&bsa, tolen) = SCARG(uap, tolen);
+ SCARG(&bsa, tolen) = tolen;
return (sys_sendto(p, &bsa, retval));
}
@@ -306,7 +307,7 @@
return (ENOMEM);
error = linux_sa_get(&sg, &sa,
- (struct osockaddr *) msg.msg_name, msg.msg_namelen);
+ (struct osockaddr *) msg.msg_name, &msg.msg_namelen);
if (error)
return (error);
@@ -869,14 +870,16 @@
struct sockaddr *sa;
struct sys_connect_args bca;
caddr_t sg = stackgap_init(p->p_emul);
+ int namlen;
- error = linux_sa_get(&sg, &sa, SCARG(uap, name), SCARG(uap, namelen));
+ namlen = SCARG(uap, namelen);
+ error = linux_sa_get(&sg, &sa, SCARG(uap, name), &namlen);
if (error)
return (error);
SCARG(&bca, s) = SCARG(uap, s);
SCARG(&bca, name) = sa;
- SCARG(&bca, namelen) = (unsigned int) SCARG(uap, namelen);
+ SCARG(&bca, namelen) = (unsigned int) namlen;
error = sys_connect(p, &bca, retval);
@@ -919,23 +922,23 @@
syscallarg(const struct osockaddr *) name;
syscallarg(int) namelen;
} */ *uap = v;
- int error;
+ int error, namlen;
struct sys_bind_args bsa;
+ namlen = SCARG(uap, namelen);
SCARG(&bsa, s) = SCARG(uap, s);
if (SCARG(uap, name)) {
struct sockaddr *sa;
caddr_t sg = stackgap_init(p->p_emul);
- error = linux_sa_get(&sg, &sa, SCARG(uap, name),
- SCARG(uap, namelen));
+ error = linux_sa_get(&sg, &sa, SCARG(uap, name), &namlen);
if (error)
return (error);
SCARG(&bsa, name) = sa;
} else
SCARG(&bsa, name) = NULL;
- SCARG(&bsa, namelen) = SCARG(uap, namelen);
+ SCARG(&bsa, namelen) = namlen;
return (sys_bind(p, &bsa, retval));
}
@@ -994,18 +997,37 @@
caddr_t *sgp;
struct sockaddr **sap;
const struct osockaddr *osa;
- int osalen;
+ int *osalen;
{
int error=0, bdom;
struct sockaddr *sa, *usa;
struct osockaddr *kosa = (struct osockaddr *) &sa;
+ int alloclen;
+#ifdef INET6
+ int oldv6size;
+ struct sockaddr_in6 *sin6;
+#endif
- if (osalen < 0 || osalen > UCHAR_MAX || !osa)
+ if (*osalen < 2 || *osalen > UCHAR_MAX || !osa)
return (EINVAL);
- kosa = (struct osockaddr *) malloc(osalen, M_TEMP, M_WAITOK);
+ alloclen = *osalen;
+#ifdef INET6
+ oldv6size = 0;
+ /*
+ * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
+ * if it's a v4-mapped address, so reserve the proper space
+ * for it.
+ */
+ if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
+ alloclen = sizeof (struct sockaddr_in6);
+ oldv6size = 1;
+ }
+#endif
- if ((error = copyin(osa, (caddr_t) kosa, osalen)))
+ kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
+
+ if ((error = copyin(osa, (caddr_t) kosa, *osalen)))
goto out;
bdom = linux_to_bsd_domain(kosa->sa_family);
@@ -1019,36 +1041,50 @@
* Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
* which lacks the scope id compared with RFC2553 one. If we detect
* the situation, reject the address and write a message to system log.
+ *
+ * Still accept addresses for which the scope id is not used.
*/
- if (bdom == AF_INET6 && osalen < sizeof(struct sockaddr_in6)) {
- struct proc *p = curproc; /* XXX */
- int uid = p->p_cred && p->p_ucred ?
- p->p_ucred->cr_uid : -1;
+ if (oldv6size && bdom == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)kosa;
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
+ (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
+ !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
+ sin6->sin6_scope_id = 0;
+ } else {
+ struct proc *p = curproc; /* XXX */
+ int uid = p->p_cred && p->p_ucred ?
+ p->p_ucred->cr_uid : -1;
- log(LOG_DEBUG,
- "pid %d (%s), uid %d: obsolete pre-RFC2553 sockaddr_in6 rejected",
- p->p_pid, p->p_comm, uid);
- error = EINVAL;
- goto out;
+ log(LOG_DEBUG,
+ "pid %d (%s), uid %d: obsolete pre-RFC2553 "
+ "sockaddr_in6 rejected",
+ p->p_pid, p->p_comm, uid);
+ error = EINVAL;
+ goto out;
+ }
}
#endif
sa = (struct sockaddr *) kosa;
sa->sa_family = bdom;
- sa->sa_len = osalen;
+ sa->sa_len = alloclen;
- usa = (struct sockaddr *) stackgap_alloc(sgp, osalen);
+ usa = (struct sockaddr *) stackgap_alloc(sgp, alloclen);
if (!usa) {
error = ENOMEM;
goto out;
}
- if ((error = copyout(sa, usa, osalen)))
+ if ((error = copyout(sa, usa, alloclen)))
goto out;
*sap = usa;
out:
+ *osalen = alloclen;
free(kosa, M_TEMP);
return (error);
}
Home |
Main Index |
Thread Index |
Old Index