Commit Diff
Diff:
2289373656246b96b5fa24d736fa083e6b5fa7cb
dbd9100e293bdccffbcd52128add650688c0e459
Commit:
dbd9100e293bdccffbcd52128add650688c0e459
Tree:
f0b1146237bb9f889bf0d95bf644ad2cff104950
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Sun Sep 19 17:53:52 2010 UTC
Message:
* write reply_raw() and reply_raw2(), it is now possible to query an IPv4 DNS A lookup that recurses. This is a milestone, but far from finished.
blob - 4f13e91ad5adf5bdda62e199bf8842378916462f
blob + 4e42843478ac0e398843617d78179c372430c54b
--- include.h
+++ include.h
@@ -36,7 +36,11 @@
#include <sys/queue.h>
#include <net/if.h>
+
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
#include <arpa/inet.h>
#include <netdb.h>
blob - 6831259ed16ed37c02d64bba1fd02e52b0252a96
blob + 282727a42f70b64f7f4bdc01714bd72c963f7447
--- recurse.c
+++ recurse.c
@@ -62,7 +62,7 @@ struct recurseentry {
} *rn1, *rn2, *rnp;
-static const char rcsid[] = "$Id: recurse.c,v 1.10 2010/09/19 11:39:38 pbug Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.11 2010/09/19 17:53:52 pbug Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -575,7 +575,7 @@ lookup_a(DB *db, struct recurses *sr, struct ns *ns)
DBT key, data;
- struct domain *sd;
+ struct domain *sd, sdomain;
in_addr_t tmp;
char buf[INET_ADDRSTRLEN];
int found = 0;
@@ -606,11 +606,14 @@ lookup_a(DB *db, struct recurses *sr, struct ns *ns)
return (-1);
}
- sd = (struct domain *)data.data;
+ memcpy((char*)&sdomain, data.data, sizeof(struct domain));
+ sd = &sdomain;
if ((sd->flags & DOMAIN_HAVE_A) == DOMAIN_HAVE_A) {
memcpy((char *)&sr->a[sr->a_count], (char *)&sd->a[0], sizeof(in_addr_t));
+ sd->a_count++;
found = 1;
+
#if 0
tmp = sr->a[sr->a_count];
inet_ntop(AF_INET, (char*)&tmp, (char *)&buf, sizeof(buf));
@@ -1027,6 +1030,7 @@ again:
if (update) {
memcpy(&sdomain.a[j], p, sizeof(in_addr_t));
sdomain.a_count++;
+ sdomain.region[j] = 0xff;
sdomain.a_ptr = 0;
sdomain.flags |= DOMAIN_HAVE_A;
sdomain.flags &= ~(DOMAIN_NEGATIVE_CACHE);
blob - 2655129ed1189037840d04b59f80066af54c6044
blob + 32d282454c1bbc198be674e7b6dfa42d5863bd9f
--- reply.c
+++ reply.c
@@ -40,6 +40,7 @@ void reply_soa(struct sreply *);
void reply_ptr(struct sreply *);
void reply_cname(struct sreply *);
void reply_fmterror(struct sreply *);
+void reply_raw2(int so, char *reply, int outlen, struct recurses *sr);
extern int compress_label(u_char *, int, int);
extern int additional_a(char *, int, struct domain *, char *, int, int, int *);
@@ -55,6 +56,8 @@ void update_db(DB *, struct domain *);
struct domain * Lookup_zone(DB *db, char *name, u_int16_t namelen, u_int16_t type, int);
void collects_init(void);
+static int udp_cksum(const struct ip *ip, const struct udphdr *up, int len);
+u_short in_cksum(const u_short *addr, register int len, int csum);
SLIST_HEAD(listhead, collects) collectshead;
@@ -67,7 +70,7 @@ struct collects {
} *cn1, *cn2, *cnp;
-static const char rcsid[] = "$Id: reply.c,v 1.25 2010/09/19 11:39:38 pbug Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.26 2010/09/19 17:53:52 pbug Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -192,6 +195,7 @@ reply_a(struct sreply *sreply, DB *db)
out:
if (sreply->sr != NULL) {
syslog(LOG_DEBUG, "raw replying has not been implemented yet");
+ reply_raw2(so, reply, outlen, sreply->sr);
} else {
if (istcp) {
char *tmpbuf;
@@ -2075,3 +2079,134 @@ collects_init(void)
{
SLIST_INIT(&collectshead);
}
+
+void
+reply_raw2(int so, char *reply, int outlen, struct recurses *sr)
+{
+ char buf[2048];
+ struct ip *ip;
+ struct udphdr *udp;
+ int udplen = outlen + sizeof(struct udphdr);
+ struct sockaddr_in *sin_src, *sin_dst;
+
+ ip = (struct ip *)&buf[0];
+ udp = (struct udphdr *)&buf[sizeof(struct ip)];
+ memcpy(&buf[sizeof(struct ip) + sizeof(struct udphdr)], reply, outlen);
+
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = sizeof(struct ip) >> 2;
+
+ ip->ip_tos = 0;
+
+ ip->ip_len = htons(udplen + sizeof(struct ip));
+
+ ip->ip_id = arc4random();
+
+ ip->ip_off = htons(IP_DF);
+
+ ip->ip_ttl = 64;
+ ip->ip_p = IPPROTO_UDP;
+
+ sin_src = (struct sockaddr_in *)(&sr->source);
+ ip->ip_dst.s_addr = sin_src->sin_addr.s_addr;
+ sin_dst = (struct sockaddr_in *)(&sr->dest);
+ ip->ip_src.s_addr = sin_dst->sin_addr.s_addr;
+
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum((u_short*)ip, sizeof(struct ip), ip->ip_sum);
+
+ udp->uh_sport = sin_dst->sin_port;
+ udp->uh_dport = sin_src->sin_port;
+ udp->uh_ulen = htons(udplen);
+ udp->uh_sum = 0;
+
+ udp->uh_sum = udp_cksum(ip, udp, udplen);
+
+ if (sendto(so, buf, sizeof(struct ip) + udplen, 0, (struct sockaddr *)(&sr->dest), sizeof(struct sockaddr)) < 0) {
+ syslog(LOG_ERR, "sendto: %m");
+ }
+}
+
+
+
+/* from print_udp.c */
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+static int
+udp_cksum(const struct ip *ip, const struct udphdr *up, int len)
+{
+ union phu {
+ struct phdr {
+ u_int32_t src;
+ u_int32_t dst;
+ u_char mbz;
+ u_char proto;
+ u_int16_t len;
+ } ph;
+ u_int16_t pa[6];
+ } phu;
+ const u_int16_t *sp;
+ u_int32_t sum;
+
+ /* pseudo-header.. */
+ phu.ph.len = htons((u_int16_t)len);
+ phu.ph.mbz = 0;
+ phu.ph.proto = IPPROTO_UDP;
+ memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
+ memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
+
+ sp = &phu.pa[0];
+ sum = sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5];
+
+ return in_cksum((u_short *)up, len, sum);
+}
+
+u_short
+in_cksum(const u_short *addr, register int len, int csum)
+{
+ int nleft = len;
+ const u_short *w = addr;
+ u_short answer;
+ int sum = csum;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum),
+ * we add sequential 16 bit words to it, and at the end, fold
+ * back all the carry bits from the top 16 bits into the lower
+ * 16 bits.
+ */
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+ if (nleft == 1)
+ sum += htons(*(u_char *)w<<8);
+
+ /*
+ * add back carry outs from top 16 bits to low 16 bits
+ */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return (answer);
+}
+
repomaster@centroid.eu