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)

Reply via email to