src/libc/net.c

Go to the documentation of this file.
00001 
00008 #include <netinet/in.h>
00009 #include <assert.h>
00010 #include <errno.h>
00011 #include "tm_macros.h"
00012 #include "libc_internal.h"
00013 
00014 #undef  htons
00015 #undef  ntohs
00016 
00017 #define NS_INADDRSZ   4
00018 
00019 
00020 TM_WAIVER unsigned long int strtoul(const char *nptr, char **endptr,  int base);
00021 TM_WAIVER int isspace(int c);
00022 
00023 uint16_t
00024 txc_libc_htons (uint16_t x)
00025 {
00026 #if BYTE_ORDER == BIG_ENDIAN
00027   return x;
00028 #elif BYTE_ORDER == LITTLE_ENDIAN
00029   return __bswap_16 (x);
00030 #else
00031 # error "What kind of system is this?"
00032 #endif
00033 }
00034 
00035 /* 
00036  * Check whether "cp" is a valid ASCII representation
00037  * of an Internet address and convert to a binary address.
00038  * Returns 1 if the address is valid, 0 if not.
00039  * This replaces inet_addr, the return value from which
00040  * cannot distinguish between failure and a local broadcast address.
00041  */
00042 int
00043 txc_libc_inet_aton(const char *cp, struct in_addr *addr)
00044 {
00045         u_long parts[4];
00046         in_addr_t val;
00047         char *c;
00048         char *endptr;
00049         int gotend, n;
00050 
00051         c = (char *)cp;
00052         n = 0;
00053         /*
00054          * Run through the string, grabbing numbers until
00055          * the end of the string, or some error
00056          */
00057         TM_BEGIN 
00058         gotend = 0;
00059         while (!gotend) {
00060                 errno = 0;
00061                 val = strtoul(c, &endptr, 0);
00062 
00063                 if (errno == ERANGE)    /* Fail completely if it overflowed. */
00064                         return (0);
00065                 
00066                 /* 
00067                  * If the whole string is invalid, endptr will equal
00068                  * c.. this way we can make sure someone hasn't
00069                  * gone '.12' or something which would get past
00070                  * the next check.
00071                  */
00072                 if (endptr == c)
00073                         return (0);
00074                 parts[n] = val;
00075                 c = endptr;
00076 
00077                 /* Check the next character past the previous number's end */
00078                 switch (*c) {
00079                 case '.' :
00080                         /* Make sure we only do 3 dots .. */
00081                         if (n == 3)     /* Whoops. Quit. */
00082                                 return (0);
00083                         n++;
00084                         c++;
00085                         break;
00086 
00087                 case '\0':
00088                         gotend = 1;
00089                         break;
00090 
00091                 default:
00092                         if (isspace((unsigned char)*c)) {
00093                                 gotend = 1;
00094                                 break;
00095                         } else
00096                                 return (0);     /* Invalid character, so fail */
00097                 }
00098 
00099         }
00100 
00101         /*
00102          * Concoct the address according to
00103          * the number of parts specified.
00104          */
00105 
00106         switch (n) {
00107         case 0:                         /* a -- 32 bits */
00108                 /*
00109                  * Nothing is necessary here.  Overflow checking was
00110                  * already done in strtoul().
00111                  */
00112                 break;
00113         case 1:                         /* a.b -- 8.24 bits */
00114                 if (val > 0xffffff || parts[0] > 0xff)
00115                         return (0);
00116                 val |= parts[0] << 24;
00117                 break;
00118 
00119         case 2:                         /* a.b.c -- 8.8.16 bits */
00120                 if (val > 0xffff || parts[0] > 0xff || parts[1] > 0xff)
00121                         return (0);
00122                 val |= (parts[0] << 24) | (parts[1] << 16);
00123                 break;
00124 
00125         case 3:                         /* a.b.c.d -- 8.8.8.8 bits */
00126                 if (val > 0xff || parts[0] > 0xff || parts[1] > 0xff ||
00127                     parts[2] > 0xff)
00128                         return (0);
00129                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
00130                 break;
00131         }
00132 
00133         if (addr != NULL)
00134                 addr->s_addr = htonl(val);
00135         return (1);
00136 
00137         TM_END
00138 }
00139 
00140 
00141 TM_WAIVER
00142 static int inet_ntop4_sprintf(char *tmp, const char *fmt, const u_char arg1, const u_char arg2, const u_char arg3, const u_char arg4) {
00143         return sprintf(tmp, fmt, arg1, arg2, arg3, arg4);
00144 }
00145 
00146 
00147 TM_CALLABLE
00148 static const char *
00149 inet_ntop4(const u_char *src, char *dst, socklen_t size) 
00150 {
00151 //  static const char fmt[] = "%u.%u.%u.%u";
00152   char tmp[sizeof "255.255.255.255"];
00153 
00154   TM_BEGIN
00155   //if (inet_ntop4_sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) >= size) {
00156   if (inet_ntop4_sprintf(tmp, "%u.%u.%u.%u", src[0], src[1], src[2], src[3]) >= size) {
00157                 errno = ENOSPC;
00158                 //__set_errno (ENOSPC);
00159     return (NULL);
00160   }
00161   return strcpy(dst, tmp);
00162   TM_END
00163 }
00164 
00165 const char *
00166 txc_libc_inet_ntop(int af, const void *src, char *dst, socklen_t size) 
00167 {
00168   TM_BEGIN
00169   switch (af) {
00170   case AF_INET:
00171     return (inet_ntop4(src, dst, size));
00172   case AF_INET6:
00173                 assert(0);
00174   default:
00175                 errno = EAFNOSUPPORT;
00176     //__set_errno (EAFNOSUPPORT);
00177     return (NULL);
00178   }
00179   TM_END
00180 }
00181 

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7