/********************************************************************* * * Function : acl_addr * * Description : Called from `load_config' to parse an ACL address. * * Parameters : * 1 : aspec = String specifying ACL address. * 2 : aca = struct access_control_addr to fill in. * * Returns : 0 => Ok, everything else is an error. * *********************************************************************/ int acl_addr(char *aspec, struct access_control_addr *aca) { int i, masklength, port; char *p; masklength = 32; port = 0; if ((p = strchr(aspec, '/')) != NULL) { *p++ = '\0'; if (ijb_isdigit(*p) == 0) { return(-1); } masklength = atoi(p); } if ((masklength < 0) || (masklength > 32)) { return(-1); } if ((p = strchr(aspec, ':')) != NULL) { *p++ = '\0'; if (ijb_isdigit(*p) == 0) { return(-1); } port = atoi(p); } aca->port = port; aca->addr = ntohl(resolve_hostname_to_ip(aspec)); if (aca->addr == INADDR_NONE) { return(-1); } /* build the netmask */ aca->mask = 0; for (i=1; i <= masklength ; i++) { aca->mask |= (1 << (32 - i)); } /* now mask off the host portion of the ip address * (i.e. save on the network portion of the address). */ aca->addr = aca->addr & aca->mask; return(0); }
/********************************************************************* * * Function : acl_addr * * Description : Called from `load_config' to parse an ACL address. * * Parameters : * 1 : aspec = String specifying ACL address. * 2 : aca = struct access_control_addr to fill in. * * Returns : 0 => Ok, everything else is an error. * *********************************************************************/ int filters::acl_addr(const char *aspec, access_control_addr *aca) { int masklength; #ifdef HAVE_RFC2553 struct addrinfo hints, *result; uint8_t *mask_data; in_port_t *mask_port; unsigned int addr_len; #else long port; #endif /* def HAVE_RFC2553 */ char *p; char *acl_spec = NULL; #ifdef HAVE_RFC2553 /* XXX: Depend on ai_family */ masklength = 128; #else masklength = 32; port = 0; #endif /* * Use a temporary acl spec copy so we can log * the unmodified original in case of parse errors. */ acl_spec = strdup(aspec); if (acl_spec == NULL) { /* XXX: This will be logged as parse error. */ return(-1); } if ((p = strchr(acl_spec, '/')) != NULL) { *p++ = '\0'; if (ijb_isdigit(*p) == 0) { freez(acl_spec); acl_spec = NULL; return(-1); } masklength = atoi(p); } if ((masklength < 0) || #ifdef HAVE_RFC2553 (masklength > 128) #else (masklength > 32) #endif ) { freez(acl_spec); acl_spec = NULL; return(-1); } if ((*acl_spec == '[') && (NULL != (p = strchr(acl_spec, ']')))) { *p = '\0'; std::memmove(acl_spec, acl_spec + 1, (size_t)(p - acl_spec)); if (*++p != ':') { p = NULL; } } else { p = strchr(acl_spec, ':'); } #ifdef HAVE_RFC2553 std::memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; int i = getaddrinfo(acl_spec, ((p) ? ++p : NULL), &hints, &result); freez(acl_spec); acl_spec = NULL; if (i != 0) { errlog::log_error(LOG_LEVEL_ERROR, "Can not resolve [%s]:%s: %s", acl_spec, p, gai_strerror(i)); return(-1); } /* TODO: Allow multihomed hostnames */ std::memcpy(&(aca->_addr), result->ai_addr, result->ai_addrlen); freeaddrinfo(result); #else if (p != NULL) { char *endptr; *p++ = '\0'; port = strtol(p, &endptr, 10); if (port <= 0 || port > 65535 || *endptr != '\0') { freez(acl_spec); acl_spec = NULL; return(-1); } } aca->_port = (unsigned long)port; aca->_addr = ntohl(resolve_hostname_to_ip(acl_spec)); freez(acl_spec); acl_spec = NULL; if (aca->_addr == INADDR_NONE) { /* XXX: This will be logged as parse error. */ return(-1); } #endif /* def HAVE_RFC2553 */ /* build the netmask */ #ifdef HAVE_RFC2553 /* Clip masklength according to current family. */ if ((aca->_addr.ss_family == AF_INET) && (masklength > 32)) { masklength = 32; } aca->_mask.ss_family = aca->_addr.ss_family; if (sockaddr_storage_to_ip(&aca->_mask, &mask_data, &addr_len, &mask_port)) { return(-1); } if (p) { /* ACL contains a port number, check ports in the future. */ *mask_port = 1; } else ((struct sockaddr_in*)&aca->_mask)->sin_port = 0; /* * XXX: This could be optimized to operate on whole words instead * of octets (128-bit CPU could do it in one iteration). */ /* * Octets after prefix can be ommitted because of * previous initialization to zeros. */ for (size_t i = 0; (i < addr_len) && masklength; i++) { if (masklength >= 8) { mask_data[i] = 0xFF; masklength -= 8; } else { /* * XXX: This assumes MSB of octet is on the left side. * This should be true for all architectures or solved * by the link layer. */ mask_data[i] = (uint8_t)~((1 << (8 - masklength)) - 1); masklength = 0; } } #else aca->mask = 0; for (i=1; i <= masklength ; i++) { aca->mask |= (1U << (32 - i)); } /* now mask off the host portion of the ip address * (i.e. save on the network portion of the address). */ aca->addr = aca->addr & aca->mask; #endif /* def HAVE_RFC2553 */ return(0); }