"Fossies" - the Fresh Open Source Software Archive

Member "udns-0.4/inet_XtoX.c" (5 Jul 2011, 7938 Bytes) of package /linux/misc/dns/udns-0.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "inet_XtoX.c" see the Fossies "Dox" file reference documentation.

    1 /* inet_XtoX.c
    2  * Simple implementation of the following functions:
    3  *  inet_ntop(), inet_ntoa(), inet_pton(), inet_aton().
    4  *
    5  * Differences from traditional implementaitons:
    6  *  o modifies destination buffers even on error return.
    7  *  o no fancy (hex, or 1.2) input support in inet_aton()
    8  *  o inet_aton() does not accept junk after an IP address.
    9  *  o inet_ntop(AF_INET) requires at least 16 bytes in dest,
   10  *    and inet_ntop(AF_INET6) at least 40 bytes
   11  *    (traditional inet_ntop() will try to fit anyway)
   12  *
   13  * Compile with -Dinet_XtoX_prefix=pfx_ to have pfx_*() instead of inet_*()
   14  * Compile with -Dinet_XtoX_no_ntop or -Dinet_XtoX_no_pton
   15  *  to disable net2str or str2net conversions.
   16  *
   17  * #define inet_XtoX_prototypes and #include "this_file.c"
   18  * to get function prototypes only (but not for inet_ntoa()).
   19  * #define inet_XtoX_decl to be `static' for static visibility,
   20  * or use __declspec(dllexport) or somesuch...
   21  *
   22  * Compile with -DTEST to test against stock implementation.
   23  *
   24  * Written by Michael Tokarev.  Public domain.
   25  */
   26 
   27 #ifdef inet_XtoX_prototypes
   28 
   29 struct in_addr;
   30 
   31 #else
   32 
   33 #include <errno.h>
   34 
   35 #ifdef TEST
   36 
   37 # include <netinet/in.h>
   38 # include <sys/socket.h>
   39 # include <arpa/inet.h>
   40 # include <stdio.h>
   41 # include <stdlib.h>
   42 # include <unistd.h>
   43 # include <string.h>
   44 # undef inet_XtoX_prefix
   45 # define inet_XtoX_prefix mjt_inet_
   46 # undef inet_XtoX_no_ntop
   47 # undef inet_XtoX_no_pton
   48 
   49 #else /* !TEST */
   50 
   51 struct in_addr {    /* declare it here to avoid messing with headers */
   52   unsigned char x[4];
   53 };
   54 
   55 #endif /* TEST */
   56 
   57 #endif /* inet_XtoX_prototypes */
   58 
   59 #ifndef inet_XtoX_prefix
   60 # define inet_XtoX_prefix inet_
   61 #endif
   62 #ifndef inet_XtoX_decl
   63 # define inet_XtoX_decl /*empty*/
   64 #endif
   65 
   66 #define cc2_(x,y) cc2__(x,y)
   67 #define cc2__(x,y) x##y
   68 #define fn(x) cc2_(inet_XtoX_prefix,x)
   69 
   70 #ifndef inet_XtoX_no_ntop
   71 
   72 inet_XtoX_decl const char *
   73 fn(ntop)(int af, const void *src, char *dst, unsigned size);
   74 
   75 #ifndef inet_XtoX_prototypes
   76 
   77 static int mjt_ntop4(const void *_src, char *dst, int size) {
   78   unsigned i, x, r;
   79   char *p;
   80   const unsigned char *s = _src;
   81   if (size < 4*4)   /* for simplicity, disallow non-max-size buffer */
   82     return 0;
   83   for (i = 0, p = dst; i < 4; ++i) {
   84     if (i) *p++ = '.';
   85     x = r = s[i];
   86     if (x > 99) { *p++ = (char)(r / 100 + '0'); r %= 100; }
   87     if (x > 9) { *p++ = (char)(r / 10 + '0'); r %= 10; }
   88     *p++ = (char)(r + '0');
   89   }
   90   *p = '\0';
   91   return 1;
   92 }
   93 
   94 static char *hexc(char *p, unsigned x) {
   95   static char hex[16] = "0123456789abcdef";
   96   if (x > 0x0fff) *p++ = hex[(x >>12) & 15];
   97   if (x > 0x00ff) *p++ = hex[(x >> 8) & 15];
   98   if (x > 0x000f) *p++ = hex[(x >> 4) & 15];
   99   *p++ = hex[x & 15];
  100   return p;
  101 }
  102 
  103 static int mjt_ntop6(const void *_src, char *dst, int size) {
  104   unsigned i;
  105   unsigned short w[8];
  106   unsigned bs = 0, cs = 0;
  107   unsigned bl = 0, cl = 0;
  108   char *p;
  109   const unsigned char *s = _src;
  110 
  111   if (size < 40)    /* for simplicity, disallow non-max-size buffer */
  112     return 0;
  113 
  114   for(i = 0; i < 8; ++i, s += 2) {
  115     w[i] = (((unsigned short)(s[0])) << 8) | s[1];
  116     if (!w[i]) {
  117       if (!cl++) cs = i;
  118     }
  119     else {
  120       if (cl > bl) bl = cl, bs = cs;
  121     }
  122   }
  123   if (cl > bl) bl = cl, bs = cs;
  124   p = dst;
  125   if (bl == 1)
  126     bl = 0;
  127   if (bl) {
  128     for(i = 0; i < bs; ++i) {
  129       if (i) *p++ = ':';
  130       p = hexc(p, w[i]);
  131     }
  132     *p++ = ':';
  133     i += bl;
  134     if (i == 8)
  135       *p++ = ':';
  136   }
  137   else
  138     i = 0;
  139   for(; i < 8; ++i) {
  140     if (i) *p++ = ':';
  141     if (i == 6 && !bs && (bl == 6 || (bl == 5 && w[5] == 0xffff)))
  142       return mjt_ntop4(s - 4, p, size - (p - dst));
  143     p = hexc(p, w[i]);
  144   }
  145   *p = '\0';
  146   return 1;
  147 }
  148 
  149 inet_XtoX_decl const char *
  150 fn(ntop)(int af, const void *src, char *dst, unsigned size) {
  151   switch(af) {
  152   /* don't use AF_*: don't mess with headers */
  153   case 2:  /* AF_INET */  if (mjt_ntop4(src, dst, size)) return dst; break;
  154   case 10: /* AF_INET6 */ if (mjt_ntop6(src, dst, size)) return dst; break;
  155   default: errno = EAFNOSUPPORT; return (char*)0;
  156   }
  157   errno = ENOSPC;
  158   return (char*)0;
  159 }
  160 
  161 inet_XtoX_decl const char *
  162 fn(ntoa)(struct in_addr addr) {
  163   static char buf[4*4];
  164   mjt_ntop4(&addr, buf, sizeof(buf));
  165   return buf;
  166 }
  167 
  168 #endif /* inet_XtoX_prototypes */
  169 #endif /* inet_XtoX_no_ntop */
  170 
  171 #ifndef inet_XtoX_no_pton
  172 
  173 inet_XtoX_decl int fn(pton)(int af, const char *src, void *dst);
  174 inet_XtoX_decl int fn(aton)(const char *src, struct in_addr *addr);
  175 
  176 #ifndef inet_XtoX_prototypes
  177 
  178 static int mjt_pton4(const char *c, void *dst) {
  179   unsigned char *a = dst;
  180   unsigned n, o;
  181   for (n = 0; n < 4; ++n) {
  182     if (*c < '0' || *c > '9')
  183       return 0;
  184     o = *c++ - '0';
  185     while(*c >= '0' && *c <= '9')
  186       if ((o = o * 10 + (*c++ - '0')) > 255)
  187         return 0;
  188     if (*c++ != (n == 3 ? '\0' : '.'))
  189       return 0;
  190     *a++ = (unsigned char)o;
  191   }
  192   return 1;
  193 }
  194 
  195 static int mjt_pton6(const char *c, void *dst) {
  196   unsigned short w[8], *a = w, *z, *i;
  197   unsigned v, o;
  198   const char *sc;
  199   unsigned char *d = dst;
  200   if (*c != ':') z = (unsigned short*)0;
  201   else if (*++c != ':') return 0;
  202   else ++c, z = a;
  203   i = 0;
  204   for(;;) {
  205     v = 0;
  206     sc = c;
  207     for(;;) {
  208       if (*c >= '0' && *c <= '9') o = *c - '0';
  209       else if (*c >= 'a' && *c <= 'f') o = *c - 'a' + 10;
  210       else if (*c >= 'A' && *c <= 'F') o = *c - 'A' + 10;
  211       else break;
  212       v = (v << 4) | o;
  213       if (v > 0xffff) return 0;
  214       ++c;
  215     }
  216     if (sc == c) {
  217       if (z == a && !*c)
  218         break;
  219       else
  220         return 0;
  221     }
  222     if (*c == ':') {
  223       if (a >= w + 8)
  224         return 0;
  225       *a++ = v;
  226       if (*++c == ':') {
  227         if (z)
  228           return 0;
  229         z = a;
  230         if (!*++c)
  231           break;
  232       }
  233     }
  234     else if (!*c) {
  235       if (a >= w + 8)
  236         return 0;
  237       *a++ = v;
  238       break;
  239     }
  240     else if (*c == '.') {
  241       if (a > w + 6)
  242         return 0;
  243       if (!mjt_pton4(sc, d))
  244         return 0;
  245       *a++ = ((unsigned)(d[0]) << 8) | d[1];
  246       *a++ = ((unsigned)(d[2]) << 8) | d[3];
  247       break;
  248     }
  249     else
  250       return 0;
  251   }
  252   v = w + 8 - a;
  253   if ((v && !z) || (!v && z))
  254     return 0;
  255   for(i = w; ; ++i) {
  256     if (i == z)
  257       while(v--) { *d++ = '\0'; *d++ = '\0'; }
  258     if (i >= a)
  259       break;
  260     *d++ = (unsigned char)((*i >> 8) & 255);
  261     *d++ = (unsigned char)(*i & 255);
  262   }
  263   return 1;
  264 }
  265 
  266 inet_XtoX_decl int fn(pton)(int af, const char *src, void *dst) {
  267   switch(af) {
  268   /* don't use AF_*: don't mess with headers */
  269   case 2  /* AF_INET  */: return mjt_pton4(src, dst);
  270   case 10 /* AF_INET6 */: return mjt_pton6(src, dst);
  271   default: errno = EAFNOSUPPORT; return -1;
  272   }
  273 }
  274 
  275 inet_XtoX_decl int fn(aton)(const char *src, struct in_addr *addr) {
  276   return mjt_pton4(src, addr);
  277 }
  278 
  279 #endif /* inet_XtoX_prototypes */
  280 
  281 #endif /* inet_XtoX_no_pton */
  282 
  283 #ifdef TEST
  284 
  285 int main(int argc, char **argv) {
  286   int i;
  287   char n0[16], n1[16];
  288   char p0[64], p1[64];
  289   int af = AF_INET;
  290   int pl = sizeof(p0);
  291   int r0, r1;
  292   const char *s0, *s1;
  293 
  294   while((i = getopt(argc, argv, "46a:p:")) != EOF) switch(i) {
  295   case '4': af = AF_INET;  break;
  296   case '6': af = AF_INET6; break;
  297   case 'a': case 'p': pl = atoi(optarg); break;
  298   default: return 1;
  299   }
  300   for(i = optind; i < argc; ++i) {
  301     char *a = argv[i];
  302 
  303     printf("%s:\n", a);
  304     r0 = inet_pton(af, a, n0);
  305     printf(" p2n stock: %s\n",
  306      (r0 < 0 ? "(notsupp)" : !r0 ? "(inval)" : fn(ntop)(af,n0,p0,sizeof(p0))));
  307     r1 = fn(pton)(af, a, n1);
  308     printf(" p2n this : %s\n",
  309      (r1 < 0 ? "(notsupp)" : !r1 ? "(inval)" : fn(ntop)(af,n1,p1,sizeof(p1))));
  310 
  311     if ((r0 > 0) != (r1 > 0) ||
  312         (r0 > 0 && r1 > 0 && memcmp(n0, n1, af == AF_INET ? 4 : 16) != 0))
  313       printf(" DIFFER!\n");
  314 
  315     s0 = inet_ntop(af, n1, p0, pl);
  316     printf(" n2p stock: %s\n", s0 ? s0 : "(inval)");
  317     s1 = fn(ntop)(af, n1, p1, pl);
  318     printf(" n2p this : %s\n", s1 ? s1 : "(inval)");
  319     if ((s0 != 0) != (s1 != 0) ||
  320         (s0 && s1 && strcmp(s0, s1) != 0))
  321       printf(" DIFFER!\n");
  322 
  323   }
  324   return 0;
  325 }
  326 
  327 #endif /* TEST */