LCOV - code coverage report
Current view: top level - netinet - inet_ntop.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 91 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 4 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: inet_ntop.c,v 1.4 2016/09/04 17:05:24 claudio Exp $   */
       2             : 
       3             : /* Copyright (c) 1996 by Internet Software Consortium.
       4             :  *
       5             :  * Permission to use, copy, modify, and distribute this software for any
       6             :  * purpose with or without fee is hereby granted, provided that the above
       7             :  * copyright notice and this permission notice appear in all copies.
       8             :  *
       9             :  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
      10             :  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
      11             :  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
      12             :  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
      13             :  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
      14             :  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
      15             :  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
      16             :  * SOFTWARE.
      17             :  */
      18             : 
      19             : #include <sys/param.h>
      20             : #include <sys/systm.h>
      21             : #include <sys/socket.h>
      22             : 
      23             : #include <netinet/in.h>
      24             : 
      25             : #define IN6ADDRSZ       16
      26             : #define INT16SZ         2
      27             : 
      28             : /*
      29             :  * WARNING: Don't even consider trying to compile this on a system where
      30             :  * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
      31             :  */
      32             : 
      33             : static const char *inet_ntop4(const u_char *src, char *dst, size_t size);
      34             : #ifdef INET6
      35             : static const char *inet_ntop6(const u_char *src, char *dst, size_t size);
      36             : #endif /* INET6 */
      37             : 
      38             : /* char *
      39             :  * inet_ntop(af, src, dst, size)
      40             :  *      convert a network format address to presentation format.
      41             :  * return:
      42             :  *      pointer to presentation format address (`dst'), or NULL (see errno).
      43             :  * author:
      44             :  *      Paul Vixie, 1996.
      45             :  */
      46             : const char *
      47           0 : inet_ntop(int af, const void *src, char *dst, socklen_t size)
      48             : {
      49           0 :         switch (af) {
      50             :         case AF_INET:
      51           0 :                 return (inet_ntop4(src, dst, (size_t)size));
      52             : #ifdef INET6
      53             :         case AF_INET6:
      54           0 :                 return (inet_ntop6(src, dst, (size_t)size));
      55             : #endif /* INET6 */
      56             :         default:
      57           0 :                 return (NULL);
      58             :         }
      59             :         /* NOTREACHED */
      60           0 : }
      61             : 
      62             : const char *
      63           0 : sockaddr_ntop(struct sockaddr *sa, char *dst, size_t size)
      64             : {
      65             :         u_int8_t l;
      66             :         size_t n;
      67             : 
      68           0 :         if (sa->sa_len < 2)
      69           0 :                 return "bad sa";
      70           0 :         switch (sa->sa_family) {
      71             :         case AF_INET:
      72           0 :                 return inet_ntop4((u_char *)&satosin(sa)->sin_addr, dst, size);
      73             : #ifdef INET6
      74             :         case AF_INET6:
      75           0 :                 return inet_ntop6((u_char *)&satosin6(sa)->sin6_addr, dst, size);
      76             : #endif
      77             :         default:
      78           0 :                 n = snprintf(dst, size, "%d ", sa->sa_family);
      79           0 :                 for (l = 0; l < sa->sa_len - offsetof(struct sockaddr, sa_data); l++) {
      80           0 :                         int r = snprintf(dst + n, size - n, "%02x", sa->sa_data[l]);
      81           0 :                         if (r == -1)
      82           0 :                                 return "bad sa";
      83           0 :                         n += r;
      84           0 :                         if (n > size)
      85           0 :                                 n = size;
      86           0 :                 }
      87           0 :                 return (dst);
      88             :         }
      89           0 : }
      90             : 
      91             : /* const char *
      92             :  * inet_ntop4(src, dst, size)
      93             :  *      format an IPv4 address, more or less like inet_ntoa()
      94             :  * return:
      95             :  *      `dst' (as a const)
      96             :  * notes:
      97             :  *      (1) uses no statics
      98             :  *      (2) takes a u_char* not an in_addr as input
      99             :  * author:
     100             :  *      Paul Vixie, 1996.
     101             :  */
     102             : static const char *
     103           0 : inet_ntop4(const u_char *src, char *dst, size_t size)
     104             : {
     105           0 :         char tmp[sizeof "255.255.255.255"];
     106             :         int l;
     107             : 
     108           0 :         l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u",
     109           0 :             src[0], src[1], src[2], src[3]);
     110           0 :         if (l <= 0 || l >= size) {
     111           0 :                 return (NULL);
     112             :         }
     113           0 :         strlcpy(dst, tmp, size);
     114           0 :         return (dst);
     115           0 : }
     116             : 
     117             : #ifdef INET6
     118             : /* const char *
     119             :  * inet_ntop6(src, dst, size)
     120             :  *      convert IPv6 binary address into presentation (printable) format
     121             :  * author:
     122             :  *      Paul Vixie, 1996.
     123             :  */
     124             : static const char *
     125           0 : inet_ntop6(const u_char *src, char *dst, size_t size)
     126             : {
     127             :         /*
     128             :          * Note that int32_t and int16_t need only be "at least" large enough
     129             :          * to contain a value of the specified size.  On some systems, like
     130             :          * Crays, there is no such thing as an integer variable with 16 bits.
     131             :          * Keep this in mind if you think this function should have been coded
     132             :          * to use pointer overlays.  All the world's not a VAX.
     133             :          */
     134           0 :         char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
     135             :         char *tp, *ep;
     136             :         struct { int base, len; } best, cur;
     137           0 :         u_int words[IN6ADDRSZ / INT16SZ];
     138             :         int i;
     139             :         int advance;
     140             : 
     141             :         /*
     142             :          * Preprocess:
     143             :          *      Copy the input (bytewise) array into a wordwise array.
     144             :          *      Find the longest run of 0x00's in src[] for :: shorthanding.
     145             :          */
     146           0 :         memset(words, '\0', sizeof words);
     147           0 :         for (i = 0; i < IN6ADDRSZ; i++)
     148           0 :                 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
     149             :         best.base = -1;
     150             :         cur.base = -1;
     151           0 :         for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
     152           0 :                 if (words[i] == 0) {
     153           0 :                         if (cur.base == -1)
     154           0 :                                 cur.base = i, cur.len = 1;
     155             :                         else
     156           0 :                                 cur.len++;
     157             :                 } else {
     158           0 :                         if (cur.base != -1) {
     159           0 :                                 if (best.base == -1 || cur.len > best.len)
     160           0 :                                         best = cur;
     161             :                                 cur.base = -1;
     162           0 :                         }
     163             :                 }
     164             :         }
     165           0 :         if (cur.base != -1) {
     166           0 :                 if (best.base == -1 || cur.len > best.len)
     167           0 :                         best = cur;
     168             :         }
     169           0 :         if (best.base != -1 && best.len < 2)
     170           0 :                 best.base = -1;
     171             : 
     172             :         /*
     173             :          * Format the result.
     174             :          */
     175           0 :         tp = tmp;
     176           0 :         ep = tmp + sizeof(tmp);
     177           0 :         for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
     178             :                 /* Are we inside the best run of 0x00's? */
     179           0 :                 if (best.base != -1 && i >= best.base &&
     180           0 :                     i < (best.base + best.len)) {
     181           0 :                         if (i == best.base) {
     182           0 :                                 if (tp + 1 >= ep)
     183           0 :                                         return (NULL);
     184           0 :                                 *tp++ = ':';
     185           0 :                         }
     186             :                         continue;
     187             :                 }
     188             :                 /* Are we following an initial run of 0x00s or any real hex? */
     189           0 :                 if (i != 0) {
     190           0 :                         if (tp + 1 >= ep)
     191           0 :                                 return (NULL);
     192           0 :                         *tp++ = ':';
     193           0 :                 }
     194             :                 /* Is this address an encapsulated IPv4? */
     195           0 :                 if (i == 6 && best.base == 0 &&
     196           0 :                     (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
     197           0 :                         if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
     198           0 :                                 return (NULL);
     199           0 :                         tp += strlen(tp);
     200           0 :                         break;
     201             :                 }
     202           0 :                 advance = snprintf(tp, ep - tp, "%x", words[i]);
     203           0 :                 if (advance <= 0 || advance >= ep - tp)
     204           0 :                         return (NULL);
     205           0 :                 tp += advance;
     206           0 :         }
     207             :         /* Was it a trailing run of 0x00's? */
     208           0 :         if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) {
     209           0 :                 if (tp + 1 >= ep)
     210           0 :                         return (NULL);
     211           0 :                 *tp++ = ':';
     212           0 :         }
     213           0 :         if (tp + 1 >= ep)
     214           0 :                 return (NULL);
     215           0 :         *tp++ = '\0';
     216             : 
     217             :         /*
     218             :          * Check for overflow, copy, and we're done.
     219             :          */
     220           0 :         if ((size_t)(tp - tmp) > size) {
     221           0 :                 return (NULL);
     222             :         }
     223           0 :         strlcpy(dst, tmp, size);
     224           0 :         return (dst);
     225           0 : }
     226             : #endif /* INET6 */

Generated by: LCOV version 1.13