#include #include #include #include #include #include #include #include #include #include #include "dns2.h" #include "utils.h" #include "packet.h" #include "constants.h" #include "glist.h" #include "rr.h" #include "dns2-private.h" DNS2 *dns2_updater_new (const char *zone) { DNS2 *updater; updater = dns2_new (); if (updater == NULL) { return NULL; } updater->type = DNS_UPDATER; /* Sanitizar "zona" */ updater->zone = dns_dup_trim_name (zone); if (updater->zone == NULL) { free (updater); return NULL; } updater->packet = dns_packet_create_request (updater->zone, RR_TYPE_SOA, RR_CLASS_IN); if (updater->packet == NULL) { free (updater->zone); free (updater); return NULL; } updater->packet->header.opcode = OPCODE_UPDATE; return updater; } int dns_updater_check_name (DNS2 *updater, const char *name) { int len, nlen; /* TODO: ¿Usar la zona o el question[0]->qname? */ len = strlen (updater->zone); nlen = strlen (name); if (nlen < len) { return 0; } if (strcmp (name, updater->zone) == 0) { return 1; } if (strcmp (&name[nlen - len], updater->zone) != 0) { return 0; } if (name[nlen - len - 1] != '.') { return 0; } return 1; } void dns2_updater_add (DNS2 *updater, DNSRR *rr) { if (dns_updater_check_name (updater, rr->name) == 0) { /* Fuera de la zona */ return; } if (g_list_find (updater->packet->authority, rr) == NULL) { updater->packet->authority = g_list_append (updater->packet->authority, rr); } } DNSRR * dns_updater_packet_get_tsig (DNSPacket *response) { int g; GList *last; DNSRR *rr; if (response->header.arcount == 0) { return NULL; } last = g_list_last (response->additional); while (last != NULL) { rr = (DNSRR *) last->data; if (rr->type == RR_TYPE_TSIG) { return rr; } last = last->prev; } return NULL; } int dns_updater_packet_has_valid_tsig (DNS2 *updater, DNSPacket *response) { DNSRR *rr, *mysig; DNSPacket *dup; rr = dns_updater_packet_get_tsig (response); if (rr == NULL) { return 0; } if (updater->auth_signature == NULL) { return 0; } /* Eliminar temporalmente el rr de la lista */ response->additional = g_list_remove (response->additional, rr); response->header.arcount = g_list_length (response->additional); /* Recalcular la firma, */ mysig = dns2_rr_dup (updater->auth_signature); if (mysig->type == RR_TYPE_TSIG /*|| mysig->tipo == RR_TYPE_SIG*/) { dns_rr_pack_generate_signature (mysig, response); } /* Comparar firmas */ /* Re-anexar la firma original */ response->additional = g_list_append (response->additional, rr); response->header.arcount = g_list_length (response->additional); return 1; }