Simon Kelley schrieb: > Eric Laganowski wrote: >> I guess I am not communicating this well. The desired dnsmasq >> behavior would be to reply, say, with 192.168.1.1 to any request >> starting with "wpad.", not just local domain, so if, say my domain is >> domain.local, dnsmasq responds with 192.168.1.1 to both >> wpad.domain.local and wpad.google.com >> >> -Eric > > That's not possible. If one wanted to implement it, the logical way > would be to do full regexp pattern matching on the domains. That has > been suggested in the past, but I've always resisted it on the grounds > that it's overkill. >
But doesn't mean there is no patch. I have this laying around for some time, here for dnsmasq 2.50. This way one can write: address=/:^wpad\..*:/192.168.0.1 or something like that... Note: This patch is not that well tested... [snip] > > Simon. > Greetings Jan -- Miksch's Law: If a string has one end, then it has another end.
=== modified file 'Makefile' --- old/Makefile 2009-09-10 23:32:18 +0000 +++ new/Makefile 2009-09-10 23:44:45 +0000 @@ -27,6 +27,7 @@ DBUS_CFLAGS="`echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --cflags dbus-1`" DBUS_LIBS=" `echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --libs dbus-1`" +PCRE_LIBS=" `$(PKG_CONFIG) --libs libpcre`" SUNOS_LIBS=" `if uname | grep SunOS 2>&1 >/dev/null; then echo -lsocket -lnsl -lposix4; fi `" all : dnsmasq @@ -35,6 +36,7 @@ cd $(SRC) && $(MAKE) \ DBUS_CFLAGS=$(DBUS_CFLAGS) \ DBUS_LIBS=$(DBUS_LIBS) \ + PCRE_LIBS=$(PCRE_LIBS) \ SUNOS_LIBS=$(SUNOS_LIBS) \ -f ../bld/Makefile dnsmasq @@ -54,6 +56,7 @@ I18N=-DLOCALEDIR='\"$(LOCALEDIR)\"' \ DBUS_CFLAGS=$(DBUS_CFLAGS) \ DBUS_LIBS=$(DBUS_LIBS) \ + PCRE_LIBS=$(PCRE_LIBS) \ SUNOS_LIBS=$(SUNOS_LIBS) \ -f ../bld/Makefile dnsmasq cd $(PO); for f in *.po; do \ === modified file 'bld/Makefile' --- old/bld/Makefile 2008-08-08 08:21:20 +0000 +++ new/bld/Makefile 2009-05-06 20:47:33 +0000 @@ -8,7 +8,7 @@ $(CC) $(CFLAGS) $(COPTS) $(DBUS_MINOR) $(I18N) $(DBUS_CFLAGS) $(SUNOS_VER) $(RPM_OPT_FLAGS) -c $< dnsmasq : $(OBJS) - $(CC) $(LDFLAGS) -o $@ $(OBJS) $(DBUS_LIBS) $(SUNOS_LIBS) $(LIBS) + $(CC) $(LDFLAGS) -o $@ $(OBJS) $(DBUS_LIBS) $(SUNOS_LIBS) $(PCRE_LIBS) $(LIBS) dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h xgettext -d dnsmasq --foreign-user --keyword=_ -o dnsmasq.pot -i $(OBJS:.o=.c) === modified file 'src/dnsmasq.h' --- old/src/dnsmasq.h 2009-09-10 23:32:18 +0000 +++ new/src/dnsmasq.h 2009-09-10 23:41:19 +0000 @@ -110,6 +110,8 @@ #include <priv.h> #endif +#include <pcre.h> + /* daemon is function in the C library.... */ #define daemon dnsmasq_daemon @@ -309,6 +311,7 @@ #define SERV_MARK 256 /* for mark-and-delete */ #define SERV_TYPE (SERV_HAS_DOMAIN | SERV_FOR_NODOTS) #define SERV_COUNTED 512 /* workspace for log code */ +#define SERV_IS_REGEX 1024 /* server entry is a regex */ struct serverfd { int fd; @@ -327,6 +330,8 @@ char interface[IF_NAMESIZE+1]; struct serverfd *sfd; char *domain; /* set if this server only handles a domain. */ + pcre *regex; + pcre_extra *pextra; int flags, tcpfd; unsigned int queries, failed_queries; struct server *next; === modified file 'src/forward.c' --- old/src/forward.c 2009-09-10 23:32:18 +0000 +++ new/src/forward.c 2009-09-10 23:41:19 +0000 @@ -149,12 +149,36 @@ } else if (serv->flags & SERV_HAS_DOMAIN) { - unsigned int domainlen = strlen(serv->domain); - char *matchstart = qdomain + namelen - domainlen; - if (namelen >= domainlen && - hostname_isequal(matchstart, serv->domain) && - domainlen >= matchlen && - (domainlen == 0 || namelen == domainlen || *(serv->domain) == '.' || *(matchstart-1) == '.' )) + unsigned int domainlen = matchlen; + int serverhit = 0; + + if (!(serv->flags & SERV_IS_REGEX)) + { + domainlen = strlen(serv->domain); + char *matchstart = qdomain + namelen - domainlen; + if (namelen >= domainlen && + hostname_isequal(matchstart, serv->domain) && + domainlen >= matchlen && + (domainlen == 0 || namelen == domainlen || *(serv->domain) == '.' || *(matchstart-1) == '.' )) + serverhit = 1; + } + else + { + int captcount = 0; + if (pcre_fullinfo(serv->regex, serv->pextra, PCRE_INFO_CAPTURECOUNT, &captcount) == 0) + { + /* C99 dyn-array, or alloca must be used */ + int ovect[(captcount + 1) * 3]; + if (pcre_exec(serv->regex, serv->pextra, qdomain, namelen, 0, 0, ovect, (captcount + 1) * 3) > 0) + { + domainlen = (unsigned int) (ovect[1] - ovect[0]); + if (domainlen >= matchlen) + serverhit = 1; + } + } + } + + if (serverhit) { unsigned short sflag = serv->addr.sa.sa_family == AF_INET ? F_IPV4 : F_IPV6; *type = SERV_HAS_DOMAIN; === modified file 'src/network.c' --- old/src/network.c 2009-09-10 23:32:18 +0000 +++ new/src/network.c 2009-09-10 23:41:19 +0000 @@ -712,7 +712,7 @@ char *s1, *s2; if (!(new->flags & SERV_HAS_DOMAIN)) s1 = _("unqualified"), s2 = _("names"); - else if (strlen(new->domain) == 0) + else if (new->domain && strlen(new->domain) == 0) s1 = _("default"), s2 = ""; else s1 = _("domain"), s2 = new->domain; === modified file 'src/option.c' --- old/src/option.c 2009-09-10 23:32:18 +0000 +++ new/src/option.c 2009-09-10 23:41:19 +0000 @@ -1342,10 +1342,16 @@ arg++; while ((end = split_chr(arg, '/'))) { - char *domain = NULL; + char *domain = NULL, *regex = NULL; + char *real_end = arg + strlen(arg); /* # matches everything and becomes a zero length domain string */ if (strcmp(arg, "#") == 0) domain = ""; + else if (*arg == ':' && *(real_end - 1) == ':') + { + *(real_end - 1) = '\0'; + regex = arg + 1; + } else if (!canonicalise_opt(arg) && strlen(arg) != 0) option = '?'; else @@ -1355,7 +1361,22 @@ serv->next = newlist; newlist = serv; serv->domain = domain; - serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS; + serv->flags = domain || regex ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS; + if (regex) + { + const char *error; + int erroff; + serv->regex = pcre_compile(regex, 0, &error, &erroff, NULL); + + if (!serv->regex) + { + option = '?'; + problem = (char *) error; + break; + } + serv->flags |= SERV_IS_REGEX; + serv->pextra = pcre_study(serv->regex, 0, &error); + } arg = end; } if (!newlist)