158 lines
2.8 KiB
C
158 lines
2.8 KiB
C
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <arpa/inet.h>
|
||
|
|
||
|
#include <sys/poll.h>
|
||
|
|
||
|
#include <fcntl.h>
|
||
|
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include <errno.h>
|
||
|
|
||
|
#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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|