bring in latest KAME implementation.
authoritojun <itojun@openbsd.org>
Wed, 26 Apr 2000 14:46:47 +0000 (14:46 +0000)
committeritojun <itojun@openbsd.org>
Wed, 26 Apr 2000 14:46:47 +0000 (14:46 +0000)
conforms to draft-ietf-ipngwg-scopedaddr-format-01.txt.
behavior change: returns numeric scopeid if we can't convert to string
removed #if 0'ed portion which we will never revisit.

lib/libc/net/getnameinfo.c

index c174b8a..33e628c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: getnameinfo.c,v 1.12 2000/03/13 02:22:12 itojun Exp $ */
+/*     $OpenBSD: getnameinfo.c,v 1.13 2000/04/26 14:46:47 itojun Exp $ */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  * - RFC2553 says that we should raise error on short buffer.  X/Open says
  *   we need to truncate the result.  We obey RFC2553 (and X/Open should be
  *   modified).
+ * - What is "local" in NI_FQDN?
+ * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
+ * - (KAME extension) NI_WITHSCOPEID when called with global address,
+ *   and sin6_scope_id filled
  */
 
+#ifndef INET6
 #define INET6
+#endif
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -79,7 +85,9 @@ struct sockinet {
 };
 
 #ifdef INET6
-static char *ip6_sa2str __P((struct sockaddr_in6 *, char *, int));
+static int ip6_parsenumeric __P((const struct sockaddr *, char *, char *,
+                                int, int));
+static int ip6_sa2str __P((struct sockaddr_in6 *, char *, size_t, int));
 #endif 
 
 #define ENI_NOSOCKET   0
@@ -207,69 +215,40 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
                /* NUMERICHOST and NAMEREQD conflicts with each other */
                if (flags & NI_NAMEREQD)
                        return ENI_NOHOSTNAME;
-               if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
-                   == NULL)
-                       return ENI_SYSTEM;
-               numaddrlen = strlen(numaddr);
-               if (numaddrlen + 1 > hostlen) /* don't forget terminator */
-                       return ENI_MEMORY;
-               strcpy(host, numaddr);
-#if defined(INET6) && defined(NI_WITHSCOPEID)
-               if (afd->a_af == AF_INET6 &&
-                   (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
-                    IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&
-                   ((struct sockaddr_in6 *)sa)->sin6_scope_id) {
-#ifndef ALWAYS_WITHSCOPE
-                       if (flags & NI_WITHSCOPEID)
-#endif /* !ALWAYS_WITHSCOPE */
-                       {
-                               char scopebuf[MAXHOSTNAMELEN], *s;
-                               int scopelen;
-
-                               if ((s = ip6_sa2str((struct sockaddr_in6 *)sa,
-                                                   scopebuf, 0)) == NULL)
-                                       /* XXX what should we do? */
-                                       strcpy(scopebuf, "0");
 
-                               scopelen = strlen(scopebuf);
-                               if (scopelen + 1 + numaddrlen + 1 > hostlen)
-                                       return ENI_MEMORY;
+               switch(afd->a_af) {
+#ifdef INET6
+               case AF_INET6:
+               {
+                       int error;
 
-#if 0
-                               /*
-                                * construct <scopeid><delim><numeric-addr>
-                                */
-                               /*
-                                * Shift the host string to allocate
-                                * space for the scope ID part.
-                                */
-                               memmove(host + scopelen + 1, host,
-                                       numaddrlen);
-                               /* copy the scope ID and the delimiter */
-                               memcpy(host, scopebuf, scopelen);
-                               host[scopelen] = SCOPE_DELIMITER;
-                               host[scopelen + 1 + numaddrlen] = '\0';
-#else
-                               /*
-                                * construct <numeric-addr><delim><scopeid>
-                                */
-                               memcpy(host + numaddrlen + 1, scopebuf,
-                                   scopelen);
-                               host[numaddrlen] = SCOPE_DELIMITER;
-                               host[numaddrlen + 1 + scopelen] = '\0';
+                       if ((error = ip6_parsenumeric(sa, addr, host,
+                                                     hostlen, flags)) != 0)
+                               return(error);
+                       break;
+               }
 #endif
-                       }
+               default:
+                       if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+                           == NULL)
+                               return ENI_SYSTEM;
+                       numaddrlen = strlen(numaddr);
+                       if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+                               return ENI_MEMORY;
+                       strcpy(host, numaddr);
+                       break;
                }
-#endif /* INET6 */
        } else {
                hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
                h_error = h_errno;
 
                if (hp) {
 #if 0
+                       /*
+                        * commented out, since "for local host" is not
+                        * implemented here - see RFC2553 p30
+                        */
                        if (flags & NI_NOFQDN) {
-                               char *p;
-
                                p = strchr(hp->h_name, '.');
                                if (p)
                                        *p = '\0';
@@ -282,23 +261,82 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
                } else {
                        if (flags & NI_NAMEREQD)
                                return ENI_NOHOSTNAME;
-                       if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
-                           == NULL)
-                               return ENI_NOHOSTNAME;
-                       if (strlen(numaddr) > hostlen)
-                               return ENI_MEMORY;
-                       strcpy(host, numaddr);
+                       switch(afd->a_af) {
+#ifdef INET6
+                       case AF_INET6:
+                       {
+                               int error;
+
+                               if ((error = ip6_parsenumeric(sa, addr, host,
+                                                             hostlen,
+                                                             flags)) != 0)
+                                       return(error);
+                               break;
+                       }
+#endif
+                       default:
+                               if (inet_ntop(afd->a_af, addr, host,
+                                   hostlen) == NULL)
+                                       return ENI_SYSTEM;
+                               break;
+                       }
                }
        }
        return SUCCESS;
 }
 
 #ifdef INET6
+static int
+ip6_parsenumeric(sa, addr, host, hostlen, flags)
+       const struct sockaddr *sa;
+       char *addr, *host;
+       int flags, hostlen;
+{
+       int numaddrlen;
+       char numaddr[512];
+
+       if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr))
+           == NULL)
+               return ENI_SYSTEM;
+
+       numaddrlen = strlen(numaddr);
+       if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+               return ENI_MEMORY;
+       strcpy(host, numaddr);
+
+#ifdef NI_WITHSCOPEID
+       if (((struct sockaddr_in6 *)sa)->sin6_scope_id) {
+               if (flags & NI_WITHSCOPEID)
+               {
+                       char scopebuf[MAXHOSTNAMELEN];
+                       int scopelen;
+
+                       /* ip6_sa2str never fails */
+                       scopelen = ip6_sa2str((struct sockaddr_in6 *)sa,
+                                             scopebuf, sizeof(scopebuf),
+                                             0);
+                       if (scopelen + 1 + numaddrlen + 1 > hostlen)
+                               return ENI_MEMORY;
+                       /*
+                        * construct <numeric-addr><delim><scopeid>
+                        */
+                       memcpy(host + numaddrlen + 1, scopebuf,
+                              scopelen);
+                       host[numaddrlen] = SCOPE_DELIMITER;
+                       host[numaddrlen + 1 + scopelen] = '\0';
+               }
+       }
+#endif /* NI_WITHSCOPEID */
+
+       return 0;
+}
+
 /* ARGSUSED */
-static char *
-ip6_sa2str(sa6, buf, flags)
+static int
+ip6_sa2str(sa6, buf, bufsiz, flags)
        struct sockaddr_in6 *sa6;
        char *buf;
+       size_t bufsiz;
        int flags;
 {
        unsigned int ifindex = (unsigned int)sa6->sin6_scope_id;
@@ -306,19 +344,20 @@ ip6_sa2str(sa6, buf, flags)
 
 #ifdef notyet
        if (flags & NI_NUMERICSCOPE) {
-               sprintf(buf, "%d", sa6->sin6_scope_id);
-               return(buf);
+               return(snprintf(buf, bufsiz, "%d", sa6->sin6_scope_id));
        }
 #endif
  
-       if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6))
-               return(if_indextoname(ifindex, buf));
-
-       if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
-               return(NULL);   /* XXX */
-       if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
-               return(NULL);   /* XXX */
+       /* if_indextoname() does not take buffer size.  not a good api... */
+       if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
+           bufsiz >= IF_NAMESIZE) {
+               char *p = if_indextoname(ifindex, buf);
+               if (p) {
+                       return(strlen(p));
+               }
+       }
 
-       return(NULL);           /* XXX */
+       /* last resort */
+       return(snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id));
 }
-#endif 
+#endif /* INET6 */