Пример #1
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 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);

}
Пример #2
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);
}