00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00027 #include "event_int.h"
00028
00029 #include <string.h>
00030
00031 RCSTAG("@(#)$Id: sockaddr_ptoa.c,v 1.2 2005/12/18 00:15:11 klmitch Exp $");
00032
00040 #define VALMASK 0x0f
00041
00050 #define DIGIT 0x10
00051
00060 #define XDIGIT 0x20
00061
00069 #define COLON 0x30
00070
00079 #define PERIOD 0x40
00080
00087 #define TYPEMASK 0xf0
00088
00103 #define ctype(c) (cmap[(int)(c)] & TYPEMASK)
00104
00116 #define cval(c) (cmap[(int)(c)] & VALMASK)
00117
00123 static unsigned char cmap[] = {
00124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x10, 0x11, 0x12, 0x13,
00128 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00129 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x00,
00132 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00134 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00144 };
00145
00158 #define _bcd(num, digit) (((num) >> ((digit) << 2)) & 0x0f)
00159
00173 #define bcd(num) (_bcd((num), 3) * 1000 + \
00174 _bcd((num), 2) * 100 + \
00175 _bcd((num), 1) * 10 + \
00176 _bcd((num), 0) * 1)
00177
00191 #define bcd_isquad(num) ((num) <= 0x0255 && _bcd((num), 1) <= 9 && \
00192 _bcd((num), 0) <= 9)
00193
00212 #define hex_accum(accum, c) ((accum) = ((accum) << 4) | cval((c)))
00213
00232 #define dec_accum(accum, c) ((accum) = ((accum) * 10) + cval((c)))
00233
00240 struct partaddr {
00241 unsigned char*addr[2];
00242 unsigned char addr2[SOCK_ADDRBUFV6_LEN];
00244 int segs[2];
00245 int cnt;
00246 ev_sockaddr_t*result;
00247 };
00248
00260 #define partaddr_init(pa, res) \
00261 do { \
00262 struct partaddr *_pa = (pa); \
00263 ev_sockaddr_t *_res = (res); \
00264 int _i; \
00265 _pa->addr[0] = sa_ipaddrbuf(_res); \
00266 _pa->addr[1] = _pa->addr2; \
00267 for (_i = 0; _i < SOCK_ADDRBUFV6_LEN; _i++) \
00268 _pa->addr[1][_i] = 0; \
00269 _pa->segs[0] = _pa->segs[1] = _pa->cnt = 0; \
00270 _pa->result = _res; \
00271 } while (0)
00272
00283 #define accumulate(pa, accum) \
00284 do { \
00285 struct partaddr *_pa = (pa); \
00286 uint32_t _accum = (accum); \
00287 if (_pa->segs[0] + _pa->segs[1] + _pa->cnt + 1 > \
00288 (sa_type(_pa->result) == AT_IPv4 ? \
00289 SOCK_ADDRBUFV4_LEN : SOCK_ADDRBUFV6_LEN)) \
00290 ev_return(EV_ERR_ADDRTOOLONG); \
00291 _pa->addr[_pa->cnt][_pa->segs[_pa->cnt]++] = (_accum >> 8) & 0xff; \
00292 _pa->addr[_pa->cnt][_pa->segs[_pa->cnt]++] = (_accum ) & 0xff; \
00293 } while (0)
00294
00305 #define test_v6(pa) \
00306 do { \
00307 struct partaddr *_pa = (pa); \
00308 if (!_pa->cnt && _pa->segs[0] != SOCK_ADDRBUFV6_LEN) \
00309 ev_return(EV_ERR_ADDRINCOMPLETE); \
00310 } while (0)
00311
00312 ev_err_t
00313 sockaddr_ptoa(ev_sockaddr_t *sa, const char *address, int alen)
00314 {
00315 const unsigned char *t = (const unsigned char *)address;
00316 unsigned char lastc = '\0';
00317 enum { s_unspec, s_inet4, s_inet6, s_inet64, s_port } state = s_unspec;
00318 uint32_t accum = 0, accum2 = 0;
00319 struct partaddr pa;
00320 int dots = 0, i, j, doublec = 0, twoc = 0;
00321 ev_satype_t subtype = AT_NONE;
00322
00323 ev_init();
00324
00325 if (!sa || !address)
00326 ev_return(EINVAL);
00327
00328 sa->sa_type = AT_NONE;
00329 memset((void *)&sa->sa_addr, 0, sizeof(sa->sa_addr));
00330
00331 if (alen < 0)
00332 alen = strlen(address);
00333
00334 if (*address == '/') {
00335 sa->sa_type = AT_LOCAL;
00336 if (alen >= SOCK_LOCALADDR_LEN)
00337 ev_return(EV_ERR_ADDRTOOLONG);
00338 strncpy(sa->sa_addr.saa_localaddr, address, alen);
00339 ev_return(0);
00340 }
00341
00342
00343
00344 partaddr_init(&pa, sa);
00345
00346
00347 for (; alen && *t; lastc = *(t++), alen--)
00348 switch (ctype(*t)) {
00349 case XDIGIT:
00350 if (state == s_unspec) {
00351 state = s_inet6;
00352 sa->sa_type = AT_IPv6;
00353 subtype = AT_IPv6;
00354 } else if (state != s_inet6)
00355 ev_return(EV_ERR_INVALIDCHAR);
00356
00357 case DIGIT:
00358 if (doublec)
00359 ev_return(EV_ERR_COLONEXPECTED);
00360 if (state == s_unspec || state == s_inet6)
00361 hex_accum(accum, *t);
00362 else
00363 dec_accum(accum, *t);
00364
00365 if (state == s_unspec && !bcd_isquad(accum)) {
00366
00367 state = s_inet6;
00368 sa->sa_type = AT_IPv6;
00369 subtype = AT_IPv6;
00370 }
00371
00372 if (accum > (state == s_inet4 ? 255 : 65535))
00373 ev_return(EV_ERR_ADDRTOOLONG);
00374
00375 twoc = 0;
00376 break;
00377
00378 case COLON:
00379 if (state == s_unspec) {
00380 state = s_inet6;
00381 sa->sa_type = AT_IPv6;
00382 subtype = AT_IPv6;
00383 if (!lastc)
00384 doublec++;
00385 } else if (state != s_inet6)
00386 ev_return(EV_ERR_INVALIDCHAR);
00387 else
00388 doublec = 0;
00389
00390 if (lastc == ':') {
00391 if (pa.cnt++)
00392 ev_return(EV_ERR_ADDRTOOLONG);
00393 twoc++;
00394 }
00395
00396 accumulate(&pa, accum);
00397 accum = 0;
00398 break;
00399
00400 case PERIOD:
00401 if ((!twoc && lastc == ':') ||
00402 lastc == '.' ||
00403 (dots && *address == '.'))
00404 ev_return(EV_ERR_INVALIDCHAR);
00405 dots++;
00406 twoc = 0;
00407 if (state == s_unspec) {
00408 accum2 = bcd(accum);
00409 accum = 0;
00410 state = s_inet4;
00411 sa->sa_type = AT_IPv4;
00412 subtype = AT_IPv4;
00413 continue;
00414 } else if (state == s_inet6) {
00415 if (bcd_isquad(accum)) {
00416
00417
00418
00419
00420
00421
00422
00423
00424 accum2 = accum;
00425 accum = 0;
00426 state = s_inet64;
00427 } else {
00428 accumulate(&pa, accum);
00429 accum = 0;
00430 test_v6(&pa);
00431 state = s_port;
00432 }
00433 continue;
00434 } else if (state == s_inet64) {
00435 accum2 = bcd(accum2);
00436 state = s_inet4;
00437 subtype = AT_IPv4;
00438
00439 } else if (state == s_inet4) {
00440 if (dots == 4) {
00441 if (sa->sa_type == AT_IPv6)
00442 test_v6(&pa);
00443 state = s_port;
00444 }
00445 } else
00446 ev_return(EV_ERR_INVALIDCHAR);
00447
00448 if (dots & 0x01) {
00449 accum2 = accum;
00450 accum = 0;
00451 } else {
00452 accumulate(&pa, (accum2 << 8) | accum);
00453 accum = 0;
00454 accum2 = 0;
00455 }
00456 break;
00457
00458 default:
00459 ev_return(EV_ERR_INVALIDCHAR);
00460 break;
00461 }
00462
00463
00464 if (state == s_unspec || (state == s_inet4 && dots == 1 &&
00465 *address == '.')) {
00466 if (lastc && !dots)
00467 ev_return(EV_ERR_BADADDR);
00468
00469
00470 sa->sa_type = AT_IPv4;
00471 if (state == s_inet4)
00472 state = s_port;
00473 } else if (state == s_inet64) {
00474
00475 accumulate(&pa, accum2);
00476 test_v6(&pa);
00477 state = s_port;
00478 }
00479
00480
00481
00482
00483
00484
00485
00486
00487 if (state == s_inet4) {
00488 if (dots < 3)
00489 ev_return(EV_ERR_ADDRINCOMPLETE);
00490 accumulate(&pa, (accum2 << 8) | accum);
00491 if (sa->sa_type == AT_IPv6)
00492 test_v6(&pa);
00493 } else if (state == s_inet6) {
00494 if (!twoc && lastc == ':')
00495 ev_return(EV_ERR_INVALIDCHAR);
00496 accumulate(&pa, accum);
00497 test_v6(&pa);
00498 } else
00499 sa->sa_addr.saa_ipaddr.saai_port = accum;
00500
00501
00502
00503
00504
00505
00506 for (i = SOCK_ADDRBUFV6_LEN - 1, j = pa.segs[1] - 1; i >= 0 && j >= 0;
00507 i--, j--)
00508 pa.addr[0][i] = pa.addr[1][j];
00509
00510
00511
00512
00513
00514 ev_return(0);
00515 }