/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4sock06.ctr */ /* Copyright (C) 2015-2017, Dirk Krause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file dk4sock06.c The dk4sock06 module. */ #line 10 "dk4sock06.ctr" #include "dk4sock.h" #include "dk4maaul.h" #include "dk4maaus.h" #line 18 "dk4sock06.ctr" #if !DK4_HAVE_INET_PTON /** Character classes. */ enum { /** Any character not rom the types below. */ INPUT_ANY = 0 , /** Digit. */ INPUT_DIGIT , /** Separator (dot for IPv4, colon for IPv6). */ INPUT_SEP , /** End of input reached. */ INPUT_END }; /** States while reading IPv4. */ enum { /** Nothing processed yet. */ S4_INIT = 0 , /** Previous character was a separator. */ S4_SEP , /** Previous character was digit. */ S4_DIG , /** Successfully finished IP address retrieval. */ S4_FINISHED , /** Error found in previous input. */ S4_ERROR }; static int dk4socket_classify_input_char( char c, int ipv6, unsigned short *valptr ) { int back = INPUT_ANY; switch (c) { case ':' : { if (0 != ipv6) { back = INPUT_SEP; } } break; case '.' : { if (0 == ipv6) { back = INPUT_SEP; } } break; case '0': { back = INPUT_DIGIT; *valptr = 0; } break; case '1': { back = INPUT_DIGIT; *valptr = 1; } break; case '2': { back = INPUT_DIGIT; *valptr = 2; } break; case '3': { back = INPUT_DIGIT; *valptr = 3; } break; case '4': { back = INPUT_DIGIT; *valptr = 4; } break; case '5': { back = INPUT_DIGIT; *valptr = 5; } break; case '6': { back = INPUT_DIGIT; *valptr = 6; } break; case '7': { back = INPUT_DIGIT; *valptr = 7; } break; case '8': { back = INPUT_DIGIT; *valptr = 8; } break; case '9': { back = INPUT_DIGIT; *valptr = 9; } break; case 'a': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 10; } } break; case 'A': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 10; } } break; case 'b': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 11; } } break; case 'B': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 11; } } break; case 'c': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 12; } } break; case 'C': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 12; } } break; case 'd': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 13; } } break; case 'D': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 13; } } break; case 'e': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 14; } } break; case 'E': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 14; } } break; case 'f': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 15; } } break; case 'F': { if (0 != ipv6) { back = INPUT_DIGIT; *valptr = 15; } } break; } return back; } #if DK4_HAVE_STRUCT_SOCKADDR_IN6 /** States while reading IPv4. */ enum { /** Nothing processed yet. */ S6_INIT = 0 , /** Previous character was a separator. */ S6_SEP , /** Previous two characters were separators. */ S6_DSEP , /** Previous character was digit. */ S6_DIG , /** Successfully finished IP address retrieval. */ S6_FINISHED , /** Error found in previous input. */ S6_ERROR }; static int dk4socket_my_ip6_pton( void *pAddr, size_t szAddr, const char *src, dk4_er_t *erp ) { dk4_er_t er; unsigned short left[8]; /* Values for left side */ unsigned short right[8]; /* Values for right side */ struct in6_addr *inp6 = NULL; /* Result */ int isright = 0; /* Flag: Already on right side */ int hl = 0; /* Number of values on left side */ int hr = 0; /* Number of values on right side */ int icl = 0; /* Input character class */ int cc = 1; /* Flag: Can continue */ int st = S6_INIT; /* Current state */ int back = DK4_SOCKET_RESULT_FAILED; int i = 0; /* Index to fill address */ unsigned short curval = 0; /* Value collected so far */ unsigned short us = 0; /* Current character value */ do { if ('\0' == *src) { icl = INPUT_END; } else { icl = dk4socket_classify_input_char(*src, 1, &us); } switch (st) { case S6_INIT : { switch (icl) { case INPUT_DIGIT : { curval = us; st = S6_DIG; } break; case INPUT_SEP : { st = S6_SEP; } break; default : { st = S6_ERROR; cc = -1; } break; } } break; case S6_SEP : { switch (icl) { case INPUT_DIGIT : { curval = us; st = S6_DIG; } break; case INPUT_SEP : { st = S6_DSEP; if (0 == isright) { isright = 1; } else { st = S6_ERROR; cc = -1; } } break; default : { st = S6_ERROR; cc = -1; } break; } } break; case S6_DSEP : { switch (icl) { case INPUT_DIGIT : { curval = us; st = S6_DIG; } break; case INPUT_END : { st = S6_FINISHED; } break; default : { st = S6_ERROR; cc = -1; } break; } } break; case S6_DIG : { switch (icl) { case INPUT_DIGIT : { dk4error_init(&er); curval = dk4ma_ushort_add( dk4ma_ushort_mul(curval, 16UL, &er), us, &er ); if (DK4_E_NONE != er.ec) { st = S6_ERROR; cc = -1; } } break; case INPUT_SEP : { if (0 != isright) { if (8 > hr) { right[hr++] = curval; st = S6_SEP; } else { st = S6_ERROR; cc = -1; } } else { if (8 > hl) { left[hl++] = curval; st = S6_SEP; } else { st = S6_ERROR; cc = -1; } } } break; case INPUT_END : { if (0 != isright) { if (8 > hr) { right[hr++] = curval; st = S6_FINISHED; cc = 0; } else { st = S6_ERROR; cc = -1; } } else { if (8 > hl) { left[hl++] = curval; st = S6_FINISHED; cc = 0; } else { st = S6_ERROR; cc = -1; } } } break; default : { st = S6_ERROR; cc = -1; } break; } } break; } src++; if ((1 == cc) && (INPUT_END == icl)) { cc = 0; } } while (1 == cc); if ((0 == cc) && (S6_FINISHED == st)) { if (9 > (hl + hr)) { inp6 = (struct in6_addr *)pAddr; for (i = 0; i < 8; i++) { #if DK4_ON_WINDOWS inp6->u.Word[i] = dk4socket_htons(0); #else inp6->s6_addr16[i] = dk4socket_htons(0); #endif } for (i = 0; i < hl; i++) { #if DK4_ON_WINDOWS inp6->u.Word[i] = dk4socket_htons(left[i]); #else inp6->s6_addr16[i] = dk4socket_htons(left[i]); #endif } for (i = 0; i < hr; i++) { #if DK4_ON_WINDOWS inp6->u.Word[8 - hr + i ] = dk4socket_htons(right[i]); #else inp6->s6_addr16[8 - hr + i] = dk4socket_htons(right[i]); #endif } back = DK4_SOCKET_RESULT_SUCCESS; } else { dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } return back; } #endif static int dk4socket_my_ip4_pton( void *pAddr, size_t szAddr, const char *src, dk4_er_t *erp ) { dk4_er_t er; struct in_addr *pin4; unsigned long curval = 0UL; unsigned long result = 0UL; int back = DK4_SOCKET_RESULT_FAILED; int cc = 1; int icl = 0; int st = S4_INIT; int curnum = 0; unsigned short us = 0; #line 365 "dk4sock06.ctr" do { us = 0; if ('\0' == *src) { icl = INPUT_END; } else { icl = dk4socket_classify_input_char(*src, 0, &us); } switch (icl) { case INPUT_DIGIT : { switch (st) { case S4_INIT: { curval = (unsigned long)us; st = S4_DIG; } break; case S4_SEP : { curval = (unsigned long)us; st = S4_DIG; } break; case S4_DIG : { dk4error_init(&er); curval = dk4ma_ulong_add( dk4ma_ulong_mul(curval, 10UL, &er), (unsigned long)us, &er ); if (DK4_E_NONE != er.ec) { st = S4_ERROR; cc = -1; } } break; } } break; case INPUT_SEP : { switch (st) { case S4_INIT: { st = S4_ERROR; cc = -1; } break; case S4_SEP : { st = S4_ERROR; cc = -1; } break; case S4_DIG : { if (256UL > curval) { switch (curnum++) { case 0: { result = ((curval << 24) & 0xFF000000UL); st = S4_SEP; curval = 0UL; } break; case 1: { result |= ((curval << 16) & 0x00FF0000UL); st = S4_SEP; curval = 0UL; } break; case 2: { result |= ((curval << 8) & 0x0000FF00UL); st = S4_SEP; curval = 0UL; } break; default: { st = S4_ERROR; cc = -1; } break; } } else { st = S4_ERROR; cc = -1; } } break; } } break; case INPUT_END : { switch (st) { case S4_INIT: { st = S4_ERROR; cc = -1; } break; case S4_SEP : { st = S4_ERROR; cc = -1; } break; case S4_DIG : { st = S4_ERROR; cc = -1; if (3 == curnum) { if (256UL > curval) { result |= curval; cc = 0; st = S4_FINISHED; } } } break; } } break; default : { st = S4_ERROR; cc = -1; } break; } src++; } while(1 == cc); if ((0 == cc) && (S4_FINISHED == st)) { pin4 = (struct in_addr *)pAddr; pin4->s_addr = dk4socket_htonl(result); back = DK4_SOCKET_RESULT_FAILED; #line 472 "dk4sock06.ctr" } else { dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); #line 475 "dk4sock06.ctr" } #line 477 "dk4sock06.ctr" return back; } static int dk4socket_my_inet_pton( void *pAddr, size_t szAddr, int afam, const char *src, dk4_er_t *erp ) { int back = DK4_SOCKET_RESULT_FAILED; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 if (AF_INET6 == afam) { back = dk4socket_my_ip6_pton(pAddr, szAddr, src, erp); } else { #endif back = dk4socket_my_ip4_pton(pAddr, szAddr, src, erp); #if DK4_HAVE_STRUCT_SOCKADDR_IN6 } #endif return back; } #endif int dk4socket_c8_inet_pton( void *pAddr, size_t szAddr, int afam, const char *src, dk4_er_t *erp ) { #if DK4_HAVE_INET_PTON /* +++++ +inet_pton */ int back = DK4_SOCKET_RESULT_FAILED; int res; if ((NULL != pAddr) && (0 < szAddr) && (NULL != src)) { switch (afam) { case AF_INET : { if (sizeof(struct in_addr) == szAddr) { back = DK4_SOCKET_RESULT_SUCCESS; } } break; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6 : { if (sizeof(struct in6_addr) == szAddr) { back = DK4_SOCKET_RESULT_SUCCESS; } } break; #endif } if (DK4_SOCKET_RESULT_SUCCESS == back) { back = DK4_SOCKET_RESULT_FAILED; dk4socket_error_reset(); res = inet_pton(afam, src, pAddr); switch (res) { case 0 : { dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } break; case -1 : { dk4socket_error_report(erp, DK4_E_SOCKET_INET_PTON); } break; default : { back = DK4_SOCKET_RESULT_SUCCESS; } break; } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; /* ----- +inet_pton */ #else /* +++++ -inet_pton */ int back = DK4_SOCKET_RESULT_FAILED; if ((NULL != pAddr) && (0 < szAddr) && (NULL != src)) { switch (afam) { case AF_INET : { if (sizeof(struct in_addr) == szAddr) { back = DK4_SOCKET_RESULT_SUCCESS; } } break; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6 : { if (sizeof(struct in6_addr) == szAddr) { back = DK4_SOCKET_RESULT_SUCCESS; } } break; #endif } if (DK4_SOCKET_RESULT_SUCCESS == back) { back = dk4socket_my_inet_pton(pAddr, szAddr, afam, src, erp); } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; /* ----- -inet_pton */ #endif }