%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% module #include "dk4conf.h" #include "dk4types.h" #include "dk4error.h" #include "dk4mem.h" #include "dk4sock.h" #include "dk4str8.h" #include "dk4mai8dsz.h" $!trace-include #if TRACE_DEBUG static void dk4socket_c8_debug_allowed_peer(dk4_allowed_peer_t *peerptr) { FILE *fipo; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 unsigned char *ucptr; size_t i; size_t pass; #endif unsigned long ul1, ul2; fipo = dktrace_file(); if (NULL != fipo) { switch (peerptr->af) { case AF_INET : { ul1 = (peerptr->data).ipv4.ad.s_addr; ul2 = (peerptr->data).ipv4.ma.s_addr; ul1 = dk4socket_ntohl(ul1); ul2 = dk4socket_ntohl(ul2); fprintf( fipo, "Address/Mask: %lu.%lu.%lu.%lu/%lu.%lu.%lu.%lu\n", ((ul1 >> 24) & 0x000000FFUL), ((ul1 >> 16) & 0x000000FFUL), ((ul1 >> 8) & 0x000000FFUL), ((ul1 ) & 0x000000FFUL), ((ul2 >> 24) & 0x000000FFUL), ((ul2 >> 16) & 0x000000FFUL), ((ul2 >> 8) & 0x000000FFUL), ((ul2 ) & 0x000000FFUL) ); } break; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6 : { fputs("Address/Mask: ", fipo); for (pass = 0; pass < 2; pass++) { if (0 != pass) { fputc('/', fipo); ucptr = &((peerptr->data).ipv6.ma.s6_addr[0]); } else { ucptr = &((peerptr->data).ipv6.ad.s6_addr[0]); } for (i = 0; i < 16; i++) { if ((0 != i) && (0 == (i % 2))) { fputc(':', fipo); } fprintf(fipo, "%02x", *(ucptr++)); } } fputc('\n', fipo); } break; #endif } } } #endif int dk4socket_c8_get_allowed_peer( dk4_allowed_peer_t *peerptr, const char *str, dk4_er_t *erp ) { char mycp[128]; IN_ADDR in4; IN_ADDR ma4; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 IN6_ADDR in6; IN6_ADDR ma6; #endif char *maptr; const char *endptr = NULL; size_t bitno = 0; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 size_t i = 0; #endif unsigned long nm4 = 0UL; int back = DK4_SOCKET_RESULT_FAILED; int af = AF_UNSPEC; int res = 0; $? "+ dk4socket_c8_get_allowed_peer \"%!8s\"", str if ((NULL != peerptr) && (NULL != str)) { if (0 != dk4str8_cpy_s(mycp, sizeof(mycp), str, erp)) { maptr = dk4str8_chr(mycp, '/'); if (NULL != maptr) { *(maptr++) = '\0'; } back = dk4socket_c8_inet_pton( &in4, sizeof(in4), AF_INET, mycp, erp); if (DK4_SOCKET_RESULT_SUCCESS == back) { af = AF_INET; } #if DK4_HAVE_STRUCT_SOCKADDR_IN6 else { back = dk4socket_c8_inet_pton( &in6, sizeof(in6), AF_INET6, mycp, erp); if (DK4_SOCKET_RESULT_SUCCESS == back) { af = AF_INET6; } } #endif if (DK4_SOCKET_RESULT_SUCCESS == back) { back = DK4_SOCKET_RESULT_FAILED; if (NULL != maptr) { $? ". mask" res = dk4ma_input_c8_dec_size_t(&bitno, maptr, &endptr, 1, NULL); if (0 != res) { $? ". mask by number of bits" /* Bit number was specified. */ switch (af) { case AF_INET : { if (0 != dk4socket_mask_bits(&nm4, bitno, erp)) { ma4.s_addr = dk4socket_htonl(nm4); DK4_MEMCPY(&((peerptr->data).ipv4.ad),&in4,sizeof(in4)); DK4_MEMCPY(&((peerptr->data).ipv4.ma),&ma4,sizeof(ma4)); peerptr->af = af; back = DK4_SOCKET_RESULT_SUCCESS; } else { $? "! out of range" } } break; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6 : { back = dk4socket_mask6_bits(&ma6, bitno, erp); if (DK4_SOCKET_RESULT_SUCCESS == back) { DK4_MEMCPY(&((peerptr->data).ipv6.ad),&in6,sizeof(in6)); DK4_MEMCPY(&((peerptr->data).ipv6.ma),&ma6,sizeof(ma6)); peerptr->af = af; } else { $? "! out of range" } } break; #endif default : { /* Must not happen */ } break; } } else { $? ". mask address" /* Not a bit number, probably an address. */ switch (af) { case AF_INET : { back = dk4socket_c8_inet_pton( &ma4, sizeof(ma4), AF_INET, maptr, erp ); if (DK4_SOCKET_RESULT_SUCCESS == back) { DK4_MEMCPY(&((peerptr->data).ipv4.ad),&in4,sizeof(in4)); DK4_MEMCPY(&((peerptr->data).ipv4.ma),&ma4,sizeof(ma4)); peerptr->af = af; } else { $? "! out of range" } } break; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6 : { back = dk4socket_c8_inet_pton( &ma6, sizeof(ma6), AF_INET6, maptr, erp ); if (DK4_SOCKET_RESULT_SUCCESS == back) { DK4_MEMCPY(&((peerptr->data).ipv6.ad),&in6,sizeof(in6)); DK4_MEMCPY(&((peerptr->data).ipv6.ma),&ma6,sizeof(ma6)); peerptr->af = af; } else { $? "! out of range" } } break; #endif } } } else { $? ". no mask" /* Host was specified */ switch (af) { case AF_INET : { ma4.s_addr = dk4socket_htonl(0xFFFFFFFFUL); DK4_MEMCPY(&((peerptr->data).ipv4.ad), &in4, sizeof(in4)); DK4_MEMCPY(&((peerptr->data).ipv4.ma), &ma4, sizeof(ma4)); peerptr->af = af; back = DK4_SOCKET_RESULT_SUCCESS; } break; #if DK4_HAVE_STRUCT_SOCKADDR_IN6 case AF_INET6 : { for (i = 0; i < 16; i++) { ma6.s6_addr[i] = 0xFF; } DK4_MEMCPY(&((peerptr->data).ipv6.ad), &in6, sizeof(in6)); DK4_MEMCPY(&((peerptr->data).ipv6.ma), &ma6, sizeof(ma6)); peerptr->af = af; back = DK4_SOCKET_RESULT_SUCCESS; } break; #endif default : { /* Must not happen */ } break; } } } else { $? "! address invalid" } } else { $? "! string too long" } } else { $? "! args" dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } #if TRACE_DEBUG if (DK4_SOCKET_RESULT_SUCCESS == back) { dk4socket_c8_debug_allowed_peer(peerptr); } #endif $? "- dk4socket_c8_get_allowed_peer %d", back return back; }