void test_send (l2net_154 *l2, l2addr_154 *dest) { Msg *m1 = initMsg(l2) ; Msg *m2 = initMsg(l2) ; bool ok ; option *up1 = initOptionOpaque(MO_Uri_Path, PATH1, sizeof PATH1 - 1) ; option *up2 = initOptionOpaque(MO_Uri_Path, PATH2, sizeof PATH2 - 1) ; option *up3 = initOptionOpaque(MO_Uri_Path, PATH3, sizeof PATH3 - 1) ; option *ocf = initOptionOpaque(MO_Content_Format, "abc", sizeof "abc" - 1) ; set_id (m1, 258) ; set_type (m1, COAP_TYPE_NON) ; push_option (m1, ocf) ; push_option (m1, up1) ; push_option (m1, up2) ; push_option (m1, up3) ; ok = sendMsg (m1, dest) ; res_send (1, ok) ; set_id (m2, 33) ; set_type (m2, COAP_TYPE_CON) ; push_option (m2, ocf) ; ok = sendMsg (m2, dest) ; res_send (2, ok) ; }
int bdd_send_reponse ( char *texte, int id, int code ) { // On prépare la réponse int taille = strlen ( texte ) + 20 ; char* reponse = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( reponse, '\0', taille ) ; sprintf ( reponse, "%d*%d*%s*EOF*", id, code, texte ) ; // On chiffre la réponse int ilen = strlen ( reponse ) ; int olen = taille * 2 ; char* out = (char*) malloc ( olen * sizeof ( char ) ) ; memset ( out, '\0', olen ) ; if ( AES_chiffrement ( reponse, out, olen, &ilen, CHIFFREMENT ) != TRUE ) { free ( reponse ) ; free ( out ) ; return ERRNO ; } // On calcul la nouvelle taille taille = ilen ; if ( ilen < 10 ) taille += 3 ; else if ( ilen < 100 ) taille += 4 ; else if ( ilen < 1000 ) taille += 5 ; else taille += 6 ; // Finalisation de la réponse free ( reponse ) ; reponse = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( reponse, '\0', taille ) ; sprintf ( reponse, "%d*", ilen ) ; if ( ilen < 10 ) memcpy ( &reponse[2], out, ilen ) ; else if ( ilen < 100 ) memcpy ( &reponse[3], out, ilen ) ; else if ( ilen < 1000 ) memcpy ( &reponse[4], out, ilen ) ; else memcpy ( &reponse[5], out, ilen ) ; // On envoie la réponse res_send ( reponse, taille ) ; // Free free ( reponse ) ; free ( out ) ; // On indique que tout s'est bien déroulé return TRUE ; }
static int dns_query(const char *cmd, const char *param, unsigned flags, AGENT_RESULT *result, int short_answer) { #if defined(HAVE_RES_QUERY) || defined(_WINDOWS) size_t offset = 0; int res, type, retrans, retry, i, ret = SYSINFO_RET_FAIL; char ip[MAX_STRING_LEN], zone[MAX_STRING_LEN], tmp[MAX_STRING_LEN], buffer[MAX_STRING_LEN]; struct in_addr inaddr; #ifndef _WINDOWS int saved_nscount, saved_retrans, saved_retry; struct sockaddr_in saved_ns; #endif typedef struct { char *name; int type; } resolv_querytype_t; static const resolv_querytype_t qt[] = { {"ANY", T_ANY}, {"A", T_A}, {"NS", T_NS}, {"MD", T_MD}, {"MF", T_MF}, {"CNAME", T_CNAME}, {"SOA", T_SOA}, {"MB", T_MB}, {"MG", T_MG}, {"MR", T_MR}, {"NULL", T_NULL}, #ifndef _WINDOWS {"WKS", T_WKS}, #endif {"PTR", T_PTR}, {"HINFO", T_HINFO}, {"MINFO", T_MINFO}, {"MX", T_MX}, {"TXT", T_TXT}, {"SRV", T_SRV}, {NULL} }; #ifdef _WINDOWS PDNS_RECORD pQueryResults, pDnsRecord; LPTSTR wzone; char tmp2[MAX_STRING_LEN]; #else char *name; unsigned char *msg_end, *msg_ptr, *p; int num_answers, num_query, q_type, q_class, q_len, value, c, n; struct servent *s; HEADER *hp; struct protoent *pr; #if PACKETSZ > 1024 unsigned char buf[PACKETSZ]; #else unsigned char buf[1024]; #endif typedef union { HEADER h; #if defined(NS_PACKETSZ) unsigned char buffer[NS_PACKETSZ]; #elif defined(PACKETSZ) unsigned char buffer[PACKETSZ]; #else unsigned char buffer[512]; #endif } answer_t; answer_t answer; #endif /* _WINDOWS */ *buffer = '\0'; if (5 < num_param(param)) return SYSINFO_RET_FAIL; if (0 != get_param(param, 1, ip, sizeof(ip))) *ip = '\0'; if (0 != get_param(param, 2, zone, sizeof(zone)) || '\0' == *zone) strscpy(zone, "zabbix.com"); if (0 != get_param(param, 3, tmp, sizeof(tmp)) || '\0' == *tmp) type = T_SOA; else { for (i = 0; NULL != qt[i].name; i++) { #ifdef _WINDOWS if (0 == lstrcmpiA(qt[i].name, tmp)) #else if (0 == strcasecmp(qt[i].name, tmp)) #endif { type = qt[i].type; break; } } if (NULL == qt[i].name) return SYSINFO_RET_FAIL; } if (0 != get_param(param, 4, tmp, sizeof(tmp)) || '\0' == *tmp) retrans = 1; else retrans = atoi(tmp); if (0 != get_param(param, 5, tmp, sizeof(tmp)) || '\0' == *tmp) retry = 2; else retry = atoi(tmp); #ifdef _WINDOWS wzone = zbx_utf8_to_unicode(zone); res = DnsQuery(wzone, type, DNS_QUERY_STANDARD, NULL, &pQueryResults, NULL); zbx_free(wzone); if (1 == short_answer) { SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1); ret = SYSINFO_RET_OK; goto clean; } if (DNS_RCODE_NOERROR != res) return SYSINFO_RET_FAIL; pDnsRecord = pQueryResults; while (NULL != pDnsRecord) { if (DnsSectionAnswer != pDnsRecord->Flags.S.Section) { pDnsRecord = pDnsRecord->pNext; continue; } if (NULL == pDnsRecord->pName) goto clean; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp))); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(pDnsRecord->wType)); switch (pDnsRecord->wType) { case T_A: inaddr.s_addr = pDnsRecord->Data.A.IpAddress; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; case T_NS: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp))); break; case T_MD: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp))); break; case T_MF: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp))); break; case T_CNAME: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp))); break; case T_SOA: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu", zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)), pDnsRecord->Data.SOA.dwSerialNo, pDnsRecord->Data.SOA.dwRefresh, pDnsRecord->Data.SOA.dwRetry, pDnsRecord->Data.SOA.dwExpire, pDnsRecord->Data.SOA.dwDefaultTtl); break; case T_MB: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp))); break; case T_MG: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp))); break; case T_MR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp))); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu", pDnsRecord->Data.Null.dwByteCount); break; case T_PTR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp))); break; case T_HINFO: for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"", zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp))); break; case T_MINFO: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2))); break; case T_MX: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s", pDnsRecord->Data.MX.wPreference, zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp))); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ", zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp))); if (0 < i) offset -= 1; /* remove the trailing space */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s", pDnsRecord->Data.SRV.wPriority, pDnsRecord->Data.SRV.wWeight, pDnsRecord->Data.SRV.wPort, zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp))); break; default: break; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); pDnsRecord = pDnsRecord->pNext; } #else /* not _WINDOWS */ if (-1 == res_init()) /* initialize always, settings might have changed */ return SYSINFO_RET_FAIL; if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf)))) return SYSINFO_RET_FAIL; if ('\0' != *ip) { if (0 == inet_aton(ip, &inaddr)) return SYSINFO_RET_FAIL; memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in)); saved_nscount = _res.nscount; _res.nsaddr_list[0].sin_addr = inaddr; _res.nsaddr_list[0].sin_family = AF_INET; _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); _res.nscount = 1; } saved_retrans = _res.retrans; saved_retry = _res.retry; _res.retrans = retrans; _res.retry = retry; res = res_send(buf, res, answer.buffer, sizeof(answer.buffer)); _res.retrans = saved_retrans; _res.retry = saved_retry; if ('\0' != *ip) { memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in)); _res.nscount = saved_nscount; } hp = (HEADER *)answer.buffer; if (1 == short_answer) { SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1); return SYSINFO_RET_OK; } if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res) return SYSINFO_RET_FAIL; msg_end = answer.buffer + res; num_answers = ntohs(answer.h.ancount); num_query = ntohs(answer.h.qdcount); msg_ptr = answer.buffer + HFIXEDSZ; /* skipping query records */ for (; 0 < num_query && msg_ptr < msg_end; num_query--) msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ; for (; 0 < num_answers && msg_ptr < msg_end; num_answers--) { if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name); GETSHORT(q_type, msg_ptr); GETSHORT(q_class, msg_ptr); msg_ptr += INT32SZ; /* skipping TTL */ GETSHORT(q_len, msg_ptr); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type)); switch (q_type) { case T_A: switch (q_class) { case C_IN: case C_HS: memcpy(&inaddr, msg_ptr, INADDRSZ); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; default: ; } msg_ptr += q_len; break; case T_NS: case T_CNAME: case T_MB: case T_MD: case T_MF: case T_MG: case T_MR: case T_PTR: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_MX: GETSHORT(value, msg_ptr); /* preference */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* exchange */ return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_SOA: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* source host */ return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* administrator */ return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); GETLONG(value, msg_ptr); /* serial number */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* refresh time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* retry time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* expire time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* minimum TTL */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len); msg_ptr += q_len; break; case T_WKS: if (INT32SZ + 1 > q_len) return SYSINFO_RET_FAIL; p = msg_ptr + q_len; memcpy(&inaddr, msg_ptr, INADDRSZ); msg_ptr += INT32SZ; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); if (NULL != (pr = getprotobynumber(*msg_ptr))) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr); msg_ptr++; n = 0; while (msg_ptr < p) { c = *msg_ptr++; do { if (0 != (c & 0200)) { s = getservbyport((int)htons(n), pr ? pr->p_name : NULL); if (NULL != s) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n); } c <<= 1; } while (0 != (++n & 07)); } break; case T_HINFO: p = msg_ptr + q_len; c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } if (msg_ptr < p) { c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } } break; case T_MINFO: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox responsible for mailing lists */ return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox for error messages */ return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); p = msg_ptr + q_len; while (msg_ptr < p) { for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++); } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: GETSHORT(value, msg_ptr); /* priority */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* weight */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* port */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* target */ return SYSINFO_RET_FAIL; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; default: msg_ptr += q_len; break; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); } #endif /* _WINDOWS */ if (0 != offset) buffer[--offset] = '\0'; SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer)); ret = SYSINFO_RET_OK; #ifdef _WINDOWS clean: if (DNS_RCODE_NOERROR == res) DnsRecordListFree(pQueryResults, DnsFreeRecordList); #endif return ret; #else /* both HAVE_RES_QUERY and _WINDOWS not defined */ return SYSINFO_RET_FAIL; #endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */ }
void bdd_send_msg ( int id, int flag, char* texte, int chiffre ) { // Initialisation char* trame = (char*) malloc ( TAILLE_MAX_TRAME * sizeof ( char ) ) ; memset ( trame, '\0', TAILLE_MAX_TRAME ) ; // On créé le message sprintf ( trame, "%d*%d*%s*EOF*", id, flag, texte ) ; int ilen = strlen ( trame ) ; // Chiffré ou non ? if ( chiffre == TRUE ) { // On chiffre le message int olen = strlen ( trame ) * 2 ; char* out = (char*) malloc ( olen * sizeof ( char ) ) ; memset ( out, '\0', olen ) ; if ( AES_chiffrement ( trame, out, olen, &ilen, CHIFFREMENT ) != TRUE ) { free ( out ) ; free ( trame ) ; } else { // On calcul la nouvelle taille int taille = ilen ; if ( ilen < 10 ) taille += 3 ; else if ( ilen < 100 ) taille += 4 ; else if ( ilen < 1000 ) taille += 5 ; else taille += 6 ; // Finalisation de la réponse free ( trame ) ; trame = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( trame, '\0', taille ) ; sprintf ( trame, "%d*", ilen ) ; if ( ilen < 10 ) memcpy ( &trame[2], out, ilen ) ; else if ( ilen < 100 ) memcpy ( &trame[3], out, ilen ) ; else if ( ilen < 1000 ) memcpy ( &trame[4], out, ilen ) ; else memcpy ( &trame[5], out, ilen ) ; // On envoie la réponse res_send ( trame, taille ) ; // Free free ( trame ) ; free ( out ) ; } } else if ( chiffre == FALSE ) { // On envoi le message res_send ( trame, ilen ) ; // Free free ( trame ) ; } }
static int dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_answer) { #if defined(HAVE_RES_QUERY) || defined(_WINDOWS) size_t offset = 0; int res, type, retrans, retry, use_tcp, i, ret = SYSINFO_RET_FAIL, ip_type = AF_INET; char *ip, zone[MAX_STRING_LEN], buffer[MAX_STRING_LEN], *zone_str, *param, tmp[MAX_STRING_LEN]; struct in_addr inaddr; struct in6_addr in6addr; #ifndef _WINDOWS #if defined(HAVE_RES_NINIT) && !defined(_AIX) /* It seems that on some AIX systems with no updates installed res_ninit() can */ /* corrupt stack (see ZBX-14559). Use res_init() on AIX. */ struct __res_state res_state_local; #else /* thread-unsafe resolver API */ int saved_retrans, saved_retry, saved_nscount = 0; unsigned long saved_options; struct sockaddr_in saved_ns; # if defined(HAVE_RES_U_EXT) /* thread-unsafe resolver API /Linux/ */ int save_nssocks, saved_nscount6; # endif #endif #if defined(HAVE_RES_EXT_EXT) /* AIX */ union res_sockaddr_union saved_ns6; #elif defined(HAVE_RES_U_EXT_EXT) /* BSD */ struct sockaddr_in6 saved_ns6; #else struct sockaddr_in6 *saved_ns6; #endif struct sockaddr_in6 sockaddrin6; struct addrinfo hint, *hres = NULL; #endif typedef struct { const char *name; int type; } resolv_querytype_t; static const resolv_querytype_t qt[] = { {"ANY", T_ANY}, {"A", T_A}, {"AAAA", T_AAAA}, {"NS", T_NS}, {"MD", T_MD}, {"MF", T_MF}, {"CNAME", T_CNAME}, {"SOA", T_SOA}, {"MB", T_MB}, {"MG", T_MG}, {"MR", T_MR}, {"NULL", T_NULL}, #ifndef _WINDOWS {"WKS", T_WKS}, #endif {"PTR", T_PTR}, {"HINFO", T_HINFO}, {"MINFO", T_MINFO}, {"MX", T_MX}, {"TXT", T_TXT}, {"SRV", T_SRV}, {NULL} }; #ifdef _WINDOWS PDNS_RECORD pQueryResults, pDnsRecord; wchar_t *wzone; char tmp2[MAX_STRING_LEN]; DWORD options; #else char *name; unsigned char *msg_end, *msg_ptr, *p; int num_answers, num_query, q_type, q_class, q_len, value, c, n; struct servent *s; HEADER *hp; struct protoent *pr; #if PACKETSZ > 1024 unsigned char buf[PACKETSZ]; #else unsigned char buf[1024]; #endif typedef union { HEADER h; #if defined(NS_PACKETSZ) unsigned char buffer[NS_PACKETSZ]; #elif defined(PACKETSZ) unsigned char buffer[PACKETSZ]; #else unsigned char buffer[512]; #endif } answer_t; answer_t answer; #endif /* _WINDOWS */ zbx_vector_str_t answers; *buffer = '\0'; if (6 < request->nparam) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters.")); return SYSINFO_RET_FAIL; } ip = get_rparam(request, 0); zone_str = get_rparam(request, 1); #ifndef _WINDOWS memset(&hint, '\0', sizeof(hint)); hint.ai_family = PF_UNSPEC; hint.ai_flags = AI_NUMERICHOST; if (NULL != ip && '\0' != *ip && 0 == getaddrinfo(ip, NULL, &hint, &hres) && AF_INET6 == hres->ai_family) ip_type = hres->ai_family; if (NULL != hres) freeaddrinfo(hres); #endif if (NULL == zone_str || '\0' == *zone_str) strscpy(zone, "zabbix.com"); else strscpy(zone, zone_str); param = get_rparam(request, 2); if (NULL == param || '\0' == *param) type = T_SOA; else { for (i = 0; NULL != qt[i].name; i++) { if (0 == strcasecmp(qt[i].name, param)) { type = qt[i].type; break; } } if (NULL == qt[i].name) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter.")); return SYSINFO_RET_FAIL; } } param = get_rparam(request, 3); if (NULL == param || '\0' == *param) retrans = 1; else if (SUCCEED != is_uint31(param, &retrans) || 0 == retrans) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fourth parameter.")); return SYSINFO_RET_FAIL; } param = get_rparam(request, 4); if (NULL == param || '\0' == *param) retry = 2; else if (SUCCEED != is_uint31(param, &retry) || 0 == retry) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid fifth parameter.")); return SYSINFO_RET_FAIL; } param = get_rparam(request, 5); if (NULL == param || '\0' == *param || 0 == strcmp(param, "udp")) use_tcp = 0; else if (0 == strcmp(param, "tcp")) use_tcp = 1; else { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid sixth parameter.")); return SYSINFO_RET_FAIL; } #ifdef _WINDOWS options = DNS_QUERY_STANDARD | DNS_QUERY_BYPASS_CACHE; if (0 != use_tcp) options |= DNS_QUERY_USE_TCP_ONLY; wzone = zbx_utf8_to_unicode(zone); res = DnsQuery(wzone, type, options, NULL, &pQueryResults, NULL); zbx_free(wzone); if (1 == short_answer) { SET_UI64_RESULT(result, DNS_RCODE_NOERROR != res ? 0 : 1); ret = SYSINFO_RET_OK; goto clean_dns; } if (DNS_RCODE_NOERROR != res) { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot perform DNS query: [%d]", res)); return SYSINFO_RET_FAIL; } pDnsRecord = pQueryResults; zbx_vector_str_create(&answers); while (NULL != pDnsRecord) { if (DnsSectionAnswer != pDnsRecord->Flags.S.Section) { pDnsRecord = pDnsRecord->pNext; continue; } if (NULL == pDnsRecord->pName) goto clean; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", zbx_unicode_to_utf8_static(pDnsRecord->pName, tmp, sizeof(tmp))); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(pDnsRecord->wType)); switch (pDnsRecord->wType) { case T_A: inaddr.s_addr = pDnsRecord->Data.A.IpAddress; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; case T_AAAA: memcpy(&in6addr.s6_addr, &(pDnsRecord->Data.AAAA.Ip6Address), sizeof(in6addr.s6_addr)); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp))); break; case T_NS: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.NS.pNameHost, tmp, sizeof(tmp))); break; case T_MD: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MD.pNameHost, tmp, sizeof(tmp))); break; case T_MF: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MF.pNameHost, tmp, sizeof(tmp))); break; case T_CNAME: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.CNAME.pNameHost, tmp, sizeof(tmp))); break; case T_SOA: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s %lu %lu %lu %lu %lu", zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNamePrimaryServer, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.SOA.pNameAdministrator, tmp2, sizeof(tmp2)), pDnsRecord->Data.SOA.dwSerialNo, pDnsRecord->Data.SOA.dwRefresh, pDnsRecord->Data.SOA.dwRetry, pDnsRecord->Data.SOA.dwExpire, pDnsRecord->Data.SOA.dwDefaultTtl); break; case T_MB: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MB.pNameHost, tmp, sizeof(tmp))); break; case T_MG: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MG.pNameHost, tmp, sizeof(tmp))); break; case T_MR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MR.pNameHost, tmp, sizeof(tmp))); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%lu", pDnsRecord->Data.Null.dwByteCount); break; case T_PTR: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.PTR.pNameHost, tmp, sizeof(tmp))); break; case T_HINFO: for (i = 0; i < (int)(pDnsRecord->Data.HINFO.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%s\"", zbx_unicode_to_utf8_static(pDnsRecord->Data.HINFO.pStringArray[i], tmp, sizeof(tmp))); break; case T_MINFO: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s %s", zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameMailbox, tmp, sizeof(tmp)), zbx_unicode_to_utf8_static(pDnsRecord->Data.MINFO.pNameErrorsMailbox, tmp2, sizeof(tmp2))); break; case T_MX: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %s", pDnsRecord->Data.MX.wPreference, zbx_unicode_to_utf8_static(pDnsRecord->Data.MX.pNameExchange, tmp, sizeof(tmp))); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); for (i = 0; i < (int)(pDnsRecord->Data.TXT.dwStringCount); i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s ", zbx_unicode_to_utf8_static(pDnsRecord->Data.TXT.pStringArray[i], tmp, sizeof(tmp))); if (0 < i) offset -= 1; /* remove the trailing space */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %hu %hu %hu %s", pDnsRecord->Data.SRV.wPriority, pDnsRecord->Data.SRV.wWeight, pDnsRecord->Data.SRV.wPort, zbx_unicode_to_utf8_static(pDnsRecord->Data.SRV.pNameTarget, tmp, sizeof(tmp))); break; default: break; } zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); pDnsRecord = pDnsRecord->pNext; zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer)); offset = 0; *buffer = '\0'; } #else /* not _WINDOWS */ #if defined(HAVE_RES_NINIT) && !defined(_AIX) memset(&res_state_local, 0, sizeof(res_state_local)); if (-1 == res_ninit(&res_state_local)) /* initialize always, settings might have changed */ #else if (-1 == res_init()) /* initialize always, settings might have changed */ #endif { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot initialize DNS subsystem: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } #if defined(HAVE_RES_NINIT) && !defined(_AIX) if (-1 == (res = res_nmkquery(&res_state_local, QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf)))) #else if (-1 == (res = res_mkquery(QUERY, zone, C_IN, type, NULL, 0, NULL, buf, sizeof(buf)))) #endif { SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot create DNS query: %s", zbx_strerror(errno))); return SYSINFO_RET_FAIL; } if (NULL != ip && '\0' != *ip && AF_INET == ip_type) { if (0 == inet_aton(ip, &inaddr)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IP address.")); return SYSINFO_RET_FAIL; } #if defined(HAVE_RES_NINIT) && !defined(_AIX) res_state_local.nsaddr_list[0].sin_addr = inaddr; res_state_local.nsaddr_list[0].sin_family = AF_INET; res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); res_state_local.nscount = 1; #else /* thread-unsafe resolver API */ memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in)); saved_nscount = _res.nscount; _res.nsaddr_list[0].sin_addr = inaddr; _res.nsaddr_list[0].sin_family = AF_INET; _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); _res.nscount = 1; #endif } else if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type) { if (0 == inet_pton(ip_type, ip, &in6addr)) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid IPv6 address.")); return SYSINFO_RET_FAIL; } memset(&sockaddrin6, '\0', sizeof(sockaddrin6)); #if defined(HAVE_RES_SIN6_LEN) sockaddrin6.sin6_len = sizeof(sockaddrin6); #endif sockaddrin6.sin6_family = AF_INET6; sockaddrin6.sin6_addr = in6addr; sockaddrin6.sin6_port = htons(ZBX_DEFAULT_DNS_PORT); #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) memset(&res_state_local.nsaddr_list[0], '\0', sizeof(res_state_local.nsaddr_list[0])); # ifdef HAVE_RES_U_EXT /* Linux */ saved_ns6 = res_state_local._u._ext.nsaddrs[0]; res_state_local._u._ext.nsaddrs[0] = &sockaddrin6; res_state_local._u._ext.nssocks[0] = -1; res_state_local._u._ext.nscount6 = 1; /* CentOS */ # elif HAVE_RES_U_EXT_EXT /* BSD */ if (NULL != res_state_local._u._ext.ext) memcpy(res_state_local._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6)); res_state_local.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); # endif res_state_local.nscount = 1; #else memcpy(&saved_ns, &(_res.nsaddr_list[0]), sizeof(struct sockaddr_in)); saved_nscount = _res.nscount; # if defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT) || defined(HAVE_RES_EXT_EXT) memset(&_res.nsaddr_list[0], '\0', sizeof(_res.nsaddr_list[0])); _res.nscount = 1; # endif # if defined(HAVE_RES_U_EXT) /* thread-unsafe resolver API /Linux/ */ saved_nscount6 = _res._u._ext.nscount6; saved_ns6 = _res._u._ext.nsaddrs[0]; save_nssocks = _res._u._ext.nssocks[0]; _res._u._ext.nsaddrs[0] = &sockaddrin6; _res._u._ext.nssocks[0] = -1; _res._u._ext.nscount6 = 1; # elif defined(HAVE_RES_U_EXT_EXT) /* thread-unsafe resolver API /BSD/ */ memcpy(&saved_ns6, _res._u._ext.ext, sizeof(saved_ns6)); _res.nsaddr_list[0].sin_port = htons(ZBX_DEFAULT_DNS_PORT); if (NULL != _res._u._ext.ext) memcpy(_res._u._ext.ext, &sockaddrin6, sizeof(sockaddrin6)); # elif defined(HAVE_RES_EXT_EXT) /* thread-unsafe resolver API /AIX/ */ memcpy(&saved_ns6, &(_res._ext.ext.nsaddrs[0]), sizeof(saved_ns6)); memcpy(&_res._ext.ext.nsaddrs[0], &sockaddrin6, sizeof(sockaddrin6)); # endif /* #if defined(HAVE_RES_U_EXT) */ #endif /* #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) */ } #if defined(HAVE_RES_NINIT) && !defined(_AIX) && (defined(HAVE_RES_U_EXT) || defined(HAVE_RES_U_EXT_EXT)) if (0 != use_tcp) res_state_local.options |= RES_USEVC; res_state_local.retrans = retrans; res_state_local.retry = retry; res = res_nsend(&res_state_local, buf, res, answer.buffer, sizeof(answer.buffer)); # ifdef HAVE_RES_U_EXT /* Linux */ if (NULL != ip && '\0' != *ip && AF_INET6 == ip_type) res_state_local._u._ext.nsaddrs[0] = saved_ns6; # endif # ifdef HAVE_RES_NDESTROY res_ndestroy(&res_state_local); # else res_nclose(&res_state_local); # endif #else /* thread-unsafe resolver API */ saved_options = _res.options; saved_retrans = _res.retrans; saved_retry = _res.retry; if (0 != use_tcp) _res.options |= RES_USEVC; _res.retrans = retrans; _res.retry = retry; res = res_send(buf, res, answer.buffer, sizeof(answer.buffer)); _res.options = saved_options; _res.retrans = saved_retrans; _res.retry = saved_retry; if (NULL != ip && '\0' != *ip) { if (AF_INET6 == ip_type) { # if defined(HAVE_RES_U_EXT) /* Linux */ _res._u._ext.nsaddrs[0] = saved_ns6; _res._u._ext.nssocks[0] = save_nssocks; _res._u._ext.nscount6 = saved_nscount6; # elif defined(HAVE_RES_U_EXT_EXT) /* BSD */ if (NULL != _res._u._ext.ext) memcpy(_res._u._ext.ext, &saved_ns6, sizeof(saved_ns6)); # elif defined(HAVE_RES_EXT_EXT) /* AIX */ memcpy(&_res._ext.ext.nsaddrs[0], &saved_ns6, sizeof(saved_ns6)); # endif } memcpy(&(_res.nsaddr_list[0]), &saved_ns, sizeof(struct sockaddr_in)); _res.nscount = saved_nscount; } #endif hp = (HEADER *)answer.buffer; if (1 == short_answer) { SET_UI64_RESULT(result, NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res ? 0 : 1); return SYSINFO_RET_OK; } if (NOERROR != hp->rcode || 0 == ntohs(hp->ancount) || -1 == res) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot perform DNS query.")); return SYSINFO_RET_FAIL; } msg_end = answer.buffer + res; num_answers = ntohs(answer.h.ancount); num_query = ntohs(answer.h.qdcount); msg_ptr = answer.buffer + HFIXEDSZ; zbx_vector_str_create(&answers); /* skipping query records */ for (; 0 < num_query && msg_ptr < msg_end; num_query--) msg_ptr += dn_skipname(msg_ptr, msg_end) + QFIXEDSZ; for (; 0 < num_answers && msg_ptr < msg_end; num_answers--) { if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); ret = SYSINFO_RET_FAIL; goto clean; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%-20s", name); GETSHORT(q_type, msg_ptr); GETSHORT(q_class, msg_ptr); msg_ptr += INT32SZ; /* skipping TTL */ GETSHORT(q_len, msg_ptr); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type)); switch (q_type) { case T_A: switch (q_class) { case C_IN: case C_HS: memcpy(&inaddr, msg_ptr, INADDRSZ); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); break; default: ; } msg_ptr += q_len; break; case T_AAAA: switch (q_class) { case C_IN: case C_HS: memcpy(&in6addr, msg_ptr, IN6ADDRSZ); offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntop(AF_INET6, &in6addr, tmp, sizeof(tmp))); break; default: ; } msg_ptr += q_len; break; case T_NS: case T_CNAME: case T_MB: case T_MD: case T_MF: case T_MG: case T_MR: case T_PTR: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_MX: GETSHORT(value, msg_ptr); /* preference */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* exchange */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_SOA: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* source host */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* administrator */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); GETLONG(value, msg_ptr); /* serial number */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* refresh time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* retry time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* expire time */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETLONG(value, msg_ptr); /* minimum TTL */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); break; case T_NULL: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " len:%d", q_len); msg_ptr += q_len; break; case T_WKS: if (INT32SZ + 1 > q_len) { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } p = msg_ptr + q_len; memcpy(&inaddr, msg_ptr, INADDRSZ); msg_ptr += INT32SZ; offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", inet_ntoa(inaddr)); if (NULL != (pr = getprotobynumber(*msg_ptr))) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", pr->p_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", (int)*msg_ptr); msg_ptr++; n = 0; while (msg_ptr < p) { c = *msg_ptr++; do { if (0 != (c & 0200)) { s = getservbyport((int)htons(n), pr ? pr->p_name : NULL); if (NULL != s) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", s->s_name); else offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " #%d", n); } c <<= 1; } while (0 != (++n & 07)); } break; case T_HINFO: p = msg_ptr + q_len; c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } if (msg_ptr < p) { c = *msg_ptr++; if (0 != c) { offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \"%.*s\"", c, msg_ptr); msg_ptr += c; } } break; case T_MINFO: if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox responsible for mailing lists */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* mailbox for error messages */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; case T_TXT: offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " \""); p = msg_ptr + q_len; while (msg_ptr < p) { for (c = *msg_ptr++; 0 < c && msg_ptr < p; c--) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%c", *msg_ptr++); } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\""); break; case T_SRV: GETSHORT(value, msg_ptr); /* priority */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* weight */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); GETSHORT(value, msg_ptr); /* port */ offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %d", value); if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr))) /* target */ { SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response.")); return SYSINFO_RET_FAIL; } offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name); break; default: msg_ptr += q_len; break; } zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "\n"); zbx_vector_str_append(&answers, zbx_strdup(NULL, buffer)); offset = 0; *buffer = '\0'; } #endif /* _WINDOWS */ zbx_vector_str_sort(&answers, ZBX_DEFAULT_STR_COMPARE_FUNC); for (i = 0; i < answers.values_num; i++) offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, "%s", answers.values[i]); if (0 != offset) buffer[--offset] = '\0'; SET_TEXT_RESULT(result, zbx_strdup(NULL, buffer)); ret = SYSINFO_RET_OK; clean: zbx_vector_str_clear_ext(&answers, zbx_str_free); zbx_vector_str_destroy(&answers); #ifdef _WINDOWS clean_dns: if (DNS_RCODE_NOERROR == res) DnsRecordListFree(pQueryResults, DnsFreeRecordList); #endif return ret; #else /* both HAVE_RES_QUERY and _WINDOWS not defined */ return SYSINFO_RET_FAIL; #endif /* defined(HAVE_RES_QUERY) || defined(_WINDOWS) */ }
main () { int i, j, hl, rc, qc, ac, p, a; int op, class, type, datalen, buflen, msgl; u_short qtype, qclass, rtype, rclass, l, l2; u_long rttl; u_char buf[100], *cp; char dn[100], *dname, *z, ping[50]; struct rrec newrr, *rec; union { char cdat[4]; unsigned long ldat; struct in_addr adat; } dat; union { u_char data[DATALEN]; HEADER head; } data; hl = sizeof (HEADER); signal (SIGALRM, tfunc); res_init(); printf ("Inhalt von resolv.conf\n"); printf ("domain: %s\n", _res.defdname); /* printf ("MAXDNSRCH = %d\n", MAXDNSRCH); for (i=0; i<MAXDNSRCH; i++) printf ("%s\n", _res.dnsrch[i]); */ printf ("%d Name-Server\n", MAXNS); for (i=0; i<MAXNS; i++) printf ("%s\n", inet_ntoa(_res.nsaddr_list[i].sin_addr)); /* printf ("number of addresses: %d \n", _res.ascount); printf ("number of name servers: %d \n", _res.nscount); */ /*printf ("%d %s\n", _res.ascount, inet_ntoa(_res.sort_list[0]));*/ /* strcpy (dn, "zeus.rz.htwk-leipzig.de"); */ /* strcpy (dn, "caramba.cs.tu-berlin.de"); */ /* strcpy (dn, "ftp.cs.tu-berlin.de"); */ /* strcpy (dn, "moses.imn.htwk-leipzig.de"); */ /* strcpy (dn, "moses"); */ do { printf ("\nSuche nach IP-Adresse von\n"); printf ("Hostname: "); z = gets (dn); printf ("\n"); if (z) { dname = dn; strcpy (data.data, dn); datalen = strlen(dn)+1; op = QUERY; buflen = sizeof(buf); /* _res.options |= RES_DEBUG; */ _res.retrans = 10; _res.retry = 2; class = C_IN; type = T_A; rc=res_mkquery (op, dname, class, type, data.data, datalen, &newrr, buf, buflen); buflen = rc; alarm (10); msgl=res_send (buf, buflen, data.data, DATALEN); if (msgl>0) { /* printf ("\nsend: %d\n", msgl); */ /* for (i=0; i< msgl; i++) { for (j=0; j<4; j++) dat.cdat[j] = data.data[i+j]; */ /* printf ("%x ", dat.ldat); if (dat.ldat==x) printf ("\n%d %x\n", i, dat.ldat); } printf ("\n"); */ /* for (i=0; i< msgl;i++) { j = data.data[i] & 0xff; printf ("%2x ", j); } printf ("\n"); for (i=0; i< msgl;i++) if (data.data[i]>31) printf ("%c ", data.data[i]); printf ("\n"); */ /* printf ("%x \n", x); */ ac = data.head.ancount; qc = data.head.qdcount; p = hl; printf ("Query\n"); while (qc) { l = data.data[p]; while (l > 0 && l < 64) { /* printf ("%d \n", p); */ for (i=1; i<=l; i++) putchar (data.data[p+i]); p = p + l + 1; l = data.data[p]; if (l) putchar ('.'); } putchar ('\n'); p++; cp = data.data+p; /* GETSHORT verlangt Pointervariable !! */ /* einfache Zuweisung (auch mit cast) ergibt falsche Werte evtl. Probleme mit integralen Grenzen ?? */ GETSHORT (qtype, cp); /* oder: qtype = _getshort(data.data+p);*/ p = p + sizeof(u_short); cp = data.data+p; GETSHORT (qclass, cp); p = p + sizeof(u_short); cp = data.data+p; printf ("QTYPE=%d, QCLASS=%d", qtype, qclass); qc--; putchar ('\n'); } printf ("\n%d Answers\n", ac); a=1; while (ac) { printf ("%d.\n", a); l = data.data[p]; while (l > 0 && l < 64) { /* printf ("%d \n", p); */ for (i=1; i<=l; i++) putchar (data.data[p+i]); p = p + l + 1; l = data.data[p]; if (l) putchar ('.'); else putchar ('\n'); } if (l>63) { rc=dn_expand (data.data, data.data+msgl, cp, buf, buflen); printf ("%s\n", buf); p += 2; } else p++; cp = data.data+p; GETSHORT (rtype, cp); p = p + sizeof(u_short); cp = data.data+p; GETSHORT (rclass, cp); p = p + sizeof(u_short); cp = data.data+p; GETLONG (rttl, cp); p = p + sizeof(u_long); printf ("RRTYPE=%d, RRCLASS=%d RRTTL=%d\n", rtype, rclass, rttl); cp = data.data+p; GETSHORT (l, cp); p = p + sizeof(u_short); if (rtype == 1) { for (j = 0; j< l; j++) dat.cdat[j] = data.data[p+j]; /* printf ("IP-Adresse: %x \n", dat.ldat); */ printf ("IP-Adresse: %s \n", inet_ntoa (dat.adat)); sprintf (buf, "%s", inet_ntoa (dat.adat)); strcpy (ping, "ping "); strcat (ping, buf); strcat (ping, " 10"); printf ("%s\n", ping); system (ping); p += l; } if (rtype == 5) { l2 = l; l = data.data[p]; while (l > 0 && l < 64) { /* printf ("%d \n", p); */ for (i=1; i<=l; i++) putchar (data.data[p+i]); p = p + l + 1; l = data.data[p]; if (l) putchar ('.'); else putchar('\n'); } if (l>63) { rc=dn_expand (data.data, data.data+msgl, cp, buf, buflen); printf ("%s\n", buf); p += 2; } else p++; l = l2; } putchar ('\n'); ac--; a++; } } else printf ("not found\n"); } } while (z); }
int bdd_do_insert ( char *safe_trame ) { // Déclaration variable Ref modele ; // Modèle propre à la trame qui sera appliqué en requête sur la BDD char* morceau = NULL ; // Variable contenant chaque morceau de la trame (strtok_r) char* safe_morceau = NULL ; // Variable contenant chaque morceau de la trame (strtok_r) char* groupes = NULL ; char* groupes_test = NULL ; int groupes_free = FALSE ; char* valeur = NULL ; char* user = NULL ; char* politiques = NULL ; char* politiques_test = NULL ; int politiques_free = FALSE ; int cpt = 0 ; // Compteur // On découpe les 7 éléments restant de notre trame for ( cpt = 0; cpt < 7; cpt++ ) { // On découpe la trame en morceaux repérés via un "*" if ( ( morceau = strtok_r ( NULL, "*", &safe_trame ) ) == NULL ) { perror ( "Erreur_bdd_do_insert : information manquante " ) ; if ( politiques_free == TRUE ) free ( politiques ) ; if ( groupes_free == TRUE ) free ( groupes ) ; bdd_send_msg ( INSERT, "ERROR" ) ; return ERRNO ; } // On vérifie que l'information est présente if ( strcmp ( morceau, "EOF") == 0 ) { perror ( "Erreur_bdd_do_insert : information manquante II " ) ; if ( politiques_free == TRUE ) free ( politiques ) ; if ( groupes_free == TRUE ) free ( groupes ) ; bdd_send_msg ( INSERT, "ERROR" ) ; return ERRNO ; } else { // On affecte l'information switch ( cpt ) { case ZERO : modele.statut = multiple ( calculate_SHA256 ( morceau ) ) ; break ; case UN : modele.affectation = multiple ( calculate_SHA256 ( morceau ) ) ; break ; case DEUX : groupes_test = morceau ; groupes = (char*) malloc ( ( strlen ( groupes_test ) + 1 ) * sizeof ( char ) ) ; memset ( groupes, '\0', strlen ( groupes_test ) + 1 ) ; sprintf ( groupes, "%s", groupes_test ) ; groupes_free = TRUE ; break ; case TROIS : modele.type = multiple ( calculate_SHA256 ( morceau ) ) ; break ; case QUATRE : valeur = morceau ; break ; case CINQ : user = morceau ; break ; case SIX : politiques_test = morceau ; politiques = (char*) malloc ( ( strlen ( politiques_test ) + 1 ) * sizeof ( char ) ) ; memset ( politiques, '\0', strlen ( politiques_test ) + 1 ) ; sprintf ( politiques, "%s", politiques_test ) ; politiques_free = TRUE ; break ; default : perror ( "Erreur_do_insert : overflow compteur cpt " ) ; if ( politiques_free == TRUE ) free ( politiques ) ; if ( groupes_free == TRUE ) free ( groupes ) ; bdd_send_msg ( INSERT, "ERROR" ) ; return ERRNO ; break ; } } } // On vérifie le format des politiques morceau = NULL ; cpt = 0 ; do { // On découpe if ( cpt == 0 ) morceau = strtok_r ( politiques_test, "$", &safe_morceau ) ; else morceau = strtok_r ( NULL, "$", &safe_morceau ) ; // On inc cpt cpt++ ; } while ( morceau != NULL ) ; if ( cpt != 4 ) { perror ( "Erreur_bdd_do_insert : politiques() " ) ; free ( politiques ) ; free ( groupes ) ; bdd_send_msg ( INSERT, "ERROR" ) ; return ERRNO ; } // On compte le nombre de groupes morceau = NULL ; safe_morceau = NULL ; int nbr_grp = 0 ; do { // On découpe if ( nbr_grp == 0 ) morceau = strtok_r ( groupes_test, ";", &safe_morceau ) ; else morceau = strtok_r ( NULL, ";", &safe_morceau ) ; // On inc cpt nbr_grp++ ; } while ( morceau != NULL ) ; // PHASE 2 // Déclaration variables char* reference_str = NULL ; char* valeur_finale = NULL ; char* reponse = NULL ; char* temporaire = NULL ; int first = TRUE ; unsigned long taille = 0 ; // Ini reference_str = (char*) malloc ( TAILLE_MAX_REF * sizeof ( char ) ) ; memset ( reference_str, '\0', TAILLE_MAX_REF ) ; taille = strlen ( valeur ) + strlen ( user ) + strlen ( politiques ) + 3 ; valeur_finale = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( valeur_finale, '\0', taille ) ; temporaire = (char*) malloc ( TAILLE_MAX_REF * nbr_grp * sizeof ( char ) ) ; memset ( temporaire, '\0', TAILLE_MAX_REF * nbr_grp ) ; // On créé autant de référence qu'il y a de groupes morceau = NULL ; safe_morceau = NULL ; cpt = 0 ; do { // On découpe if ( cpt == 0 ) morceau = strtok_r ( groupes, ";", &safe_morceau ) ; else morceau = strtok_r ( NULL, ";", &safe_morceau ) ; // On vérifie if ( morceau != NULL ) { // On prépare la référénce qui va être inséreée en BDD modele.groupe = multiple ( calculate_SHA256 ( morceau ) ) ; memset ( reference_str, '\0', TAILLE_MAX_REF ) ; if ( ref_concatenation ( &modele, reference_str ) == ERRNO ) { perror ( "Erreur_bdd_do_insert : ref_concatenation() " ) ; free ( politiques ) ; free ( reference_str ) ; free ( valeur_finale ) ; free ( groupes ) ; free ( temporaire ) ; bdd_send_msg ( INSERT, "ERROR" ) ; return ERRNO ; } // On prépare la valeur_final qui va être insrérée en BDD memset ( valeur_finale, '\0', taille ) ; sprintf ( valeur_finale, "%s*%s*%s", user, valeur, politiques ) ; // On réalise l'insertion if ( bdd_do_request ( mysql_bdd, INSERT, reference_str, valeur_finale, NULL ) == ERRNO ) { perror ( "Erreur_bdd_do_insert : bdd_do_request() " ) ; free ( politiques ) ; free ( reference_str ) ; free ( valeur_finale ) ; free ( groupes ) ; free ( temporaire ) ; bdd_send_msg ( INSERT, "ERROR" ) ; return ERRNO ; } else nbr_tuples++ ; // On ajoute la référence à la réponse if ( first == TRUE ) { sprintf ( temporaire, "%s", reference_str ) ; first = FALSE ; } else if ( first == FALSE ) sprintf ( temporaire + strlen ( temporaire ), ";%s", reference_str ) ; // On inc cpt cpt++ ; } } while ( morceau != NULL ) ; // On envoie la réponse taille = strlen ( temporaire ) + 10 ; reponse = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( reponse, '\0', taille ) ; sprintf ( reponse, "%d*%s*EOF", INSERT, temporaire ) ; res_send ( reponse ) ; // Free free ( politiques ) ; free ( reference_str ) ; free ( valeur_finale ) ; free ( groupes ) ; free ( temporaire ) ; free ( reponse ) ; // On indique que tout s'est bien déroulé return TRUE ; }
int bdd_search_modele ( MYSQL_RES* resultat_req, Ref* modele ) { // Initialisation Ref reference ; int return_value ; int suite = TRUE ; MYSQL_ROW tuple ; char* user = NULL ; char* safe_tuple = NULL ; // Permet d'appeler strtok_r sur le bon contenu. char* reponse = NULL ; int first = TRUE ; // Initialisation user = (char*) malloc ( TAILLE_HASH_NOM * sizeof ( char ) ) ; memset ( user, '\0', TAILLE_HASH_NOM ) ; // Initialisation char* output = (char*) malloc ( RSA_size ( bdd_key ) * sizeof ( char ) ) ; memset ( output, '\0', RSA_size ( bdd_key ) ) ; // Initialisation char* temporaire = (char*) malloc ( ( TAILLE_MAX_REF + TAILLE_HASH_NOM + 3 ) * nbr_tuples * sizeof ( char ) ) ; memset ( temporaire, '\0', ( TAILLE_MAX_REF + TAILLE_HASH_NOM + 3 ) * nbr_tuples ) ; // On parcourt chaque tuple while ( suite == TRUE ) { // On récupère un tuple if ( ( tuple = mysql_fetch_row ( resultat_req ) ) == NULL ) suite = FALSE ; // On le traite if ( suite == TRUE ) { // On découpe la référence if ( ( return_value = ref_split ( tuple[0], &reference ) ) == ERRNO ) { perror ( "Erreur_bdd_search_modele : ref_split " ) ; free ( user ) ; free ( output ) ; bdd_send_msg ( SEEK, "ERROR" ) ; return ERRNO ; } // On regarde si elle correspond à ce que l'on recherche if ( ( return_value = ref_cmp ( &reference, modele ) ) == ERRNO ) { perror ( "Erreur_bdd_traitement_request : ref_cmp " ) ; free ( user ) ; free ( output ) ; bdd_send_msg ( SEEK, "ERROR" ) ; return ERRNO ; } else if ( return_value == TRUE ) // La référence nous intéresse { // On déchiffre le tuple memset ( output, '\0', RSA_size ( bdd_key ) ) ; if ( RSA_chiffrement ( (unsigned char*) tuple[1], (unsigned char*) output, DECHIFFREMENT ) != TRUE ) { perror ( "Erreur_bdd_serach_modele : RSA_dechiffrement " ) ; free ( output ) ; free ( user ) ; bdd_send_msg ( SEEK, "ERROR" ) ; return ERRNO ; } // On récupère le hash du nom associé memset ( user, '\0', TAILLE_HASH_NOM ) ; sprintf ( user, "%s", strtok_r ( output, "*", &safe_tuple ) ) ; // On ajoute la référence et le nom associé à la réponse if ( first == TRUE ) { sprintf ( temporaire, "%s;%s", tuple[0], user ) ; first = FALSE ; } else if ( first == FALSE ) sprintf ( temporaire + strlen ( temporaire ), "*%s;%s", tuple[0], user ) ; } } } // On envoie la réponse int taille = strlen ( temporaire ) + 10 ; reponse = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( reponse, '\0', taille ) ; sprintf ( reponse, "%d*%s*EOF", SEEK, temporaire ) ; res_send ( reponse ) ; // Free free ( output ) ; free ( user ) ; free ( temporaire ) ; free ( reponse ) ; // On indique que tout s'est bien déroulé return TRUE ; }
int bdd_do_select ( char *safe_trame ) { // Déclaration variable char* morceau = NULL ; // Variable contenant chaque morceau de la trame (strtok_r) char* statut = NULL ; char* affectation = NULL ; char* groupes = NULL ; char* reference = NULL ; int cpt = 0 ; // Compteur MYSQL_RES* resultat_req ; // Object MYSQL décrivant le résultat d'une requête MYSQL_ROW tuple ; // Object MYSQL décrivant un tuple dans la liste résultat char* safe_tuple = NULL ; // Permet d'appeler strtok_r sur le bon contenu. char* valeur = NULL ; char* politique = NULL ; int code_retour = 0 ; // On découpe les 4 éléments restant de notre trame for ( cpt = 0; cpt < 4; cpt++ ) { // On découpe la trame en morceaux repérés via un "*" if ( ( morceau = strtok_r ( NULL, "*", &safe_trame ) ) == NULL ) { perror ( "Erreur_bdd_do_select : information manquante " ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On vérifie que l'information est présente if ( strcmp ( morceau, "EOF") == 0 ) { perror ( "Erreur_bdd_do_select : information manquante II" ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } else { // On affecte l'information switch ( cpt ) { case ZERO : statut = morceau ; break ; case UN : affectation = morceau ; break ; case DEUX : groupes = morceau ; break ; case TROIS : reference = morceau ; break ; default : perror ( "Erreur_do_select : overflow compteur cpt " ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; break ; } } } // On récupère auprès de la BDD, la valeur associée à cette référence if ( bdd_do_request ( mysql_bdd, SELECT, reference, NULL, &resultat_req ) == ERRNO ) { perror ( "Erreur_bdd_do_select : bad requete " ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On récupère le tuple if ( ( tuple = mysql_fetch_row ( resultat_req ) ) == NULL ) { perror ( "Erreur_bdd_do_select : bad tuple " ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On déchiffre le tuple char* output = (char*) malloc ( RSA_size ( bdd_key ) * sizeof ( char ) ) ; memset ( output, '\0', RSA_size ( bdd_key ) ) ; if ( RSA_chiffrement ( (unsigned char*) tuple[0], (unsigned char*) output, DECHIFFREMENT ) != TRUE ) { perror ( "Erreur_bdd_do_select : RSA_dechiffrement " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On récupère les 3 informations du tuple morceau = NULL ; for ( cpt = 0; cpt < 3; cpt++ ) { // On découpe le tuple en morceaux repérés via un "*" if ( cpt == 0 ) morceau = strtok_r ( output, "*", &safe_tuple ) ; else morceau = strtok_r ( NULL, "*", &safe_tuple ) ; // Vérification if ( morceau == NULL ) { perror ( "Erreur_bdd_do_select : information manquante III " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On affecte l'information switch ( cpt ) { case ZERO : break ; case UN : valeur = morceau ; break ; case DEUX : politique = morceau ; break ; default : perror ( "Erreur_do_select : overflow compteur cpt " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; break ; } } // On regarde les politique de partage de la ressource morceau = NULL ; safe_tuple = NULL ; for ( cpt = 0; cpt < 3; cpt++ ) { // On découpe les politiques de partage en morceaux repérés via un "$" if ( cpt == 0 ) morceau = strtok_r ( politique, "$", &safe_tuple ) ; else morceau = strtok_r ( NULL, "$", &safe_tuple ) ; if ( morceau == NULL ) { perror ( "Erreur_bdd_do_select : information manquante IV " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } // On regarde d'abord si on est en accès interdit if ( strcmp ( morceau, "-" ) == 0 ) { printf ( "Erreur_bdd_do_select : BAD-PERMISSION " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "BAD-PERMISSION" ) ; return FALSE ; } else if ( strcmp ( morceau, "+") != 0 ) // Puis si on n'est pas en accès total { // Alors on traite le cas par cas switch ( cpt ) { case ZERO : // Statut code_retour = bdd_verification_partage ( morceau, statut ) ; break ; case UN : // Affectation code_retour = bdd_verification_partage ( morceau, affectation ) ; break ; case DEUX : // Groupes code_retour = bdd_verification_partage ( morceau, groupes ) ; break ; default : perror ( "Erreur_do_select : overflow compteur cpt " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; break ; } // On vérifie le code retour if ( code_retour == FALSE ) { printf ( "Erreur_bdd_do_select : bad permission " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "BAD-PERMISSION" ) ; return FALSE ; } else if ( code_retour == ERRNO ) { printf ( "Erreur_bdd_do_select : bdd_verification_partage " ) ; free ( output ) ; mysql_free_result ( resultat_req ) ; bdd_send_msg ( SELECT, "ERROR" ) ; return ERRNO ; } } } // Si on arrive ici c'est que la poltique de partage est respectée : on retourne la valeur int taille = strlen ( valeur ) + 10 ; char* reponse = (char*) malloc ( taille * sizeof ( char ) ) ; memset ( reponse, '\0', taille ) ; sprintf ( reponse, "%d*%s*EOF", SELECT, valeur ) ; res_send ( reponse ) ; // On free l'espace de résultat free ( output ) ; mysql_free_result ( resultat_req ) ; free ( reponse ) ; // On indique que tout s'est bien déroulé return TRUE ; }