/** * Advance the BDD iterator, taking into account that some assignments * need to be expanded twice. */ static void advance_assignment(struct ipset_iterator *iterator) { /* Check the current state of the iterator to determine how to * advance. */ /* In most cases, the assignment we just finished only needed to be * expanded once. So we move on to the next assignment and process * it. */ if (CORK_LIKELY(iterator->multiple_expansion_state == IPSET_ITERATOR_NORMAL)) { ipset_bdd_iterator_advance(iterator->bdd_iterator); process_assignment(iterator); return; } /* If the assignment needs to be expanded twice, we'll do the IPv4 * expansion first. If that's what we've just finished, do the IPv6 * expansion next. */ if (iterator->multiple_expansion_state == IPSET_ITERATOR_MULTIPLE_IPV4) { DEBUG("Expanding IPv6 second"); iterator->multiple_expansion_state = IPSET_ITERATOR_MULTIPLE_IPV6; ipset_assignment_set (iterator->bdd_iterator->assignment, 0, IPSET_FALSE); expand_ipv6(iterator); return; } /* If we've just finished the IPv6 expansion, then we've finished * with this assignment. Before moving on to the next one, we have * to reset variable 0 to EITHER (which it was before we started * this whole mess). */ if (iterator->multiple_expansion_state == IPSET_ITERATOR_MULTIPLE_IPV6) { DEBUG("Finished both expansions"); ipset_assignment_set (iterator->bdd_iterator->assignment, 0, IPSET_EITHER); ipset_bdd_iterator_advance(iterator->bdd_iterator); process_assignment(iterator); return; } }
int cloakhost(char *host, char *dest) { char virt[HOSTLEN + 1], ip6buffer[INET6_ADDRSTRLEN], *p; unsigned int dotCount, colCount; int32_t csum; host_type_t htype; htype = host_type(host, &dotCount, &colCount); memset(virt, 0x0, HOSTLEN+1); switch (htype) { case HT_INVALID: return 0; case HT_FQDN: csum = fnv_hash(sha1_hash(host, strlen(host)), SHABUFLEN); if (dotCount == 1) { snprintf(virt, HOSTLEN, "%s%c%X.%s", cloak_host, (csum < 0 ? '=' : '-'), (csum < 0 ? -csum : csum), host); } else if (dotCount > 1) { int chlen = strlen(cloak_host) + 10; /* -12345678. */ p = (char *) strchr((char *)host, '.'); while((strlen(p) + chlen) > HOSTLEN) { /* controllare i return value non sarebbe una cattiva idea... */ if ((p = (char *) strchr((char *) ++p, '.')) == NULL) return 0; } snprintf(virt, HOSTLEN, "%s%c%X.%s", cloak_host, (csum < 0 ? '=' : '-'), (csum < 0 ? -csum : csum), p + 1); } else return 0; break; case HT_IPv4: { char ipmask[16]; csum = fnv_hash(sha1_hash(host, strlen(host)), SHABUFLEN); strncpy(ipmask, host, sizeof(ipmask)); ipmask[sizeof(ipmask) - 1] = '\0'; if ((p = strchr(ipmask, '.')) != NULL) if ((p = strchr(p + 1, '.')) != NULL) *p = '\0'; if (p == NULL) snprintf(virt, HOSTLEN, "%s%c%X", cloak_host, csum < 0 ? '=' : '-', csum < 0 ? -csum : csum); else snprintf(virt, HOSTLEN, "%s.%s%c%X", ipmask, cloak_host, csum < 0 ? '=' : '-', csum < 0 ? -csum : csum); break; } case HT_IPv6: { /* FFFFFFFUUUUUUUU */ int rv; struct in6_addr ip6addr; /* Expand address before hashing */ expand_ipv6(host, colCount, ip6buffer); Debug((DEBUG_INFO, "%s expanded to %s (%u columns)", host, ip6buffer, colCount)); csum = fnv_hash(sha1_hash(ip6buffer, strlen(ip6buffer)), SHABUFLEN); /* Clear the buffer */ memset(ip6buffer, 0, sizeof(ip6buffer)); /* Get raw bytes... */ rv = inet_pton(AF_INET6, host, &ip6addr); if (rv <= 0) { Debug((DEBUG_ERROR, "inet_pton failed: rv = %d, errno = %d", rv, errno)); return 0; } /* ...blank out the lowest 80 bits... */ memset(&(ip6addr.s6_addr[6]), 0, 10); /* ...and get back the "presentation format" */ if (inet_ntop(AF_INET6, &ip6addr, ip6buffer, INET6_ADDRSTRLEN) == NULL) { Debug((DEBUG_ERROR, "inet_ntop failed: errno = %d", errno)); return 0; } /* Now append the checksum (eg. "2001:db8::Azzurra-12345678") */ snprintf(virt, HOSTLEN, "%s%s%c%X", ip6buffer, cloak_host, csum < 0 ? '=' : '-', csum < 0 ? -csum : csum); break; } } memcpy(dest, virt, HOSTLEN); return 1; }
/****************************************************************************** * * * Function: process_rule * * * * Purpose: process single discovery rule * * * * Parameters: * * * * Return value: * * * * Author: Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ static void process_rule(DB_DRULE *rule) { DB_RESULT result; DB_ROW row; DB_DCHECK check; char ip[MAX_STRING_LEN], prefix[MAX_STRING_LEN]; unsigned int j[9], i; int first, last, ipv6; char *curr_range = NULL, *next_range = NULL, *dash = NULL; #if defined(HAVE_IPV6) char *colon; #endif assert(rule); zabbix_log(LOG_LEVEL_DEBUG, "In process_rule() [name:%s] [range:%s]", rule->name, rule->iprange); for ( curr_range = rule->iprange; curr_range; curr_range = next_range ) { /* split by ',' */ if ( NULL != (next_range = strchr(curr_range, ',')) ) { next_range[0] = '\0'; } if ( NULL != (dash = strchr(curr_range, '-')) ) { dash[0] = '\0'; } first = last = -1; #if defined(HAVE_IPV6) if ( SUCCEED == expand_ipv6(curr_range, ip, sizeof(ip)) ) { ipv6 = 1; if( sscanf(ip, "%x:%x:%x:%x:%x:%x:%x:%x", &j[0], &j[1], &j[2], &j[3], &j[4], &j[5], &j[6], &j[7]) == 8 ) { first = j[7]; zbx_strlcpy( prefix, curr_range, sizeof(prefix) ); if( NULL != (colon = strrchr(prefix, ':')) ) { ( colon + 1 )[0] = '\0'; } } if( dash != NULL ) { if( sscanf(dash + 1, "%x", &j[8]) == 1 ) { last = j[8]; } } else { last = first; } } else { #endif /* HAVE_IPV6 */ ipv6 = 0; if( sscanf(curr_range, "%d.%d.%d.%d", &j[0], &j[1], &j[2], &j[3]) == 4 ) { first = j[3]; } if( dash != NULL ) { if( sscanf(dash + 1, "%d", &j[4]) == 1 ) { last = j[4]; } } else { last = first; } #if defined(HAVE_IPV6) } #endif /* HAVE_IPV6 */ if( dash ) { dash[0] = '-'; dash = NULL; } if ( next_range ) { next_range[0] = ','; next_range ++; } if( first < 0 || last < 0 ) { zabbix_log(LOG_LEVEL_WARNING, "Discovery: Wrong format of IP range [%s]", rule->iprange); continue; } for ( i = first; i <= last; i++ ) { switch( ipv6 ) { case 0 : zbx_snprintf(ip, sizeof(ip), "%d.%d.%d.%d", j[0], j[1], j[2], i); break; case 1 : zbx_snprintf(ip, sizeof(ip), "%s%x", prefix, i); break; } zabbix_log(LOG_LEVEL_DEBUG, "Discovery: process_rule() [IP:%s]", ip); result = DBselect("select dcheckid,druleid,type,key_,snmp_community,ports from dchecks where druleid=" ZBX_FS_UI64, rule->druleid); while((row=DBfetch(result))) { memset(&check, 0, sizeof(DB_RESULT)); ZBX_STR2UINT64(check.dcheckid,row[0]); ZBX_STR2UINT64(check.druleid,row[1]); check.type = atoi(row[2]); check.key_ = row[3]; check.snmp_community = row[4]; check.ports = row[5]; process_check(rule, &check, ip); } DBfree_result(result); add_host_event(ip); } } zabbix_log( LOG_LEVEL_DEBUG, "End process_rule()"); }
static void process_assignment(struct ipset_iterator *iterator) { while (!iterator->bdd_iterator->finished) { if (iterator->bdd_iterator->value == iterator->desired_value) { /* If the BDD iterator hasn't finished, and the result of * the function with this assignment matches what the caller * wants, then we've found an assignment to generate IP * addresses from. * * Try to expand this assignment, and process the first * expanded assignment. We want 32 + 1 variables if the * current address is IPv4; 128 + 1 if it's IPv6. */ DEBUG("Got a matching BDD assignment"); enum ipset_tribool address_type = ipset_assignment_get (iterator->bdd_iterator->assignment, 0); if (address_type == IPSET_FALSE) { /* FALSE means IPv6*/ DEBUG("Assignment is IPv6"); iterator->multiple_expansion_state = IPSET_ITERATOR_NORMAL; expand_ipv6(iterator); return; } else if (address_type == IPSET_TRUE) { /* TRUE means IPv4*/ DEBUG("Assignment is IPv4"); iterator->multiple_expansion_state = IPSET_ITERATOR_NORMAL; expand_ipv4(iterator); return; } else { /* EITHER means that this assignment contains both IPv4 * and IPv6 addresses. Expand it as IPv4 first. */ DEBUG("Assignment is both IPv4 and IPv6"); DEBUG("Expanding IPv4 first"); iterator->multiple_expansion_state = IPSET_ITERATOR_MULTIPLE_IPV4; ipset_assignment_set (iterator->bdd_iterator->assignment, 0, IPSET_TRUE); expand_ipv4(iterator); return; } } /* The BDD iterator has a value, but it doesn't match the one we * want. Advance the BDD iterator and try again. */ DEBUG("Value is %d, skipping", iterator->bdd_iterator->value); ipset_bdd_iterator_advance(iterator->bdd_iterator); } /* If we fall through, then the BDD iterator has finished. That * means there's nothing left for the set iterator. */ DEBUG("Set iterator is finished"); ipset_expanded_assignment_free(iterator->assignment_iterator); iterator->assignment_iterator = NULL; ipset_bdd_iterator_free(iterator->bdd_iterator); iterator->bdd_iterator = NULL; iterator->finished = true; }
/****************************************************************************** * * * Function: process_rule * * * * Purpose: process single discovery rule * * * * Author: Eugene Grigorjev * * * ******************************************************************************/ static void process_rule(DB_DRULE *drule) { const char *__function_name = "process_rule"; DB_DHOST dhost; int host_status, now; unsigned int j[9], i, first, last, mask, network, broadcast; char ip[INTERFACE_IP_LEN_MAX], *curr_range, *next_range, *dash, *slash, dns[INTERFACE_DNS_LEN_MAX]; int ipv6; zabbix_log(LOG_LEVEL_DEBUG, "In %s() rule:'%s' range:'%s'", __function_name, drule->name, drule->iprange); for (curr_range = drule->iprange; curr_range; curr_range = next_range) { if (NULL != (next_range = strchr(curr_range, ','))) *next_range = '\0'; zabbix_log(LOG_LEVEL_DEBUG, "%s() '%s'", __function_name, curr_range); if (NULL != (dash = strchr(curr_range, '-'))) *dash = '\0'; if (NULL != (slash = strchr(curr_range, '/'))) *slash = '\0'; first = last = 0; if (SUCCEED == expand_ipv6(curr_range, ip, sizeof(ip))) { ipv6 = 1; #ifdef HAVE_IPV6 if (8 == sscanf(ip, "%x:%x:%x:%x:%x:%x:%x:%x", &j[0], &j[1], &j[2], &j[3], &j[4], &j[5], &j[6], &j[7])) { first = (j[6] << 16) + j[7]; if (NULL != dash) { if (1 == sscanf(dash + 1, "%x", &j[8])) last = (j[6] << 16) + j[8]; } else if (NULL != slash) { if (1 == sscanf(slash + 1, "%d", &j[8]) && j[8] >= 112 && j[8] <= 128) { j[8] -= 96; mask = (32 == j[8]) ? 0xffffffff : ~(0xffffffff >> j[8]); network = first & mask; broadcast = network + ~mask; first = network + 1; zabbix_log(LOG_LEVEL_DEBUG, "%s() IPv6 CIDR:%u", __function_name, j[8] + 96); zbx_snprintf(ip, sizeof(ip), "%x:%x:%x:%x:%x:%x:%x:%x", 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, (mask & 0xffff0000) >> 16, (mask & 0x0000ffff)); zabbix_log(LOG_LEVEL_DEBUG, "%s() IPv6 Netmask:'%s'", __function_name, collapse_ipv6(ip, sizeof(ip))); zbx_snprintf(ip, sizeof(ip), "%x:%x:%x:%x:%x:%x:%x:%x", j[0], j[1], j[2], j[3], j[4], j[5], (network & 0xffff0000) >> 16, (network & 0x0000ffff)); zabbix_log(LOG_LEVEL_DEBUG, "%s() IPv6 Network:'%s'", __function_name, collapse_ipv6(ip, sizeof(ip))); zbx_snprintf(ip, sizeof(ip), "%x:%x:%x:%x:%x:%x:%x:%x", j[0], j[1], j[2], j[3], j[4], j[5], (broadcast & 0xffff0000) >> 16, (broadcast & 0x0000ffff)); zabbix_log(LOG_LEVEL_DEBUG, "%s() IPv6 Broadcast:'%s'", __function_name, collapse_ipv6(ip, sizeof(ip))); if (j[8] <= 30) last = broadcast - 1; } } else