aboutsummaryrefslogtreecommitdiff
path: root/eperd/evtdig.c
diff options
context:
space:
mode:
Diffstat (limited to 'eperd/evtdig.c')
-rw-r--r--eperd/evtdig.c282
1 files changed, 138 insertions, 144 deletions
diff --git a/eperd/evtdig.c b/eperd/evtdig.c
index a836745..c94e884 100644
--- a/eperd/evtdig.c
+++ b/eperd/evtdig.c
@@ -230,16 +230,11 @@ typedef uint32_t counter_t;
struct tdig_base {
struct event_base *event_base;
- evutil_socket_t rawfd_v4; /* Raw socket used to nsm hosts */
- evutil_socket_t rawfd_v6; /* Raw socket used to nsm hosts */
-
struct timeval tv_noreply; /* DNS query Reply timeout */
/* A circular list of user queries */
struct query_state *qry_head;
- struct event event4; /* Used to detect read events on raw socket */
- struct event event6; /* Used to detect read events on raw socket */
struct event statsReportEvent;
int resolv_max;
char nslist[MAXNS][INET6_ADDRSTRLEN * 2];
@@ -270,7 +265,10 @@ struct query_state {
char * name; /* Host identifier as given by the user */
char * fqname; /* Full qualified hostname */
char * ipname; /* Remote address in dot notation */
- u_int16_t qryid; /* query id 16 bit */
+ char * infname; /* Bind to this interface (or address) */
+ u_int16_t qryid; /* query id 16 bit */
+ struct event event; /* Used to detect read events on udp socket */
+ int udp_fd; /* udp_fd and tcp_fd should be merged */
int tcp_fd;
FILE *tcp_file;
int wire_size;
@@ -495,17 +493,18 @@ static void tdig_stats(int unused UNUSED_PARAM, const short event UNUSED_PARAM,
static int tdig_delete(void *state);
static void ChangetoDnsNameFormat(u_char *dns, char * qry) ;
struct tdig_base *tdig_base_new(struct event_base *event_base);
-void tdig_start (struct query_state *qry);
+void tdig_start (void *qry);
void printReply(struct query_state *qry, int wire_size, unsigned char *result);
void printErrorQuick (struct query_state *qry);
static void local_exit(void *state);
static void *tdig_init(int argc, char *argv[], void (*done)(void *state));
-static void process_reply(void * arg, int nrecv, struct timeval now, int af, void *remote);
+static void process_reply(void * arg, int nrecv, struct timeval now);
static void mk_dns_buff(struct query_state *qry, u_char *packet);
int ip_addr_cmp (u_int16_t af_a, void *a, u_int16_t af_b, void *b);
-static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, struct query_state *qry);
+static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, void *arg);
static void noreply_callback(int unused UNUSED_PARAM, const short event UNUSED_PARAM, void *h);
static void free_qry_inst(struct query_state *qry);
+static void ready_callback (int unused, const short event, void * arg);
/* move the next functions from tdig.c */
u_int32_t get32b (char *p);
@@ -654,39 +653,6 @@ int ip_addr_cmp (u_int16_t af_a, void *a, u_int16_t af_b, void *b)
return 1;
}
-/* Lookup for a query by its index */
-static struct query_state* tdig_lookup_query( struct tdig_base * base, int idx, int af, void * remote)
-{
- int i = 0;
- struct query_state *qry;
-
- qry = base->qry_head;
- if (!qry)
- return NULL;
- do {
- i++;
- if (qry->qryid == idx)
- {
- crondlog(LVL5 "found matching query id %d", idx);
- if( qry->ressent && ip_addr_cmp (af, remote, qry->ressent->ai_family, qry->ressent->ai_addr) == 0) {
- crondlog(LVL7 "matching id and address id %d", idx);
- return qry;
- }
- else {
- crondlog(LVL7 "matching id and address mismatch id %d", idx);
- }
- }
- qry = qry->next;
- if (i > (2*base->activeqry) ) {
- crondlog(LVL7 "i am looping %d AA", idx);
- return NULL;
- }
-
- } while (qry != base->qry_head);
-
- return NULL;
-}
-
static void mk_dns_buff(struct query_state *qry, u_char *packet)
{
struct DNS_HEADER *dns = NULL;
@@ -811,12 +777,13 @@ static void mk_dns_buff(struct query_state *qry, u_char *packet)
/* Attempt to transmit a UDP DNS Request to a serveri. TCP is else where */
static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event UNUSED_PARAM, void *h)
{
+ int fd;
+ sa_family_t af;
struct query_state *qry = h;
struct tdig_base *base = qry->base;
uint32_t nsent = 0;
u_char *outbuff;
int err = 0;
- int sockfd;
/* Clean the no reply timer (if any was previously set) */
evtimer_del(&qry->noreply_timer);
@@ -828,33 +795,63 @@ static void tdig_send_query_callback(int unused UNUSED_PARAM, const short event
gettimeofday(&qry->xmit_time, NULL);
mk_dns_buff(qry, outbuff);
do {
- switch (qry->res->ai_family) {
- case AF_INET:
- nsent = sendto(base->rawfd_v4, outbuff,qry->pktsize, MSG_DONTWAIT, qry->res->ai_addr, qry->res->ai_addrlen);
- break;
- case AF_INET6:
- nsent = sendto(base->rawfd_v6, outbuff,qry->pktsize, MSG_DONTWAIT, qry->res->ai_addr, qry->res->ai_addrlen);
- break;
+ if (qry->udp_fd != -1)
+ {
+ event_del(&qry->event);
+ close(qry->udp_fd);
+ qry->udp_fd= -1;
}
+
+ af = ((struct sockaddr *)(qry->res->ai_addr))->sa_family;
+
+ if ((fd = socket(af, SOCK_DGRAM, 0) ) < 0 )
+ {
+ snprintf(line, DEFAULT_LINE_LENGTH, "%s \"socket\" : \"socket failed %s\"", qry->err.size ? ", " : "", strerror(errno));
+ buf_add(&qry->err, line, strlen(line));
+ printReply (qry, 0, NULL);
+ return;
+ }
+
+ qry->udp_fd= fd;
+
+ evutil_make_socket_nonblocking(fd);
+
+ event_assign(&qry->event, tdig_base->event_base, fd,
+ EV_READ | EV_PERSIST, ready_callback, qry);
+ event_add(&qry->event, NULL);
+
+ if (qry->infname)
+ {
+ if (bind_interface(fd, af, qry->infname) == -1)
+ {
+ snprintf(line, DEFAULT_LINE_LENGTH,
+ "%s \"socket\" : \"bind_interface failed\"",
+ qry->err.size ? ", " : "");
+ buf_add(&qry->err, line, strlen(line));
+ printReply (qry, 0, NULL);
+ return;
+ }
+ }
+
+ qry->loc_socklen = sizeof(qry->loc_sin6);
+ if (connect(qry->udp_fd, qry->res->ai_addr, qry->res->ai_addrlen) == -1)
+ {
+ snprintf(line, DEFAULT_LINE_LENGTH,
+ "%s \"socket\" : \"connect failed %s\"",
+ qry->err.size ? ", " : "",
+ strerror(errno));
+ buf_add(&qry->err, line, strlen(line));
+ printReply (qry, 0, NULL);
+ return;
+ }
+
+ nsent = send(qry->udp_fd, outbuff,qry->pktsize, MSG_DONTWAIT);
qry->ressent = qry->res;
if (nsent == qry->pktsize) {
- // the packet is send. Now lets try to the source address we would have used.
- // create another sock with same dest, connect and get the source address
- // delete that socket and hope the the source address is the right one.
- if ((sockfd = socket(qry->res->ai_family, SOCK_DGRAM, 0 ) ) < 0 ) {
- snprintf(line, DEFAULT_LINE_LENGTH, "%s \"socket\" : \"temp socket to get src address failed %s\"", qry->err.size ? ", " : "", strerror(errno));
- buf_add(&qry->err, line, strlen(line));
- return;
- }
- else {
- qry->loc_socklen = sizeof(qry->loc_sin6);
- connect(sockfd, qry->res->ai_addr, qry->res->ai_addrlen);
- if (getsockname(sockfd,(struct sockaddr *)&qry->loc_sin6, &qry->loc_socklen) == -1) {
- snprintf(line, DEFAULT_LINE_LENGTH, "%s \"getscokname\" : \"%s\"", qry->err.size ? ", " : "", strerror(errno));
- buf_add(&qry->err, line, strlen(line));
- }
- close(sockfd);
+ if (getsockname(qry->udp_fd, (struct sockaddr *)&qry->loc_sin6, &qry->loc_socklen) == -1) {
+ snprintf(line, DEFAULT_LINE_LENGTH, "%s \"getscokname\" : \"%s\"", qry->err.size ? ", " : "", strerror(errno));
+ buf_add(&qry->err, line, strlen(line));
}
/* One more DNS Query is sent */
@@ -947,6 +944,12 @@ static void tcp_reporterr(struct tu_env *env, enum tu_err cause,
buf_add(&qry->err, line, strlen(line));
break;
+ case TU_SOCKET_ERR:
+
+ snprintf(line, DEFAULT_LINE_LENGTH, "%s \"TUSOCKET\" : \"%s\"", qry->err.size ? ", " : "", str );
+ buf_add(&qry->err, line, strlen(line));
+ break;
+
case TU_READ_ERR:
// need more than this reporting for this case AA
snprintf(line, DEFAULT_LINE_LENGTH, "%s \"TU_READ_ERR\" : \"%s\"", qry->err.size ? ", " : "", str );
@@ -1078,7 +1081,7 @@ static void tcp_readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr)
dnsR = (struct DNS_HEADER*) qry->packet.buf;
if ( ntohs(dnsR->id) == qry->qryid ) {
qry->triptime = (rectime.tv_sec - qry->xmit_time.tv_sec)*1000 + (rectime.tv_usec-qry->xmit_time.tv_usec)/1e3;
- printReply (qry, qry->packet.size, qry->packet.buf);
+ printReply (qry, qry->packet.size, (unsigned char *)qry->packet.buf);
}
else {
bzero(line, DEFAULT_LINE_LENGTH);
@@ -1091,7 +1094,7 @@ static void tcp_readcb(struct bufferevent *bev UNUSED_PARAM, void *ptr)
}
}
-static void tcp_writecb(struct bufferevent *bev, void *ptr)
+static void tcp_writecb(struct bufferevent *bev UNUSED_PARAM, void *ptr UNUSED_PARAM)
{
/*
struct query_state * qry;
@@ -1112,14 +1115,16 @@ static void tcp_writecb(struct bufferevent *bev, void *ptr)
* o the one we are looking for (matching the same identifier of all the packets the program is able to send)
*/
-static void process_reply(void * arg, int nrecv, struct timeval now, int af, void *remote )
+static void process_reply(void * arg, int nrecv, struct timeval now)
{
- struct tdig_base *base = arg;
-
struct DNS_HEADER *dnsR = NULL;
+ struct tdig_base * base;
struct query_state * qry;
+ qry= arg;
+ base= qry->base;
+
if (nrecv < sizeof (struct DNS_HEADER)) {
base->shortpkt++;
return;
@@ -1130,13 +1135,10 @@ static void process_reply(void * arg, int nrecv, struct timeval now, int af, voi
crondlog(LVL7 "DBG: base address process reply %p, nrec %d", base, nrecv);
- /* Get the pointer to the qry descriptor in our internal table */
- qry = tdig_lookup_query(base, ntohs(dnsR->id), af, remote);
-
- if ( ! qry) {
+ if (ntohs(dnsR->id) != qry->qryid)
+ {
base->martian++;
- crondlog(LVL7 "DBG: no match found for qry id i %d",\
-ntohs(dnsR->id));
+ crondlog(LVL7 "DBG: wrong id %d for qry", ntohs(dnsR->id));
return;
}
@@ -1150,46 +1152,50 @@ ntohs(dnsR->id));
return;
}
-static void ready_callback4 (int unused UNUSED_PARAM, const short event UNUSED_PARAM, void * arg)
+static void ready_callback (int unused UNUSED_PARAM, const short event UNUSED_PARAM, void * arg)
{
- struct tdig_base *base = arg;
+ struct query_state * qry;
int nrecv;
- struct sockaddr_in remote4; /* responding internet address */
- socklen_t slen;
struct timeval rectime;
+
+ printf("in ready_callback\n");
+
+ qry = arg;
- slen = sizeof(struct sockaddr);
- bzero(base->packet, MAX_DNS_BUF_SIZE);
+ bzero(qry->base->packet, MAX_DNS_BUF_SIZE);
/* Time the packet has been received */
gettimeofday(&rectime, NULL);
/* Receive data from the network */
- nrecv = recvfrom(base->rawfd_v4, base->packet, sizeof(base->packet), MSG_DONTWAIT, &remote4, &slen);
+ nrecv = recv(qry->udp_fd, qry->base->packet,
+ sizeof(qry->base->packet), MSG_DONTWAIT);
if (nrecv < 0) {
/* One more failure */
- base->recvfail++;
+ qry->base->recvfail++;
return ;
}
- process_reply(arg, nrecv, rectime, remote4.sin_family, &remote4);
+ process_reply(arg, nrecv, rectime);
return;
}
+#if 0
static void ready_callback6 (int unused UNUSED_PARAM, const short event UNUSED_PARAM, void * arg)
{
- struct tdig_base *base = arg;
+ struct query_state * qry;
int nrecv;
struct timeval rectime;
struct msghdr msg;
struct iovec iov[1];
//char buf[INET6_ADDRSTRLEN];
- struct sockaddr_in6 remote6;
char cmsgbuf[256];
+ qry= arg;
+
/* Time the packet has been received */
gettimeofday(&rectime, NULL);
- iov[0].iov_base= base->packet;
- iov[0].iov_len= sizeof(base->packet);
+ iov[0].iov_base= qry->base->packet;
+ iov[0].iov_len= sizeof(qry->base->packet);
msg.msg_name= &remote6;
msg.msg_namelen= sizeof( struct sockaddr_in6);
@@ -1199,16 +1205,17 @@ static void ready_callback6 (int unused UNUSED_PARAM, const short event UNUSED_P
msg.msg_controllen= sizeof(cmsgbuf);
msg.msg_flags= 0; /* Not really needed */
- nrecv= recvmsg(base->rawfd_v6, &msg, MSG_DONTWAIT);
+ nrecv= recvmsg(qry->udp_fd, &msg, MSG_DONTWAIT);
if (nrecv == -1) {
/* Strange, read error */
printf("ready_callback6: read error '%s'\n", strerror(errno));
return;
}
- process_reply(arg, nrecv, rectime, remote6.sin6_family, &remote6);
+ process_reply(arg, nrecv, rectime);
return;
}
+#endif
static bool argProcess (int argc, char *argv[], struct query_state *qry )
{
@@ -1284,9 +1291,11 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
qry->out_filename = NULL;
qry->opt_proto = 17;
qry->tcp_file = NULL;
+ qry->udp_fd = -1;
qry->tcp_fd = -1;
qry->server_name = NULL;
qry->str_Atlas = NULL;
+ qry->infname = NULL;
tdig_base->activeqry++;
qry->qst = STATUS_FREE;
qry->retry = 0;
@@ -1329,7 +1338,7 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
evtimer_assign(&qry->done_qry_timer, tdig_base->event_base, done_qry_cb, qry);
optind = 0;
- while (c= getopt_long(argc, argv, "46adD:e:tbhinqO:Rrs:A:?", longopts, NULL), c != -1) {
+ while (c= getopt_long(argc, argv, "46adD:e:tbhinqO:Rrs:A:I:?", longopts, NULL), c != -1) {
switch(c) {
case '4':
qry->opt_v4_only = 1;
@@ -1355,6 +1364,10 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
}
qry->str_Atlas = strdup(optarg);
break;
+ case 'I':
+ free(qry->infname);
+ qry->infname= strdup(optarg);
+ break;
case 'b':
qry->lookupname = strdup ("version.bind.");
break;
@@ -1702,36 +1715,11 @@ static void *tdig_init(int argc, char *argv[], void (*done)(void *state))
/* called only once. Initialize tdig_base variables here */
struct tdig_base * tdig_base_new(struct event_base *event_base)
{
- evutil_socket_t fd6;
- evutil_socket_t fd4;
- struct addrinfo hints;
- int on = 1;
struct timeval tv;
- bzero(&hints,sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_flags = 0;
- hints.ai_socktype = SOCK_DGRAM;
- hints.ai_flags = 0;
-
- /* Create an endpoint for communication using raw socket for ICMP calls */
- if ((fd4 = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol) ) < 0 )
- {
- return NULL;
- }
-
- hints.ai_family = AF_INET6;
- if ((fd6 = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol) ) < 0 )
- {
- close(fd4);
- return NULL;
- }
-
tdig_base= xzalloc(sizeof( struct tdig_base));
if (tdig_base == NULL)
{
- close(fd4);
- close(fd6);
return (NULL);
}
@@ -1751,33 +1739,16 @@ struct tdig_base * tdig_base_new(struct event_base *event_base)
memset(tdig_base, 0, sizeof(struct tdig_base));
tdig_base->event_base = event_base;
- tdig_base->rawfd_v4 = fd4;
- tdig_base->rawfd_v6 = fd6;
-
- setsockopt(fd6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
-
- on = 1;
- setsockopt(fd6, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
-
//memset(&tdig_base-->loc_sin6, '\0', sizeof(tdig_base-->loc_sin6));
//tdig_base-->loc_socklen= 0;
- evutil_make_socket_nonblocking(tdig_base->rawfd_v4);
+ evtimer_assign(&tdig_base->statsReportEvent, tdig_base->event_base, tdig_stats, tdig_base);
msecstotv(DEFAULT_NOREPLY_TIMEOUT, &tdig_base->tv_noreply);
// Define the callback to handle UDP Reply
// add the raw file descriptor to those monitored for read events
- event_assign(&tdig_base->event4, tdig_base->event_base, tdig_base->rawfd_v4,
- EV_READ | EV_PERSIST, ready_callback4, tdig_base);
- event_add(&tdig_base->event4, NULL);
-
- event_assign(&tdig_base->event6, tdig_base->event_base, tdig_base->rawfd_v6,
- EV_READ | EV_PERSIST, ready_callback6, tdig_base);
- event_add(&tdig_base->event6, NULL);
-
- evtimer_assign(&tdig_base->statsReportEvent, tdig_base->event_base, tdig_stats, tdig_base);
tv.tv_sec = DEFAULT_STATS_REPORT_INTERVEL;
tv.tv_usec = 0;
event_add(&tdig_base->statsReportEvent, &tv);
@@ -1785,7 +1756,9 @@ struct tdig_base * tdig_base_new(struct event_base *event_base)
return tdig_base;
}
-static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, struct query_state *qry) {
+static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, void *arg) {
+ struct query_state *qry;
+ qry= arg;
if (err) {
snprintf(line, DEFAULT_LINE_LENGTH, "\"evdns_getaddrinfo\": "
"\"%s %s\"", qry->server_name,
@@ -1803,16 +1776,19 @@ static void udp_dns_cb(int err, struct evutil_addrinfo *ev_res, struct query_sta
}
}
-void tdig_start (struct query_state *qry)
+void tdig_start (void *arg)
{
struct timeval asap = { 0, 0 };
struct timeval interval;
int err_num;
+ struct query_state *qry;
struct addrinfo hints, *res;
char port[] = "domain";
char port_as_char[] = "53";
+ qry= arg;
+
switch(qry->qst)
{
case STATUS_FREE :
@@ -1897,7 +1873,7 @@ void tdig_start (struct query_state *qry)
interval.tv_sec = CONN_TO;
interval.tv_usec= 0;
tu_connect_to_name (&qry->tu_env, qry->server_name, port_as_char,
- &interval, &hints, NULL,
+ &interval, &hints, qry->infname,
tcp_timeout_callback, tcp_reporterr,
tcp_dnscount, tcp_beforeconnect,
tcp_connected, tcp_readcb, tcp_writecb);
@@ -2048,6 +2024,13 @@ static void free_qry_inst(struct query_state *qry)
if(qry->opt_proto == 6)
tu_cleanup(&qry->tu_env);
+ if (qry->udp_fd != -1)
+ {
+ event_del(&qry->event);
+ close(qry->udp_fd);
+ qry->udp_fd= -1;
+ }
+
if ( qry->opt_resolv_conf) {
// this loop goes over servers in /etc/resolv.conf
// select the next server and restart
@@ -2096,6 +2079,11 @@ static int tdig_delete(void *state)
free(qry->lookupname);
qry->lookupname = NULL;
}
+ if(qry->infname)
+ {
+ free(qry->infname);
+ qry->infname = NULL;
+ }
/* Delete timers */
evtimer_del(&qry->noreply_timer);
@@ -2131,6 +2119,12 @@ static int tdig_delete(void *state)
free(qry->server_name);
qry->server_name = NULL;
}
+ if (qry->udp_fd != -1)
+ {
+ event_del(&qry->event);
+ close(qry->udp_fd);
+ qry->udp_fd= -1;
+ }
if(qry->base)
qry->base->activeqry--;
free(qry);
@@ -2374,7 +2368,7 @@ void printReply(struct query_state *qry, int wire_size, unsigned char *result)
reader-result,&stop);
JSDOT( RNAME, answers[i].rdata);
reader = reader + stop;
- serial = get32b(reader);
+ serial = get32b((char *)reader);
JU_NC(SERIAL, serial);
reader = reader + 4;
reader = reader + 16; // skip REFRESH, RETRY, EXIPIRE, and MINIMUM
@@ -2470,7 +2464,7 @@ unsigned char* ReadName(unsigned char *base, size_t size, size_t offset,
if ((len & 0xc0) != 0xc0)
{
/* Bad format */
- strcpy(name, "format-error");
+ strcpy((char *)name, "format-error");
printf("format-error: len = %d\n",
len);
abort();
@@ -2480,7 +2474,7 @@ unsigned char* ReadName(unsigned char *base, size_t size, size_t offset,
offset= ((len & ~0xc0) << 8) | base[offset+1];
if (offset >= size)
{
- strcpy(name, "offset-error");
+ strcpy((char *)name, "offset-error");
printf("offset-error\n");
abort();
return name;
@@ -2497,7 +2491,7 @@ unsigned char* ReadName(unsigned char *base, size_t size, size_t offset,
}
if (offset+len+1 > size)
{
- strcpy(name, "buf-bounds-error");
+ strcpy((char *)name, "buf-bounds-error");
printf("buf-bounds-error\n");
abort();
return name;
@@ -2505,7 +2499,7 @@ unsigned char* ReadName(unsigned char *base, size_t size, size_t offset,
if (p+len+1 > 255)
{
- strcpy(name, "name-length-error");
+ strcpy((char *)name, "name-length-error");
printf("name-length-error\n");
abort();
return name;