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