본문 바로가기

MS/tip

custom inet_pton


inet_pton이 Windows server 2008부터, Windows vista부터 지원한다는 걸 뒤늦게 알고 엄청 삽질 했다.

ipv6를 미리미리 염두하지 않고 xp update를 종료한 ms에게 심심한 뻐큐를 날려본다.



 

017: #define NS_INT16SZ       2
018: #define NS_INADDRSZ      4
019: #define NS_IN6ADDRSZ    16
020: 
021: static int inet_pton4( const char *src, unsigned char *dst )
022: {
023:   static const char digits[] = "0123456789";
024:   int saw_digit, octets, ch;
025:   unsigned char tmp[NS_INADDRSZ], *tp;
026: 
027:   saw_digit = 0;
028:   octets = 0;
029:   *(tp = tmp) = 0;
030:   while( (ch = *src++) != '\0' )
031:   {
032:     const char *pch;
033: 
034:     if( (pch = strchr(digits, ch)) != NULL )
035:     {
036:       unsigned int iNew = (unsigned int)(*tp * 10 + (pch - digits));
037: 
038:       if( iNew > 255 ) return (0);
039:       *tp = iNew;
040:       if( !saw_digit )
041:       {
042:         if( ++octets > 4 ) return (0);
043:         saw_digit = 1;
044:       }
045:     }
046:     else if( ch == '.' && saw_digit )
047:     {
048:       if( octets == 4 ) return (0);
049:       *++tp = 0;
050:       saw_digit = 0;
051:     }
052:     else
053:     {
054:       return (0);
055:     }
056:   }
057: 
058:   if( octets < 4 ) return (0);
059: 
060:   memcpy( dst, tmp, NS_INADDRSZ );
061: 
062:   return (1);
063: }
064: 
065: static int inet_pton6( const char *src, unsigned char * dst )
066: {
067:   static const char xdigits_l[] = "0123456789abcdef",
068:                     xdigits_u[] = "0123456789ABCDEF";
069:   unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
070:   const char *xdigits, *curtok;
071:   int ch, saw_xdigit;
072:   unsigned int val;
073: 
074:   memset((tp = tmp), '\0', NS_IN6ADDRSZ);
075:   endp = tp + NS_IN6ADDRSZ;
076:   colonp = NULL;
077: 
078:   // Leading :: requires some special handling.
079:   if( *src == ':' && *++src != ':' ) return (0);
080: 
081:   curtok = src;
082:   saw_xdigit = 0;
083:   val = 0;
084:   while( ( ch = *src++ ) != '\0' )
085:   {
086:     const char *pch;
087: 
088:     if( ( pch = strchr( ( xdigits = xdigits_l ), ch ) ) == NULL )
089:       pch = strchr( (xdigits = xdigits_u), ch );
090: 
091:     if( pch != NULL )
092:     {
093:       val <<= 4;
094:       val |= (pch - xdigits);
095:       if( val > 0xffff ) return (0);
096:       saw_xdigit = 1;
097:       continue;
098:     }
099: 
100:     if( ch == ':' )
101:     {
102:       curtok = src;
103:       if( !saw_xdigit )
104:       {
105:         if( colonp ) return (0);
106:         colonp = tp;
107:         continue;
108:       }
109: 
110:       if( tp + NS_INT16SZ > endp ) return (0);
111: 
112:       *tp++ = (unsigned char) (val >> 8) & 0xff;
113:       *tp++ = (unsigned char) val & 0xff;
114:       saw_xdigit = 0;
115:       val = 0;
116:       continue;
117:     }
118: 
119:     if( ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0 )
120:     {
121:       tp += NS_INADDRSZ;
122:       saw_xdigit = 0;
123:       break;  /* '\0' was seen by inet_pton4(). */
124:     }
125:     return (0);
126:   }
127: 
128:   if( saw_xdigit )
129:   {
130:     if( tp + NS_INT16SZ > endp ) return (0);
131: 
132:     *tp++ = (unsigned char) (val >> 8) & 0xff;
133:     *tp++ = (unsigned char) val & 0xff;
134:   }
135: 
136:   if( colonp != NULL )
137:   {
138:     // Since some memmove()'s erroneously fail to handle overlapping regions, we'll do the shift by hand.
139:     const int n = (int)(tp - colonp);
140:     int i;
141: 
142:     for( i = 1; i <= n; i++ )
143:     {
144:       endp[- i] = colonp[- i];
145:       colonp[- i] = 0;
146:     }
147:     tp = endp;
148:   }
149: 
150:   if( tp != endp ) return (0);
151:   
152:   memcpy(dst, tmp, NS_IN6ADDRSZ);
153:   return (1);
154: }
155: 
156: int inet_pton( int af, const char *src, void *dst )
157: {
158:   switch (af)
159:   {
160:   case AF_INET:
161:     return inet_pton4( src, (unsigned char *)dst );
162:   case AF_INET6:
163:     return inet_pton6( src, (unsigned char *)dst );
164:   default:
165:     errno = EAFNOSUPPORT;
166:     return (-1);
167:   }
168: }

[참고자료] http://samba.anu.edu.au/rsync/doxygen/head/inet__pton_8c-source.html