diff --git a/CHANGELOG b/CHANGELOG index 717c29d..5e54df9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -163,6 +163,9 @@ version 2.85 Tweak TFTP code to check sender of all received packets, as specified in RFC 1350 para 4. + Support some wildcard matching of input tags to --tag-if. + Thanks to Geoff Back for the idea and the patch. + version 2.84 Fix a problem, introduced in 2.83, which could see DNS replies diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 680aaab..7ffccad 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -1435,6 +1435,12 @@ Any number of set: and tag: forms may appear, in any order. tag set by another .B --tag-if, the line which sets the tag must precede the one which tests it. + +As an extension, the tag: clauses support limited wildcard matching, +similar to the matching in the \fB--interface\fP directive. This allows, for +example, using \fB--tag-if=set:ppp,tag:ppp*\fP to set the tag 'ppp' for all requests +received on any matching interface (ppp0, ppp1, etc). This can be used in conjunction +with the tag:! format meaning that no tag matching the wildcard may be set. .TP .B \-J, --dhcp-ignore=tag:[,tag:] When all the given tags appear in the tag set ignore the host and do diff --git a/src/dhcp-common.c b/src/dhcp-common.c index 36bc38a..73568a9 100644 --- a/src/dhcp-common.c +++ b/src/dhcp-common.c @@ -79,13 +79,46 @@ ssize_t recv_dhcp_packet(int fd, struct msghdr *msg) return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz; } +/* like match_netid() except that the check can have a trailing * for wildcard */ +/* started as a direct copy of match_netid() */ +int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool) +{ + struct dhcp_netid *tmp1; + + for (; check; check = check->next) + { + const int check_len = strlen(check->net); + const int is_wc = (check->net[check_len - 1] == '*'); + + /* '#' for not is for backwards compat. */ + if (check->net[0] != '!' && check->net[0] != '#') + { + for (tmp1 = pool; tmp1; tmp1 = tmp1->next) + if (is_wc ? (strncmp(check->net, tmp1->net, check_len-1) == 0) : + (strcmp(check->net, tmp1->net) == 0)) + break; + if (!tmp1) + return 0; + } + else + for (tmp1 = pool; tmp1; tmp1 = tmp1->next) + if (is_wc ? (strncmp((check->net)+1, tmp1->net, check_len-2) == 0) : + (strcmp((check->net)+1, tmp1->net) == 0)) + return 0; + } + return 1; +} + struct dhcp_netid *run_tag_if(struct dhcp_netid *tags) { struct tag_if *exprs; struct dhcp_netid_list *list; + /* this now uses match_netid_wild() above so that tag_if can + * be used to set a 'group of interfaces' tag. + */ for (exprs = daemon->tag_if; exprs; exprs = exprs->next) - if (match_netid(exprs->tag, tags, 1)) + if (match_netid_wild(exprs->tag, tags)) for (list = exprs->set; list; list = list->next) { list->list->next = tags;