diff --git a/server/access.c b/server/access.c index d2abee91..04a197bc 100644 --- a/server/access.c +++ b/server/access.c @@ -373,8 +373,9 @@ add_int_ent(acc_int_list_t **ilist, const char *ip) */ if(strcasecmp(ip, "ANY") == 0) { - new_sle->maddr = 0x0; - new_sle->mask = 0x0; + new_sle->family = AF_INET; + new_sle->acc_int.inet.maddr = 0x0; + new_sle->acc_int.inet.mask = 0x0; } else { @@ -473,17 +474,18 @@ add_int_ent(acc_int_list_t **ilist, const char *ip) /* Store our mask converted from CIDR to a 32-bit value. */ + new_sle->family = AF_INET; if(mask == 32) - new_sle->mask = 0xFFFFFFFF; + new_sle->acc_int.inet.mask = 0xFFFFFFFF; else if(need_shift && (mask > 0 && mask < 32)) - new_sle->mask = (0xFFFFFFFF << (32 - mask)); + new_sle->acc_int.inet.mask = (0xFFFFFFFF << (32 - mask)); else - new_sle->mask = mask; + new_sle->acc_int.inet.mask = mask; /* Store our masked address for comparisons with future incoming * packets. */ - new_sle->maddr = ntohl(in.s_addr) & new_sle->mask; + new_sle->acc_int.inet.maddr = ntohl(in.s_addr) & new_sle->acc_int.inet.mask; } /* If this is not the first entry, we walk our pointer to the @@ -2070,22 +2072,49 @@ int valid_access_stanzas(acc_stanza_t *acc) } int -compare_addr_list(acc_int_list_t *ip_list, const uint32_t ip) +compare_addr_list(acc_int_list_t *ip_list, int family, ...) { - int match = 0; + va_list ap; + uint32_t ip; + struct in6_addr * ip6; + va_start(ap, family); + switch(family) + { + case AF_INET: + ip = va_arg(ap, uint32_t); + break; + case AF_INET6: + ip6 = va_arg(ap, struct in6_addr *); + break; + default: + va_end(ap); + return 0; + } + va_end(ap); while(ip_list) { - if((ip & ip_list->mask) == (ip_list->maddr & ip_list->mask)) + if(ip_list->family != family) { - match = 1; - break; + ip_list = ip_list->next; + continue; + } + switch(family) + { + case AF_INET: + if((ip & ip_list->acc_int.inet.mask) == (ip_list->acc_int.inet.maddr & ip_list->acc_int.inet.mask)) + return 1; + break; + case AF_INET6: + if(memcmp(&ip_list->acc_int.inet6.maddr, ip6, sizeof(*ip6)) == 0) + return 1; + break; } ip_list = ip_list->next; } - return(match); + return 0; } /** diff --git a/server/access.h b/server/access.h index 02dc9b19..d4fb045e 100644 --- a/server/access.h +++ b/server/access.h @@ -114,7 +114,7 @@ int valid_access_stanzas(acc_stanza_t *acc); * \return Returns true on a match * */ -int compare_addr_list(acc_int_list_t *source_list, const uint32_t ip); +int compare_addr_list(acc_int_list_t *source_list, int family, ...); /** * \brief Check for a proto-port string diff --git a/server/fwknopd_common.h b/server/fwknopd_common.h index da35b1d4..3ce6b726 100644 --- a/server/fwknopd_common.h +++ b/server/fwknopd_common.h @@ -358,8 +358,20 @@ enum { */ typedef struct acc_int_list { - unsigned int maddr; - unsigned int mask; + int family; + union + { + struct + { + unsigned int maddr; + unsigned int mask; + } inet; + struct + { + struct in6_addr maddr; + unsigned int prefix; + } inet6; + } acc_int; struct acc_int_list *next; } acc_int_list_t; diff --git a/server/incoming_spa.c b/server/incoming_spa.c index 3e22178e..4cd805ae 100644 --- a/server/incoming_spa.c +++ b/server/incoming_spa.c @@ -347,14 +347,28 @@ check_stanza_expiration(acc_stanza_t *acc, spa_data_t *spadat, * source IP */ static int -is_src_match(acc_stanza_t *acc, const uint32_t ip) +is_src_match(acc_stanza_t *acc, const spa_pkt_info_t *spa_pkt) { - while (acc) + switch (spa_pkt->packet_family) { - if(compare_addr_list(acc->source_list, ip)) - return 1; + case AF_INET: + while (acc) + { + if(compare_addr_list(acc->source_list, AF_INET, ntohl(spa_pkt->packet_addr.inet.src_ip))) + return 1; - acc = acc->next; + acc = acc->next; + } + break; + case AF_INET6: + while (acc) + { + if(compare_addr_list(acc->source_list, AF_INET6, &spa_pkt->packet_addr.inet6.src_ip)) + return 1; + + acc = acc->next; + } + break; } return 0; } @@ -363,7 +377,7 @@ static int src_check(fko_srv_options_t *opts, spa_pkt_info_t *spa_pkt, spa_data_t *spadat, char **raw_digest) { - if (is_src_match(opts->acc_stanzas, ntohl(spa_pkt->packet_src_ip))) + if (is_src_match(opts->acc_stanzas, spa_pkt)) { if(strncasecmp(opts->config[CONF_ENABLE_DIGEST_PERSISTENCE], "Y", 1) == 0) { @@ -427,9 +441,9 @@ static int src_dst_check(acc_stanza_t *acc, spa_pkt_info_t *spa_pkt, spa_data_t *spadat, const int stanza_num) { - if(! compare_addr_list(acc->source_list, ntohl(spa_pkt->packet_src_ip)) || + if(! compare_addr_list(acc->source_list, AF_INET, ntohl(spa_pkt->packet_src_ip)) || (acc->destination_list != NULL - && ! compare_addr_list(acc->destination_list, ntohl(spa_pkt->packet_dst_ip)))) + && ! compare_addr_list(acc->destination_list, AF_INET, ntohl(spa_pkt->packet_dst_ip)))) { log_msg(LOG_DEBUG, "(stanza #%d) SPA packet (%s -> %s) filtered by SOURCE and/or DESTINATION criteria",