diff -puNrb dnsmasq-2.68/Makefile dnsmasq-2.68-lee/Makefile
--- dnsmasq-2.68/Makefile 2013-12-08 15:58:29.000000000 +0000
+++ dnsmasq-2.68-lee/Makefile 2014-01-18 15:49:28.000000000 +0000
@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/g
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
- dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o domain.o
+ dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o action.o domain.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h
diff -puNrb dnsmasq-2.68/src/action.c dnsmasq-2.68-lee/src/action.c
--- dnsmasq-2.68/src/action.c 1970-01-01 01:00:00.000000000 +0100
+++ dnsmasq-2.68-lee/src/action.c 2014-01-18 16:23:04.000000000 +0000
@@ -0,0 +1,166 @@
+/* actions.c is ... license to be added
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 dated June, 1991, or
+ (at your option) version 3 dated 29 June, 2007.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+
+#include "dnsmasq.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#define UDP_FROM_PORT_ADD 10001
+#define UDP_FROM_PORT_DEL 10002
+
+static int udp_sock;
+static int action_inited[ACTION_LAST+1];
+static char *buffer;
+static int packet_size = sizeof(struct ip) + sizeof(struct udphdr);
+
+static struct ip *iph;
+static struct udphdr *udp;
+
+/* We support sending a udp packet to a specific address, with a source
+ address that matches the ip address returned in the dns query */
+
+void action_udp_init()
+{
+ int opt = 1;
+ udp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
+ buffer = safe_malloc(packet_size);
+
+ if(!buffer || (udp_sock < 0))
+ die (_("failed to create UDP action socket: %s"), NULL, EC_MISC);
+
+ if(setsockopt(udp_sock, IPPROTO_IP, IP_HDRINCL, &opt, sizeof(opt)) < 0)
+ die (_("failed to create UDP action socket: %s"), NULL, EC_MISC);
+
+ memset((void *)buffer, 0, packet_size);
+
+ iph = (struct ip *)buffer;
+ udp = (struct udphdr *)(buffer + sizeof(struct ip));
+
+ iph->ip_hl = 5;
+ iph->ip_v = 4;
+ iph->ip_tos = 16;
+ iph->ip_len = packet_size;
+ iph->ip_id = 0;
+ iph->ip_ttl = 64;
+ iph->ip_p = 17; /* udp */
+ iph->ip_sum = 0;
+ udp->len = htons(sizeof(struct udphdr));
+ udp->check = 0;
+}
+
+int action_udp_send(struct sockaddr_in *dest, const struct all_addr *ipaddr, int flags, int remove)
+{
+#ifdef HAVE_IPV6
+ /* we only support IPv4 for this at the moment */
+ if (flags & F_IPV6)
+ return -1;
+#endif
+
+ iph->ip_src = ipaddr->addr.addr4;
+ iph->ip_dst = dest->sin_addr;
+ udp->dest = dest->sin_port;
+ udp->source = htons(remove ? UDP_FROM_PORT_DEL : UDP_FROM_PORT_ADD);
+
+ return sendto(udp_sock, buffer, packet_size, 0, (struct sockaddr *)dest, sizeof(struct sockaddr_in));
+}
+
+/*
+ * Go through each of the action items we have and process it...
+ */
+
+int process_action(const struct action *action, const struct all_addr *ipaddr, int flags, int remove)
+{
+ struct actionitem **actionlist = action->actionlist;
+ struct actionitem *item;
+
+ while((item = *actionlist++))
+ {
+ switch(item->type)
+ {
+#ifdef HAVE_IPSET
+ case ACTION_IPSET:
+ return add_to_ipset(item->u.ipset, ipaddr, flags, remove);
+ break;
+#endif
+ case ACTION_UDP:
+ return action_udp_send(item->u.udp, ipaddr, flags, remove);
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Run through all the actions and initialise each of the types we have
+ used */
+
+void action_init()
+{
+ struct action *action;
+ struct actionitem **actionlist, *item;
+ int i;
+
+ for(i=0; iactions;
+ while(action) {
+ printf("Action domain: %s\n", action->domain);
+ actionlist = action->actionlist;
+
+ while((item = *actionlist++))
+ {
+ printf("action %p\n", item);
+ printf("action type: %d\n", item->type);
+ if(!action_inited[item->type])
+ {
+ printf("intialising type\n");
+ switch(item->type)
+ {
+#ifdef HAVE_IPSET
+ case ACTION_IPSET:
+ ipset_init();
+ break;
+#endif
+ case ACTION_UDP:
+ action_udp_init();
+ break;
+ }
+ action_inited[item->type] = 1;
+ }
+
+
+ }
+ action=action->next;
+ }
+}
+
+
+
Binary files dnsmasq-2.68/src/action.o and dnsmasq-2.68-lee/src/action.o differ
Binary files dnsmasq-2.68/src/cache.o and dnsmasq-2.68-lee/src/cache.o differ
Binary files dnsmasq-2.68/src/dnsmasq and dnsmasq-2.68-lee/src/dnsmasq differ
diff -puNrb dnsmasq-2.68/src/dnsmasq.c dnsmasq-2.68-lee/src/dnsmasq.c
--- dnsmasq-2.68/src/dnsmasq.c 2013-12-08 15:58:29.000000000 +0000
+++ dnsmasq-2.68-lee/src/dnsmasq.c 2014-01-18 16:25:56.000000000 +0000
@@ -215,10 +215,8 @@ int main (int argc, char **argv)
#endif
-#ifdef HAVE_IPSET
- if (daemon->ipsets)
- ipset_init();
-#endif
+ if (daemon->actions)
+ action_init();
#ifdef HAVE_LINUX_NETWORK
netlink_init();
diff -puNrb dnsmasq-2.68/src/dnsmasq.h dnsmasq-2.68-lee/src/dnsmasq.h
--- dnsmasq-2.68/src/dnsmasq.h 2013-12-08 15:58:29.000000000 +0000
+++ dnsmasq-2.68-lee/src/dnsmasq.h 2014-01-18 13:39:44.000000000 +0000
@@ -450,10 +450,22 @@ struct server {
struct server *next;
};
-struct ipsets {
- char **sets;
+struct actionitem {
+ int type;
+ union {
+ char *ipset;
+ struct sockaddr_in *udp;
+ } u;
+};
+
+#define ACTION_IPSET 0
+#define ACTION_UDP 1
+#define ACTION_LAST 1 /* used to size array */
+
+struct action {
+ struct actionitem **actionlist;
char *domain;
- struct ipsets *next;
+ struct action *next;
};
struct irec {
@@ -835,7 +847,7 @@ extern struct daemon {
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
struct bogus_addr *bogus_addr;
struct server *servers;
- struct ipsets *ipsets;
+ struct action *actions;
int log_fac; /* log facility */
char *log_file; /* optional log file */
int max_logs; /* queue limit */
@@ -970,7 +982,7 @@ size_t setup_reply(struct dns_header *he
struct all_addr *addrp, unsigned int flags,
unsigned long local_ttl);
int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
- time_t now, char **ipsets, int is_sign, int checkrebind,
+ time_t now, struct action *action, int is_sign, int checkrebind,
int checking_disabled);
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask, time_t now);
@@ -1198,6 +1210,10 @@ void ipset_init(void);
int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove);
#endif
+/* action.c */
+void action_init(void);
+int process_action(const struct action *action, const struct all_addr *ipaddr, int flags, int remove);
+
/* helper.c */
#if defined(HAVE_SCRIPT)
int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd);
Binary files dnsmasq-2.68/src/dnsmasq.o and dnsmasq-2.68-lee/src/dnsmasq.o differ
diff -puNrb dnsmasq-2.68/src/forward.c dnsmasq-2.68-lee/src/forward.c
--- dnsmasq-2.68/src/forward.c 2013-12-08 15:58:29.000000000 +0000
+++ dnsmasq-2.68-lee/src/forward.c 2014-01-18 13:36:57.000000000 +0000
@@ -450,24 +450,24 @@ static size_t process_reply(struct dns_h
int checking_disabled, int check_subnet, union mysockaddr *query_source)
{
unsigned char *pheader, *sizep;
- char **sets = 0;
+ struct action *action = 0;
int munged = 0, is_sign;
size_t plen;
#ifdef HAVE_IPSET
/* Similar algorithm to search_servers. */
- struct ipsets *ipset_pos;
+ struct action *action_pos;
unsigned int namelen = strlen(daemon->namebuff);
unsigned int matchlen = 0;
- for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
+ for (action_pos = daemon->actions; action_pos; action_pos = action_pos->next)
{
- unsigned int domainlen = strlen(ipset_pos->domain);
+ unsigned int domainlen = strlen(action_pos->domain);
char *matchstart = daemon->namebuff + namelen - domainlen;
- if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
+ if (namelen >= domainlen && hostname_isequal(matchstart, action_pos->domain) &&
(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
domainlen >= matchlen) {
matchlen = domainlen;
- sets = ipset_pos->sets;
+ action = action_pos;
}
}
#endif
@@ -534,7 +534,7 @@ static size_t process_reply(struct dns_h
SET_RCODE(header, NOERROR);
}
- if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, checking_disabled))
+ if (extract_addresses(header, n, daemon->namebuff, now, action, is_sign, check_rebind, checking_disabled))
{
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
munged = 1;
Binary files dnsmasq-2.68/src/forward.o and dnsmasq-2.68-lee/src/forward.o differ
diff -puNrb dnsmasq-2.68/src/lee.conf dnsmasq-2.68-lee/src/lee.conf
--- dnsmasq-2.68/src/lee.conf 1970-01-01 01:00:00.000000000 +0100
+++ dnsmasq-2.68-lee/src/lee.conf 2014-01-18 15:35:25.000000000 +0000
@@ -0,0 +1,5 @@
+
+
+
+action=/sun.com/udp=192.168.95.100:6677
+action=/google.com/udp=192.168.95.100:6677
Binary files dnsmasq-2.68/src/log.o and dnsmasq-2.68-lee/src/log.o differ
Binary files dnsmasq-2.68/src/netlink.o and dnsmasq-2.68-lee/src/netlink.o differ
Binary files dnsmasq-2.68/src/network.o and dnsmasq-2.68-lee/src/network.o differ
diff -puNrb dnsmasq-2.68/src/option.c dnsmasq-2.68-lee/src/option.c
--- dnsmasq-2.68/src/option.c 2013-12-08 15:58:29.000000000 +0000
+++ dnsmasq-2.68-lee/src/option.c 2014-01-18 16:30:56.000000000 +0000
@@ -127,7 +127,7 @@ struct myoption {
#define LOPT_AUTHSOA 316
#define LOPT_AUTHSFS 317
#define LOPT_AUTHPEER 318
-#define LOPT_IPSET 319
+#define LOPT_ACTION 319
#define LOPT_SYNTH 320
#ifdef OPTION6_PREFIX_CLASS
#define LOPT_PREF_CLSS 321
@@ -272,7 +272,7 @@ static const struct myoption opts[] =
{ "auth-soa", 1, 0, LOPT_AUTHSOA },
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
{ "auth-peer", 1, 0, LOPT_AUTHPEER },
- { "ipset", 1, 0, LOPT_IPSET },
+ { "action", 1, 0, LOPT_ACTION },
{ "synth-domain", 1, 0, LOPT_SYNTH },
#ifdef OPTION6_PREFIX_CLASS
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
@@ -422,7 +422,7 @@ static struct {
{ LOPT_AUTHSOA, ARG_ONE, "[,...]", gettext_noop("Set authoritive zone information"), NULL },
{ LOPT_AUTHSFS, ARG_DUP, "[,...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
{ LOPT_AUTHPEER, ARG_DUP, "[,...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
- { LOPT_IPSET, ARG_DUP, "//[,...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
+ { LOPT_ACTION, ARG_DUP, "//=[,=...]", gettext_noop("Specify actions to take on addresses when matching domains"), NULL },
{ LOPT_SYNTH, ARG_DUP, ",,[]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
#ifdef OPTION6_PREFIX_CLASS
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,", gettext_noop("Specify DHCPv6 prefix class"), NULL },
@@ -2162,18 +2162,14 @@ static int one_opt(int option, char *arg
break;
}
- case LOPT_IPSET: /* --ipset */
-#ifndef HAVE_IPSET
- ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
- break;
-#else
+ case LOPT_ACTION: /* --action */
{
- struct ipsets ipsets_head;
- struct ipsets *ipsets = &ipsets_head;
- int size;
- char *end;
- char **sets, **sets_pos;
- memset(ipsets, 0, sizeof(struct ipsets));
+ struct action actions_head;
+ struct action *action = &actions_head;
+ int size, port;
+ char *end, *equals, *colon;
+ struct actionitem **actionlist, **actionlist_pos;
+ memset(action, 0, sizeof(struct action));
unhide_metas(arg);
if (arg && *arg == '/')
{
@@ -2189,19 +2185,19 @@ static int one_opt(int option, char *arg
domain = "";
else if (strlen(arg) != 0 && !(domain = canonicalise_opt(arg)))
option = '?';
- ipsets->next = opt_malloc(sizeof(struct ipsets));
- ipsets = ipsets->next;
- memset(ipsets, 0, sizeof(struct ipsets));
- ipsets->domain = domain;
+ action->next = opt_malloc(sizeof(struct action));
+ action = action->next;
+ memset(action, 0, sizeof(struct action));
+ action->domain = domain;
arg = end;
}
}
else
{
- ipsets->next = opt_malloc(sizeof(struct ipsets));
- ipsets = ipsets->next;
- memset(ipsets, 0, sizeof(struct ipsets));
- ipsets->domain = "";
+ action->next = opt_malloc(sizeof(struct action));
+ action = action->next;
+ memset(action, 0, sizeof(struct action));
+ action->domain = 0;
}
if (!arg || !*arg)
{
@@ -2213,22 +2209,51 @@ static int one_opt(int option, char *arg
if (*end == ',')
++size;
- sets = sets_pos = opt_malloc(sizeof(char *) * size);
+ actionlist = actionlist_pos = opt_malloc(sizeof(struct actionitem *) * size);
do {
end = split(arg);
- *sets_pos++ = opt_string_alloc(arg);
+ equals = split_chr(arg, '=');
+ if(!equals)
+ ret_err(_("invalid action format"));
+ *actionlist_pos = opt_malloc(sizeof(struct actionitem));
+ if(strcmp(arg,"ipset") == 0)
+ {
+#ifndef HAVE_IPSET
+ ret_err(_("recompile with HAVE_IPSET defined to enable ipset actions"));
+#else
+ (*actionlist_pos)->type = ACTION_IPSET;
+ (*actionlist_pos)->u.ipset = opt_string_alloc(arg);
+#endif
+ }
+ else if(strcmp(arg,"udp") == 0)
+ {
+ colon = split_chr(equals, ':');
+ if(!colon)
+ ret_err(_("invalid upd specification"));
+ if(!atoi_check(colon, &port))
+ ret_err(_("invalid udp port"));
+ (*actionlist_pos)->type = ACTION_UDP;
+ (*actionlist_pos)->u.udp = opt_malloc(sizeof(struct sockaddr_in));
+ memset((void *)(*actionlist_pos)->u.udp, 0, sizeof(struct sockaddr_in));
+ (*actionlist_pos)->u.udp->sin_family = PF_INET;
+ (*actionlist_pos)->u.udp->sin_port = htons(port);
+ if (!inet_pton(AF_INET, equals, &(*actionlist_pos)->u.udp->sin_addr))
+ ret_err(_("invalid udp ip address"));
+ }
+ else
+ ret_err(_("unknown action"));
+ actionlist_pos++;
arg = end;
} while (end);
- *sets_pos = 0;
- for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
- ipsets->next->sets = sets;
- ipsets->next = daemon->ipsets;
- daemon->ipsets = ipsets_head.next;
+ *actionlist_pos = 0;
+ for (action = &actions_head; action->next; action = action->next)
+ action->next->actionlist = actionlist;
+ action->next = daemon->actions;
+ daemon->actions = actions_head.next;
break;
}
-#endif
case 'c': /* --cache-size */
{
Binary files dnsmasq-2.68/src/option.o and dnsmasq-2.68-lee/src/option.o differ
diff -puNrb dnsmasq-2.68/src/rfc1035.c dnsmasq-2.68-lee/src/rfc1035.c
--- dnsmasq-2.68/src/rfc1035.c 2013-12-08 15:58:29.000000000 +0000
+++ dnsmasq-2.68-lee/src/rfc1035.c 2014-01-18 16:30:17.000000000 +0000
@@ -878,17 +878,12 @@ static int find_soa(struct dns_header *h
expired and cleaned out that way.
Return 1 if we reject an address because it look like part of dns-rebinding attack. */
int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now,
- char **ipsets, int is_sign, int check_rebind, int checking_disabled)
+ struct action *action, int is_sign, int check_rebind, int checking_disabled)
{
unsigned char *p, *p1, *endrr, *namep;
int i, j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
unsigned long ttl = 0;
struct all_addr addr;
-#ifdef HAVE_IPSET
- char **ipsets_cur;
-#else
- (void)ipsets; /* unused */
-#endif
cache_start_insert();
@@ -1071,14 +1066,10 @@ int extract_addresses(struct dns_header
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
return 1;
-#ifdef HAVE_IPSET
- if (ipsets && (flags & (F_IPV4 | F_IPV6)))
+ if (action && (flags & (F_IPV4 | F_IPV6)))
{
- ipsets_cur = ipsets;
- while (*ipsets_cur)
- add_to_ipset(*ipsets_cur++, &addr, flags, 0);
+ process_action(action, &addr, flags, 0);
}
-#endif
newc = cache_insert(name, &addr, now, attl, flags | F_FORWARD);
if (newc && cpp)
Binary files dnsmasq-2.68/src/rfc1035.o and dnsmasq-2.68-lee/src/rfc1035.o differ
Binary files dnsmasq-2.68/src/rfc2131.o and dnsmasq-2.68-lee/src/rfc2131.o differ
Binary files dnsmasq-2.68/src/util.o and dnsmasq-2.68-lee/src/util.o differ