netdev
[Top] [All Lists]

Re: sin6_scope_id and 2.2.x kernel

To: misiek@xxxxxxxxxx
Subject: Re: sin6_scope_id and 2.2.x kernel
From: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@xxxxxxxxxxxxxxxxx>
Date: Sun, 19 Nov 2000 09:42:43 +0900
Cc: netdev@xxxxxxxxxxx, usagi-users@xxxxxxxxxxxxxx
In-reply-to: <20001118200432.B10801@pld.ORG.PL>
References: <20001117181502.B25253@pld.ORG.PL> <20001118082211C.yoshfuji@ecei.tohoku.ac.jp> <20001118200432.B10801@pld.ORG.PL>
Sender: owner-netdev@xxxxxxxxxxx
In article <20001118200432.B10801@xxxxxxxxxx> (at Sat, 18 Nov 2000 20:04:32 
+0100), Arkadiusz Miskiewicz <misiek@xxxxxxxxxx> says:

> > If you introduce sin6_scope_id into linux-2.2.x,
> > binaries on glibc-2.1 systems (including binaries
> > build on glibc-2.1 systems) encounter many random problem.
> IMO you are wrong here because all such binaries && linux 2.4
> (so sin6_scope_id in kernel) are working fine without almost
> any problems (one problem is lack of sin6_scope support in glibc,
> so troubles with link-local addresses)

You are wrong.
There are possibility of binary incompatibility and security flaws.


> > Use linux-2.4.x
> I'm always using latest devel kernel 8) but some PLD users
> still use 2.2

Ipv6 users should upgrade to linux-2.4 as glibc people expect.
(or, convince them introduce linux-2.2 hack into glibc-2.2.)


> (, or usagi linux-2.2.x).
> when we were testing it we got problems such as invalid argument
> in connect() even for global v6 addresses etc so it was unusable.

Why don't you report it to us?


Anyway, this patch against glibc-2.2 will help you.
(this was contributed to glibc without linux-2.2 hack.)

Index: inet/getnameinfo.c
===================================================================
RCS file: /cvsroot/usagi/libc/glibc22/inet/getnameinfo.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.9
diff -u -r1.1.1.2 -r1.1.1.2.4.9
--- inet/getnameinfo.c  2000/11/03 07:25:51     1.1.1.2
+++ inet/getnameinfo.c  2000/11/19 00:19:13     1.1.1.2.4.9
@@ -1,3 +1,5 @@
+/* $USAGI: getnameinfo.c,v 1.1.1.2.4.9 2000/11/19 00:19:13 yoshfuji Exp $ */
+
 /* The Inner Net License, Version 2.00
 
   The author(s) grant permission for redistribution and use in source and
@@ -175,6 +177,10 @@
   struct hostent th;
   int ok = 0;
 
+  if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|
+               NI_NAMEREQD|NI_DGRAM))
+    return -1;
+
   if (sa == NULL || addrlen < sizeof (sa_family_t))
     return -1;
 
@@ -189,7 +195,7 @@
        return -1;
       break;
     case AF_INET6:
-      if (addrlen < sizeof (struct sockaddr_in6))
+      if (addrlen < sizeof (struct __sockaddr_in6_rfc2133))
        return -1;
       break;
     default:
@@ -273,8 +279,11 @@
                        ok = 1;
                      }
                  }
-               strncpy (host, h->h_name, hostlen);
-               ok = 1;
+               else
+                 {
+                   strncpy (host, h->h_name, hostlen);
+                   ok = 1;
+                 }
              }
          }
 
@@ -295,40 +304,37 @@
 
                    c = inet_ntop (AF_INET6,
                                   (void *) &sin6p->sin6_addr, host, hostlen);
-                   if (addrlen > sizeof (struct sockaddr_in6)
+                   if (addrlen >= sizeof (struct sockaddr_in6)
                        && (scopeid = sin6p->sin6_scope_id))
                      {
                        /* Buffer is >= IFNAMSIZ+1.  */
-                       char scopebuf[IFNAMSIZ + 1];
+                       char scopebuf[IFNAMSIZ + 1]={SCOPE_DELIMITER};
+                       char *scopeptr = &scopebuf[1];
                        int ni_numericscope = 0;
+                       size_t real_hostlen = __strnlen(host, hostlen);
+                       size_t scopelen = 0;
 
                        if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr)
                            || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr))
                          {
                            if (if_indextoname (scopeid, scopebuf) == NULL)
                              ++ni_numericscope;
+                           else
+                             scopelen = strlen(scopebuf);
                          }
                        else
                          ++ni_numericscope;
 
                        if (ni_numericscope)
-                         {
-                           char *scopeptr = &scopebuf[1];
-                           size_t real_hostlen;
-                           size_t scopelen;
-
-                           scopebuf[0] = SCOPE_DELIMITER;
-                           scopelen = 1 + __snprintf (scopeptr,
-                                                      (scopebuf
-                                                       + sizeof scopebuf
-                                                       - scopeptr),
-                                                      "%u", scopeid);
-
-                           real_hostlen = __strnlen (host, hostlen);
-                           if (real_hostlen + scopelen + 1 > hostlen)
-                             return -1;
-                           memcpy (host + real_hostlen, scopebuf, scopelen);
-                         }
+                         scopelen = 1 + __snprintf (scopeptr,
+                                                    (scopebuf
+                                                     + sizeof scopebuf
+                                                     - scopeptr),
+                                                    "%u", scopeid);
+
+                       if (real_hostlen + scopelen + 1 > hostlen)
+                         return -1;
+                       memcpy (host + real_hostlen, scopebuf, scopelen + 1);
                      }
                  }
                else
Index: inet/netinet/in.h
===================================================================
RCS file: /cvsroot/usagi/libc/glibc22/inet/netinet/in.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.4
diff -u -r1.1.1.1 -r1.1.1.1.4.4
--- inet/netinet/in.h   2000/10/13 09:38:50     1.1.1.1
+++ inet/netinet/in.h   2000/11/19 00:19:13     1.1.1.1.4.4
@@ -1,3 +1,5 @@
+/* $USAGI: in.h,v 1.1.1.1.4.4 2000/11/19 00:19:13 yoshfuji Exp $ */
+
 /* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -212,6 +214,15 @@
     struct in6_addr sin6_addr; /* IPv6 address */
     uint32_t sin6_scope_id;    /* IPv6 scope-id */
   };
+#ifdef __USE_GNU
+struct __sockaddr_in6_rfc2133
+  {
+    __SOCKADDR_COMMON (__sin6_);
+    in_port_t __sin6_port;
+    uint32_t __sin6_flowinfo;
+    struct in6_addr __sin6_addr;
+  };
+#endif
 
 /* IPv6 multicast request.  */
 struct ipv6_mreq
Index: sysdeps/posix/getaddrinfo.c
===================================================================
RCS file: /cvsroot/usagi/libc/glibc22/sysdeps/posix/getaddrinfo.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.8
diff -u -r1.1.1.1 -r1.1.1.1.4.8
--- sysdeps/posix/getaddrinfo.c 2000/10/13 09:38:40     1.1.1.1
+++ sysdeps/posix/getaddrinfo.c 2000/11/06 08:55:47     1.1.1.1.4.8
@@ -1,3 +1,5 @@
+/* $USAGI: getaddrinfo.c,v 1.1.1.1.4.8 2000/11/06 08:55:47 yoshfuji Exp $ */
+
 /* The Inner Net License, Version 2.00
 
   The author(s) grant permission for redistribution and use in source and
@@ -99,13 +101,14 @@
 
 /* Values for `protoflag'.  */
 #define GAI_PROTO_NOSERVICE    1
+#define GAI_PROTO_PROTOANY     2
 
 static struct gaih_typeproto gaih_inet_typeproto[] =
 {
   { 0, 0, NULL, 0 },
   { SOCK_STREAM, IPPROTO_TCP, (char *) "tcp", 0 },
   { SOCK_DGRAM, IPPROTO_UDP, (char *) "udp", 0 },
-  { SOCK_RAW, IPPROTO_RAW, (char *) "raw", GAI_PROTO_NOSERVICE },
+  { SOCK_RAW, 0, (char *) "raw", GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE },
   { 0, 0, NULL, 0 }
 };
 
@@ -150,6 +153,7 @@
             && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0
                 || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
                 || (req->ai_protocol != 0
+                    && !(tp->protoflag & GAI_PROTO_PROTOANY)
                     && req->ai_protocol != tp->protocol)))
        ++tp;
 
@@ -229,6 +233,7 @@
 
 static int
 gaih_inet_serv (const char *servicename, struct gaih_typeproto *tp,
+              const struct addrinfo *req,
               struct gaih_servtuple *st)
 {
   struct servent *s;
@@ -255,7 +260,8 @@
 
   st->next = NULL;
   st->socktype = tp->socktype;
-  st->protocol = tp->protocol;
+  st->protocol = (tp->protoflag & GAI_PROTO_PROTOANY) ?
+                req->ai_protocol : tp->protocol;
   st->port = s->s_port;
 
   return 0;
@@ -291,8 +297,10 @@
     {                                                          \
       for (i = 0; h->h_addr_list[i]; i++)                      \
        {                                                       \
-         if (*pat == NULL)                                     \
+         if (*pat == NULL) {                                   \
            *pat = __alloca (sizeof(struct gaih_addrtuple));    \
+           (*pat)->scopeid = 0;                                \
+         }                                                     \
          (*pat)->next = NULL;                                  \
          (*pat)->family = _family;                             \
          memcpy ((*pat)->addr, h->h_addr_list[i],              \
@@ -319,6 +327,7 @@
       while (tp->name != NULL
             && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype)
                 || (req->ai_protocol != 0
+                    && !(tp->protoflag & GAI_PROTO_PROTOANY)
                     && req->ai_protocol != tp->protocol)))
        ++tp;
 
@@ -343,7 +352,7 @@
              st = (struct gaih_servtuple *)
                __alloca (sizeof (struct gaih_servtuple));
 
-             if ((rc = gaih_inet_serv (service->name, tp, st)))
+             if ((rc = gaih_inet_serv (service->name, tp, req, st)))
                return rc;
            }
          else
@@ -359,11 +368,15 @@
                  if (req->ai_socktype != 0
                      && req->ai_socktype != tp->socktype)
                    continue;
+                 if (req->ai_protocol != 0 
+                     && !(tp->protoflag & GAI_PROTO_PROTOANY)
+                     && req->ai_protocol != tp->protocol)
+                   continue;
 
                  newp = (struct gaih_servtuple *)
                    __alloca (sizeof (struct gaih_servtuple));
 
-                 if ((rc = gaih_inet_serv (service->name, tp, newp)))
+                 if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
                    {
                      if (rc & GAIH_OKIFUNSPEC)
                        continue;
@@ -382,7 +395,8 @@
          st = __alloca (sizeof (struct gaih_servtuple));
          st->next = NULL;
          st->socktype = tp->socktype;
-         st->protocol = tp->protocol;
+         st->protocol = (tp->protoflag & GAI_PROTO_PROTOANY) ?
+                        req->ai_protocol : tp->protocol;
          st->port = htons (service->num);
        }
     }
@@ -390,8 +404,9 @@
     {
       st = __alloca (sizeof (struct gaih_servtuple));
       st->next = NULL;
-      st->socktype = req->ai_socktype;
-      st->protocol = req->ai_protocol;
+      st->socktype = tp->socktype;
+      st->protocol = (tp->protoflag & GAI_PROTO_PROTOANY) ?
+                    req->ai_protocol : tp->protocol;
       st->port = 0;
     }
   else
@@ -542,6 +557,7 @@
     struct gaih_servtuple *st2;
     struct gaih_addrtuple *at2 = at;
     size_t socklen, namelen;
+    sa_family_t family;
 
     /*
       buffer is the size of an unformatted IPv6 address in printable format.
@@ -597,9 +613,15 @@
          namelen = 0;
 
        if (at2->family == AF_INET6)
-         socklen = sizeof (struct sockaddr_in6);
+         { 
+           family = AF_INET6;
+           socklen = sizeof (struct sockaddr_in6);
+         }
        else
-         socklen = sizeof (struct sockaddr_in);
+         {
+           family = AF_INET;
+           socklen = sizeof (struct sockaddr_in);
+         }
 
        for (st2 = st; st2 != NULL; st2 = st2->next)
          {
@@ -608,7 +630,7 @@
              return -EAI_MEMORY;
 
            (*pai)->ai_flags = req->ai_flags;
-           (*pai)->ai_family = at2->family;
+           (*pai)->ai_family = family;
            (*pai)->ai_socktype = st2->socktype;
            (*pai)->ai_protocol = st2->protocol;
            (*pai)->ai_addrlen = socklen;
@@ -616,9 +638,9 @@
 #if SALEN
            (*pai)->ai_addr->sa_len = socklen;
 #endif /* SALEN */
-           (*pai)->ai_addr->sa_family = at2->family;
+           (*pai)->ai_addr->sa_family = family;
 
-           if (at2->family == AF_INET6)
+           if (family == AF_INET6)
              {
                struct sockaddr_in6 *sin6p =
                  (struct sockaddr_in6 *) (*pai)->ai_addr;
@@ -703,7 +725,7 @@
       else
        /* Can't specify a numerical socket unless a protocol family was
           given. */
-        if (hints->ai_socktype == 0)
+        if (hints->ai_socktype == 0 && hints->ai_protocol == 0)
           return EAI_SERVICE;
       pservice = &gaih_service;
     }


-- 
Hideaki YOSHIFUJI @ USAGI Project  <yoshfuji@xxxxxxxxxxxxxx>
PGP5i FP: F731 6599 5EB2 BBA7 1515  1323 1806 A96F 5700 6B25 

<Prev in Thread] Current Thread [Next in Thread>