{
const char *m = mask, *n = name;
const char *m_tmp = mask, *n_tmp = name;
- int wild = 0;
-
- for (;;)
- {
- if (*m == '*') {
- while (*m == '*') /* clean up any additional wildcards */
- m++;
-
- m_tmp = m;
- n_tmp = n;
- wild = 1;
- }
- if (*m == '\\') /* next wildcard is disregarded */
- m++;
+ int star_p;
- if (!*m) {
- if (!*n)
- return 0; /* match */
-
- for (m--; (m > mask) && (*m == '?'); m--);
- ;
-
- if (*m == '*' && (m > mask))
- return 0; /* match */
-
- if (!wild)
- return 1;
-
- m = m_tmp;
- n = ++n_tmp;
- }
- else if (!*n) {
- while (*m == '*') /* clean up any additional wildcards */
- m++;
-
- return (*m != 0);
- }
- if (ToLower(*m) != ToLower(*n) && *m != '?') {
- if (!wild)
- return 1; /* failure! */
-
- m = m_tmp;
- n = ++n_tmp;
+ for (;;) switch (*m) {
+ case '\0':
+ if (!*n)
+ return 0;
+ backtrack:
+ if (m_tmp == mask)
+ return 1;
+ m = m_tmp;
+ n = ++n_tmp;
+ if (*n == '\0')
+ return 1;
+ break;
+ case '\\':
+ m++;
+ /* allow escaping to force capitalization */
+ if (*m++ != *n++)
+ goto backtrack;
+ break;
+ case '*': case '?':
+ for (star_p = 0; ; m++) {
+ if (*m == '*')
+ star_p = 1;
+ else if (*m == '?') {
+ if (!*n++)
+ goto backtrack;
+ } else break;
}
- else {
- if (*m)
- m++;
- if (*n)
- n++;
+ if (star_p) {
+ if (!*m)
+ return 0;
+ else if (*m == '\\') {
+ m_tmp = ++m;
+ if (!*m)
+ return 1;
+ for (n_tmp = n; *n && *n != *m; n++) ;
+ } else {
+ m_tmp = m;
+ for (n_tmp = n; *n && ToLower(*n) != ToLower(*m); n++) ;
+ }
}
+ /* and fall through */
+ default:
+ if (!*n)
+ return *m != '\0';
+ if (ToLower(*m) != ToLower(*n))
+ goto backtrack;
+ m++;
+ n++;
+ break;
}
-
- return 1; /* no match! */
}
/*
return 1; /* Auch... something left out ? Fail */
}
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-/** Parse an input string as an IPv4 address.
- * @param[in] in Text form of address.
- * @param[out] out IPv4 address in network representation.
- * @return Number of address bits specified by \a in.
- */
-static int ipmask_parse_ipv4(const char *in, struct in_addr *out)
-{
- int class;
- int ad[4] = { 0 };
- int bits = 0;
-
- class = sscanf(in, "%d.%d.%d.%d/%d", &ad[0], &ad[1], &ad[2], &ad[3], &bits);
- if (class != 5)
- bits = class * 8;
- out->s_addr = ntohl((ad[0] << 24) | (ad[1] << 16) | (ad[2] << 8) | ad[3]);
- return bits;
-}
-
-/** Test whether a string looks like it matches only IPv4 addresses.
- * @param[in] mask Hostname matching mask.
- * @return Non-zero if \a mask can only match IPv4 addresses, zero otherwise.
- */
-int check_if_ipmask(const char *mask)
-{
- int has_digit = 0;
- const char *p;
-
- /* Given the bug that inspired this test, this may seem like a hasty
- * kludge. It isn't: Wildcard characters should be matched from the
- * start, as when the username is the "interesting" part of the ban.
- * Likewise, we cannot simply reject masks interpreted as x/0 for
- * all x.
- */
- if (mask[0] == '.' || mask[0] == '/')
- return 0;
- for (p = mask; *p; ++p)
- if (*p != '*' && *p != '?' && *p != '.' && *p != '/')
- {
- if (!IsDigit(*p))
- return 0;
- has_digit = -1;
- }
-
- return has_digit;
-}
-
-/** Try to parse an IPv4 or IPv6 address mask.
- * @param[in] in Address matching mask.
- * @param[out] mask Fixed bits of address mask.
- * @param[out] bits_ptr If non-NULL, receives number of bits specified in address mask.
- * @return Non-zero on successful parse; zero on error.
- */
-int ipmask_parse(const char *in, struct irc_in_addr *mask, unsigned char *bits_ptr)
-{
- struct in_addr ipv4;
- char *p;
- int bits = 0;
-
- if (check_if_ipmask(in)) {
- bits = ipmask_parse_ipv4(in, &ipv4);
- mask->in6_16[0] = mask->in6_16[1] = mask->in6_16[2] = 0;
- mask->in6_16[3] = mask->in6_16[4] = 0;
- mask->in6_16[5] = 0xffff;
- memcpy(&mask->in6_16[6], &ipv4.s_addr, sizeof(ipv4.s_addr));
- bits += 96;
- } else if (in[0] == '*' && in[1] == '\0') {
- /* accept as a 0-bit mask */
- memset(&mask->in6_16, 0, sizeof(mask->in6_16));
- bits = 0;
- } else {
- if (!(p = strchr(in, '/')))
- bits = 128;
- else
- *p = 0;
- if (!ircd_aton(mask, in)) {
- if (p)
- *p = '/';
- return 0;
- }
- if (p) {
- bits = atoi(p + 1);
- *p = '/';
- }
- }
-
- if (bits_ptr)
- *bits_ptr = bits;
- return 1;
-}
-
/** Test whether an address matches the most significant bits of a mask.
* @param[in] addr Address to test.
* @param[in] mask Address to test against.