LCOV - code coverage report
Current view: top level - src/backend/utils/adt - inet_net_pton.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 77.6 % 312 242
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 7 7
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 65.1 % 238 155

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
       3                 :             :  * Copyright (c) 1996,1999 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 ISC DISCLAIMS ALL WARRANTIES
      10                 :             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      11                 :             :  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
      12                 :             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      13                 :             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      14                 :             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
      15                 :             :  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      16                 :             :  *
      17                 :             :  *        src/backend/utils/adt/inet_net_pton.c
      18                 :             :  */
      19                 :             : 
      20                 :             : #if defined(LIBC_SCCS) && !defined(lint)
      21                 :             : static const char rcsid[] = "Id: inet_net_pton.c,v 1.4.2.3 2004/03/17 00:40:11 marka Exp $";
      22                 :             : #endif
      23                 :             : 
      24                 :             : #include "postgres.h"
      25                 :             : 
      26                 :             : #include <sys/socket.h>
      27                 :             : #include <netinet/in.h>
      28                 :             : #include <arpa/inet.h>
      29                 :             : #include <assert.h>
      30                 :             : #include <ctype.h>
      31                 :             : 
      32                 :             : #include "utils/builtins.h"           /* needed on some platforms */
      33                 :             : #include "utils/inet.h"
      34                 :             : 
      35                 :             : 
      36                 :             : static int      inet_net_pton_ipv4(const char *src, u_char *dst);
      37                 :             : static int      inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size);
      38                 :             : static int      inet_net_pton_ipv6(const char *src, u_char *dst);
      39                 :             : static int      inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size);
      40                 :             : 
      41                 :             : 
      42                 :             : /*
      43                 :             :  * int
      44                 :             :  * pg_inet_net_pton(af, src, dst, size)
      45                 :             :  *      convert network number from presentation to network format.
      46                 :             :  *      accepts hex octets, hex strings, decimal octets, and /CIDR.
      47                 :             :  *      "size" is in bytes and describes "dst".
      48                 :             :  * return:
      49                 :             :  *      number of bits, either imputed classfully or specified with /CIDR,
      50                 :             :  *      or -1 if some failure occurred (check errno).  ENOENT means it was
      51                 :             :  *      not a valid network specification.
      52                 :             :  * author:
      53                 :             :  *      Paul Vixie (ISC), June 1996
      54                 :             :  *
      55                 :             :  * Changes:
      56                 :             :  *      I added the inet_cidr_pton function (also from Paul) and changed
      57                 :             :  *      the names to reflect their current use.
      58                 :             :  *
      59                 :             :  */
      60                 :             : int
      61                 :         609 : pg_inet_net_pton(int af, const char *src, void *dst, size_t size)
      62                 :             : {
      63      [ -  +  + ]:         609 :         switch (af)
      64                 :             :         {
      65                 :             :                 case PGSQL_AF_INET:
      66         [ +  + ]:         451 :                         return size == -1 ?
      67                 :         244 :                                 inet_net_pton_ipv4(src, dst) :
      68                 :         207 :                                 inet_cidr_pton_ipv4(src, dst, size);
      69                 :             :                 case PGSQL_AF_INET6:
      70         [ +  + ]:         158 :                         return size == -1 ?
      71                 :         104 :                                 inet_net_pton_ipv6(src, dst) :
      72                 :          54 :                                 inet_cidr_pton_ipv6(src, dst, size);
      73                 :             :                 default:
      74                 :           0 :                         errno = EAFNOSUPPORT;
      75                 :           0 :                         return -1;
      76                 :             :         }
      77                 :         609 : }
      78                 :             : 
      79                 :             : /*
      80                 :             :  * static int
      81                 :             :  * inet_cidr_pton_ipv4(src, dst, size)
      82                 :             :  *      convert IPv4 network number from presentation to network format.
      83                 :             :  *      accepts hex octets, hex strings, decimal octets, and /CIDR.
      84                 :             :  *      "size" is in bytes and describes "dst".
      85                 :             :  * return:
      86                 :             :  *      number of bits, either imputed classfully or specified with /CIDR,
      87                 :             :  *      or -1 if some failure occurred (check errno).  ENOENT means it was
      88                 :             :  *      not an IPv4 network specification.
      89                 :             :  * note:
      90                 :             :  *      network byte order assumed.  this means 192.5.5.240/28 has
      91                 :             :  *      0b11110000 in its fourth octet.
      92                 :             :  * author:
      93                 :             :  *      Paul Vixie (ISC), June 1996
      94                 :             :  */
      95                 :             : static int
      96                 :         207 : inet_cidr_pton_ipv4(const char *src, u_char *dst, size_t size)
      97                 :             : {
      98                 :             :         static const char xdigits[] = "0123456789abcdef";
      99                 :             :         static const char digits[] = "0123456789";
     100                 :         414 :         int                     n,
     101                 :             :                                 ch,
     102                 :         207 :                                 tmp = 0,
     103                 :             :                                 dirty,
     104                 :             :                                 bits;
     105                 :         207 :         const u_char *odst = dst;
     106                 :             : 
     107                 :         207 :         ch = *src++;
     108   [ +  +  +  - ]:         207 :         if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
     109         [ +  - ]:          40 :                 && isxdigit((unsigned char) src[1]))
     110                 :             :         {
     111                 :             :                 /* Hexadecimal: Eat nybble string. */
     112         [ #  # ]:           0 :                 if (size <= 0U)
     113                 :           0 :                         goto emsgsize;
     114                 :           0 :                 dirty = 0;
     115                 :           0 :                 src++;                                  /* skip x or X. */
     116   [ #  #  #  # ]:           0 :                 while ((ch = *src++) != '\0' && isxdigit((unsigned char) ch))
     117                 :             :                 {
     118                 :           0 :                         ch = pg_ascii_tolower((unsigned char) ch);
     119                 :           0 :                         n = strchr(xdigits, ch) - xdigits;
     120   [ #  #  #  # ]:           0 :                         assert(n >= 0 && n <= 15);
     121         [ #  # ]:           0 :                         if (dirty == 0)
     122                 :           0 :                                 tmp = n;
     123                 :             :                         else
     124                 :           0 :                                 tmp = (tmp << 4) | n;
     125         [ #  # ]:           0 :                         if (++dirty == 2)
     126                 :             :                         {
     127         [ #  # ]:           0 :                                 if (size-- <= 0U)
     128                 :           0 :                                         goto emsgsize;
     129                 :           0 :                                 *dst++ = (u_char) tmp;
     130                 :           0 :                                 dirty = 0;
     131                 :           0 :                         }
     132                 :             :                 }
     133         [ #  # ]:           0 :                 if (dirty)
     134                 :             :                 {                                               /* Odd trailing nybble? */
     135         [ #  # ]:           0 :                         if (size-- <= 0U)
     136                 :           0 :                                 goto emsgsize;
     137                 :           0 :                         *dst++ = (u_char) (tmp << 4);
     138                 :           0 :                 }
     139                 :           0 :         }
     140         [ -  + ]:         207 :         else if (isdigit((unsigned char) ch))
     141                 :             :         {
     142                 :             :                 /* Decimal: eat dotted digit string. */
     143                 :         693 :                 for (;;)
     144                 :             :                 {
     145                 :         693 :                         tmp = 0;
     146                 :         693 :                         do
     147                 :             :                         {
     148                 :        1296 :                                 n = strchr(digits, ch) - digits;
     149   [ -  +  -  + ]:        1296 :                                 assert(n >= 0 && n <= 9);
     150                 :        1296 :                                 tmp *= 10;
     151                 :        1296 :                                 tmp += n;
     152         [ +  + ]:        1296 :                                 if (tmp > 255)
     153                 :           2 :                                         goto enoent;
     154   [ +  +  +  + ]:        1294 :                         } while ((ch = *src++) != '\0' &&
     155                 :        1216 :                                          isdigit((unsigned char) ch));
     156         [ +  - ]:         691 :                         if (size-- <= 0U)
     157                 :           0 :                                 goto emsgsize;
     158                 :         691 :                         *dst++ = (u_char) tmp;
     159   [ +  +  +  + ]:         691 :                         if (ch == '\0' || ch == '/')
     160                 :         205 :                                 break;
     161         [ -  + ]:         486 :                         if (ch != '.')
     162                 :           0 :                                 goto enoent;
     163                 :         486 :                         ch = *src++;
     164         [ +  - ]:         486 :                         if (!isdigit((unsigned char) ch))
     165                 :           0 :                                 goto enoent;
     166                 :             :                 }
     167                 :         205 :         }
     168                 :             :         else
     169                 :           0 :                 goto enoent;
     170                 :             : 
     171                 :         205 :         bits = -1;
     172   [ +  +  +  -  :         205 :         if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
                   -  + ]
     173                 :             :         {
     174                 :             :                 /* CIDR width specifier.  Nothing can follow it. */
     175                 :         127 :                 ch = *src++;                    /* Skip over the /. */
     176                 :         127 :                 bits = 0;
     177                 :         127 :                 do
     178                 :             :                 {
     179                 :         221 :                         n = strchr(digits, ch) - digits;
     180   [ -  +  +  - ]:         221 :                         assert(n >= 0 && n <= 9);
     181                 :         221 :                         bits *= 10;
     182                 :         221 :                         bits += n;
     183   [ +  +  +  + ]:         221 :                 } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
     184         [ -  + ]:         127 :                 if (ch != '\0')
     185                 :           0 :                         goto enoent;
     186         [ -  + ]:         127 :                 if (bits > 32)
     187                 :           0 :                         goto emsgsize;
     188                 :         127 :         }
     189                 :             : 
     190                 :             :         /* Fiery death and destruction unless we prefetched EOS. */
     191         [ -  + ]:         205 :         if (ch != '\0')
     192                 :           0 :                 goto enoent;
     193                 :             : 
     194                 :             :         /* If nothing was written to the destination, we found no address. */
     195         [ +  - ]:         205 :         if (dst == odst)
     196                 :           0 :                 goto enoent;
     197                 :             :         /* If no CIDR spec was given, infer width from net class. */
     198         [ +  + ]:         205 :         if (bits == -1)
     199                 :             :         {
     200         [ +  + ]:          78 :                 if (*odst >= 240)            /* Class E */
     201                 :          32 :                         bits = 32;
     202         [ -  + ]:          46 :                 else if (*odst >= 224)       /* Class D */
     203                 :           0 :                         bits = 8;
     204         [ +  + ]:          46 :                 else if (*odst >= 192)       /* Class C */
     205                 :           5 :                         bits = 24;
     206         [ -  + ]:          41 :                 else if (*odst >= 128)       /* Class B */
     207                 :           0 :                         bits = 16;
     208                 :             :                 else
     209                 :             :                         /* Class A */
     210                 :          41 :                         bits = 8;
     211                 :             :                 /* If imputed mask is narrower than specified octets, widen. */
     212         [ +  + ]:          78 :                 if (bits < ((dst - odst) * 8))
     213                 :          36 :                         bits = (dst - odst) * 8;
     214                 :             : 
     215                 :             :                 /*
     216                 :             :                  * If there are no additional bits specified for a class D address
     217                 :             :                  * adjust bits to 4.
     218                 :             :                  */
     219   [ +  +  +  - ]:          78 :                 if (bits == 8 && *odst == 224)
     220                 :           0 :                         bits = 4;
     221                 :          78 :         }
     222                 :             :         /* Extend network to cover the actual mask. */
     223         [ +  + ]:         213 :         while (bits > ((dst - odst) * 8))
     224                 :             :         {
     225         [ -  + ]:           8 :                 if (size-- <= 0U)
     226                 :           0 :                         goto emsgsize;
     227                 :           8 :                 *dst++ = '\0';
     228                 :             :         }
     229                 :         205 :         return bits;
     230                 :             : 
     231                 :             : enoent:
     232                 :           2 :         errno = ENOENT;
     233                 :           2 :         return -1;
     234                 :             : 
     235                 :             : emsgsize:
     236                 :           0 :         errno = EMSGSIZE;
     237                 :           0 :         return -1;
     238                 :         207 : }
     239                 :             : 
     240                 :             : /*
     241                 :             :  * int
     242                 :             :  * inet_net_pton_ipv4(af, src, dst, *bits)
     243                 :             :  *      convert network address from presentation to network format.
     244                 :             :  *      accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
     245                 :             :  *      "dst" is assumed large enough for its "af".  "bits" is set to the
     246                 :             :  *      /CIDR prefix length, which can have defaults (like /32 for IPv4).
     247                 :             :  * return:
     248                 :             :  *      -1 if an error occurred (inspect errno; ENOENT means bad format).
     249                 :             :  *      0 if successful conversion occurred.
     250                 :             :  * note:
     251                 :             :  *      192.5.5.1/28 has a nonzero host part, which means it isn't a network
     252                 :             :  *      as called for by inet_cidr_pton() but it can be a host address with
     253                 :             :  *      an included netmask.
     254                 :             :  * author:
     255                 :             :  *      Paul Vixie (ISC), October 1998
     256                 :             :  */
     257                 :             : static int
     258                 :         244 : inet_net_pton_ipv4(const char *src, u_char *dst)
     259                 :             : {
     260                 :             :         static const char digits[] = "0123456789";
     261                 :         244 :         const u_char *odst = dst;
     262                 :         244 :         int                     n,
     263                 :             :                                 ch,
     264                 :             :                                 tmp,
     265                 :             :                                 bits;
     266                 :         244 :         size_t          size = 4;
     267                 :             : 
     268                 :             :         /* Get the mantissa. */
     269         [ -  + ]:         910 :         while (ch = *src++, isdigit((unsigned char) ch))
     270                 :             :         {
     271                 :         910 :                 tmp = 0;
     272                 :         910 :                 do
     273                 :             :                 {
     274                 :        1799 :                         n = strchr(digits, ch) - digits;
     275   [ -  +  +  - ]:        1799 :                         assert(n >= 0 && n <= 9);
     276                 :        1799 :                         tmp *= 10;
     277                 :        1799 :                         tmp += n;
     278         [ +  + ]:        1799 :                         if (tmp > 255)
     279                 :           2 :                                 goto enoent;
     280   [ +  +  +  + ]:        1797 :                 } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
     281         [ +  - ]:         908 :                 if (size-- == 0)
     282                 :           0 :                         goto emsgsize;
     283                 :         908 :                 *dst++ = (u_char) tmp;
     284   [ +  +  +  + ]:         908 :                 if (ch == '\0' || ch == '/')
     285                 :         242 :                         break;
     286         [ +  - ]:         666 :                 if (ch != '.')
     287                 :           0 :                         goto enoent;
     288                 :             :         }
     289                 :             : 
     290                 :             :         /* Get the prefix length if any. */
     291                 :         242 :         bits = -1;
     292   [ +  +  +  -  :         242 :         if (ch == '/' && isdigit((unsigned char) src[0]) && dst > odst)
                   -  + ]
     293                 :             :         {
     294                 :             :                 /* CIDR width specifier.  Nothing can follow it. */
     295                 :         165 :                 ch = *src++;                    /* Skip over the /. */
     296                 :         165 :                 bits = 0;
     297                 :         165 :                 do
     298                 :             :                 {
     299                 :         265 :                         n = strchr(digits, ch) - digits;
     300   [ -  +  +  - ]:         265 :                         assert(n >= 0 && n <= 9);
     301                 :         265 :                         bits *= 10;
     302                 :         265 :                         bits += n;
     303   [ +  +  +  + ]:         265 :                 } while ((ch = *src++) != '\0' && isdigit((unsigned char) ch));
     304         [ -  + ]:         165 :                 if (ch != '\0')
     305                 :           0 :                         goto enoent;
     306         [ -  + ]:         165 :                 if (bits > 32)
     307                 :           0 :                         goto emsgsize;
     308                 :         165 :         }
     309                 :             : 
     310                 :             :         /* Fiery death and destruction unless we prefetched EOS. */
     311         [ -  + ]:         242 :         if (ch != '\0')
     312                 :           0 :                 goto enoent;
     313                 :             : 
     314                 :             :         /* Prefix length can default to /32 only if all four octets spec'd. */
     315         [ +  + ]:         242 :         if (bits == -1)
     316                 :             :         {
     317         [ +  - ]:          77 :                 if (dst - odst == 4)
     318                 :          77 :                         bits = 32;
     319                 :             :                 else
     320                 :           0 :                         goto enoent;
     321                 :          77 :         }
     322                 :             : 
     323                 :             :         /* If nothing was written to the destination, we found no address. */
     324         [ -  + ]:         242 :         if (dst == odst)
     325                 :           0 :                 goto enoent;
     326                 :             : 
     327                 :             :         /* If prefix length overspecifies mantissa, life is bad. */
     328         [ -  + ]:         242 :         if ((bits / 8) > (dst - odst))
     329                 :           0 :                 goto enoent;
     330                 :             : 
     331                 :             :         /* Extend address to four octets. */
     332         [ +  + ]:         302 :         while (size-- > 0)
     333                 :          60 :                 *dst++ = 0;
     334                 :             : 
     335                 :         242 :         return bits;
     336                 :             : 
     337                 :             : enoent:
     338                 :           2 :         errno = ENOENT;
     339                 :           2 :         return -1;
     340                 :             : 
     341                 :             : emsgsize:
     342                 :           0 :         errno = EMSGSIZE;
     343                 :           0 :         return -1;
     344                 :         244 : }
     345                 :             : 
     346                 :             : static int
     347                 :          88 : getbits(const char *src, int *bitsp)
     348                 :             : {
     349                 :             :         static const char digits[] = "0123456789";
     350                 :          88 :         int                     n;
     351                 :          88 :         int                     val;
     352                 :          88 :         char            ch;
     353                 :             : 
     354                 :          88 :         val = 0;
     355                 :          88 :         n = 0;
     356         [ +  + ]:         270 :         while ((ch = *src++) != '\0')
     357                 :             :         {
     358                 :         182 :                 const char *pch;
     359                 :             : 
     360                 :         182 :                 pch = strchr(digits, ch);
     361         [ +  - ]:         182 :                 if (pch != NULL)
     362                 :             :                 {
     363   [ +  +  +  - ]:         182 :                         if (n++ != 0 && val == 0)       /* no leading zeros */
     364                 :           0 :                                 return 0;
     365                 :         182 :                         val *= 10;
     366                 :         182 :                         val += (pch - digits);
     367         [ -  + ]:         182 :                         if (val > 128)               /* range */
     368                 :           0 :                                 return 0;
     369                 :         182 :                         continue;
     370                 :             :                 }
     371                 :           0 :                 return 0;
     372         [ +  - ]:         182 :         }
     373         [ +  - ]:          88 :         if (n == 0)
     374                 :           0 :                 return 0;
     375                 :          88 :         *bitsp = val;
     376                 :          88 :         return 1;
     377                 :          88 : }
     378                 :             : 
     379                 :             : static int
     380                 :           6 : getv4(const char *src, u_char *dst, int *bitsp)
     381                 :             : {
     382                 :             :         static const char digits[] = "0123456789";
     383                 :           6 :         u_char     *odst = dst;
     384                 :           6 :         int                     n;
     385                 :           6 :         u_int           val;
     386                 :           6 :         char            ch;
     387                 :             : 
     388                 :           6 :         val = 0;
     389                 :           6 :         n = 0;
     390         [ +  + ]:          48 :         while ((ch = *src++) != '\0')
     391                 :             :         {
     392                 :          47 :                 const char *pch;
     393                 :             : 
     394                 :          47 :                 pch = strchr(digits, ch);
     395         [ +  + ]:          47 :                 if (pch != NULL)
     396                 :             :                 {
     397   [ -  +  #  # ]:          24 :                         if (n++ != 0 && val == 0)       /* no leading zeros */
     398                 :           0 :                                 return 0;
     399                 :          24 :                         val *= 10;
     400                 :          24 :                         val += (pch - digits);
     401         [ -  + ]:          24 :                         if (val > 255)               /* range */
     402                 :           0 :                                 return 0;
     403                 :          24 :                         continue;
     404                 :             :                 }
     405   [ +  +  +  - ]:          23 :                 if (ch == '.' || ch == '/')
     406                 :             :                 {
     407         [ -  + ]:          23 :                         if (dst - odst > 3) /* too many octets? */
     408                 :           0 :                                 return 0;
     409                 :          23 :                         *dst++ = val;
     410         [ +  + ]:          23 :                         if (ch == '/')
     411                 :           5 :                                 return getbits(src, bitsp);
     412                 :          18 :                         val = 0;
     413                 :          18 :                         n = 0;
     414                 :          18 :                         continue;
     415                 :             :                 }
     416                 :           0 :                 return 0;
     417         [ +  + ]:          47 :         }
     418         [ +  - ]:           1 :         if (n == 0)
     419                 :           0 :                 return 0;
     420         [ -  + ]:           1 :         if (dst - odst > 3)                  /* too many octets? */
     421                 :           0 :                 return 0;
     422                 :           1 :         *dst++ = val;
     423                 :           1 :         return 1;
     424                 :           6 : }
     425                 :             : 
     426                 :             : static int
     427                 :         104 : inet_net_pton_ipv6(const char *src, u_char *dst)
     428                 :             : {
     429                 :         104 :         return inet_cidr_pton_ipv6(src, dst, 16);
     430                 :             : }
     431                 :             : 
     432                 :             : #define NS_IN6ADDRSZ 16
     433                 :             : #define NS_INT16SZ 2
     434                 :             : #define NS_INADDRSZ 4
     435                 :             : 
     436                 :             : static int
     437                 :         158 : inet_cidr_pton_ipv6(const char *src, u_char *dst, size_t size)
     438                 :             : {
     439                 :             :         static const char xdigits_l[] = "0123456789abcdef",
     440                 :             :                                 xdigits_u[] = "0123456789ABCDEF";
     441                 :         158 :         u_char          tmp[NS_IN6ADDRSZ],
     442                 :             :                            *tp,
     443                 :             :                            *endp,
     444                 :             :                            *colonp;
     445                 :         158 :         const char *xdigits,
     446                 :             :                            *curtok;
     447                 :         158 :         int                     ch,
     448                 :             :                                 saw_xdigit;
     449                 :         158 :         u_int           val;
     450                 :         158 :         int                     digits;
     451                 :         158 :         int                     bits;
     452                 :             : 
     453         [ -  + ]:         158 :         if (size < NS_IN6ADDRSZ)
     454                 :           0 :                 goto emsgsize;
     455                 :             : 
     456                 :         158 :         memset((tp = tmp), '\0', NS_IN6ADDRSZ);
     457                 :         158 :         endp = tp + NS_IN6ADDRSZ;
     458                 :         158 :         colonp = NULL;
     459                 :             :         /* Leading :: requires some special handling. */
     460         [ +  + ]:         158 :         if (*src == ':')
     461         [ -  + ]:          11 :                 if (*++src != ':')
     462                 :           0 :                         goto enoent;
     463                 :         158 :         curtok = src;
     464                 :         158 :         saw_xdigit = 0;
     465                 :         158 :         val = 0;
     466                 :         158 :         digits = 0;
     467                 :         158 :         bits = -1;
     468         [ +  + ]:        3463 :         while ((ch = *src++) != '\0')
     469                 :             :         {
     470                 :        3306 :                 const char *pch;
     471                 :             : 
     472         [ +  + ]:        3306 :                 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
     473                 :         788 :                         pch = strchr((xdigits = xdigits_u), ch);
     474         [ +  + ]:        3306 :                 if (pch != NULL)
     475                 :             :                 {
     476                 :        2518 :                         val <<= 4;
     477                 :        2518 :                         val |= (pch - xdigits);
     478         [ -  + ]:        2518 :                         if (++digits > 4)
     479                 :           0 :                                 goto enoent;
     480                 :        2518 :                         saw_xdigit = 1;
     481                 :        2518 :                         continue;
     482                 :             :                 }
     483         [ +  + ]:         788 :                 if (ch == ':')
     484                 :             :                 {
     485                 :         699 :                         curtok = src;
     486         [ +  + ]:         699 :                         if (!saw_xdigit)
     487                 :             :                         {
     488         [ +  + ]:         129 :                                 if (colonp)
     489                 :           1 :                                         goto enoent;
     490                 :         128 :                                 colonp = tp;
     491                 :         128 :                                 continue;
     492                 :             :                         }
     493         [ +  - ]:         570 :                         else if (*src == '\0')
     494                 :           0 :                                 goto enoent;
     495         [ -  + ]:         570 :                         if (tp + NS_INT16SZ > endp)
     496                 :           0 :                                 goto enoent;
     497                 :         570 :                         *tp++ = (u_char) (val >> 8) & 0xff;
     498                 :         570 :                         *tp++ = (u_char) val & 0xff;
     499                 :         570 :                         saw_xdigit = 0;
     500                 :         570 :                         digits = 0;
     501                 :         570 :                         val = 0;
     502                 :         570 :                         continue;
     503                 :             :                 }
     504   [ +  +  +  -  :          89 :                 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
                   -  + ]
     505                 :           6 :                         getv4(curtok, tp, &bits) > 0)
     506                 :             :                 {
     507                 :           6 :                         tp += NS_INADDRSZ;
     508                 :           6 :                         saw_xdigit = 0;
     509                 :           6 :                         break;                          /* '\0' was seen by inet_pton4(). */
     510                 :             :                 }
     511   [ +  -  -  + ]:          83 :                 if (ch == '/' && getbits(src, &bits) > 0)
     512                 :          83 :                         break;
     513                 :           0 :                 goto enoent;
     514      [ +  -  + ]:        3306 :         }
     515         [ +  + ]:         157 :         if (saw_xdigit)
     516                 :             :         {
     517         [ -  + ]:         131 :                 if (tp + NS_INT16SZ > endp)
     518                 :           0 :                         goto enoent;
     519                 :         131 :                 *tp++ = (u_char) (val >> 8) & 0xff;
     520                 :         131 :                 *tp++ = (u_char) val & 0xff;
     521                 :         131 :         }
     522         [ +  + ]:         157 :         if (bits == -1)
     523                 :          69 :                 bits = 128;
     524                 :             : 
     525                 :         157 :         endp = tmp + 16;
     526                 :             : 
     527         [ +  + ]:         157 :         if (colonp != NULL)
     528                 :             :         {
     529                 :             :                 /*
     530                 :             :                  * Since some memmove()'s erroneously fail to handle overlapping
     531                 :             :                  * regions, we'll do the shift by hand.
     532                 :             :                  */
     533                 :         127 :                 const int       n = tp - colonp;
     534                 :         127 :                 int                     i;
     535                 :             : 
     536         [ +  - ]:         127 :                 if (tp == endp)
     537                 :           0 :                         goto enoent;
     538         [ +  + ]:         789 :                 for (i = 1; i <= n; i++)
     539                 :             :                 {
     540                 :         662 :                         endp[-i] = colonp[n - i];
     541                 :         662 :                         colonp[n - i] = 0;
     542                 :         662 :                 }
     543                 :         127 :                 tp = endp;
     544         [ -  + ]:         127 :         }
     545         [ -  + ]:         157 :         if (tp != endp)
     546                 :           0 :                 goto enoent;
     547                 :             : 
     548                 :             :         /*
     549                 :             :          * Copy out the result.
     550                 :             :          */
     551                 :         157 :         memcpy(dst, tmp, NS_IN6ADDRSZ);
     552                 :             : 
     553                 :         157 :         return bits;
     554                 :             : 
     555                 :             : enoent:
     556                 :           1 :         errno = ENOENT;
     557                 :           1 :         return -1;
     558                 :             : 
     559                 :             : emsgsize:
     560                 :           0 :         errno = EMSGSIZE;
     561                 :           0 :         return -1;
     562                 :         158 : }
        

Generated by: LCOV version 2.3.2-1