mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 05:07:58 +00:00
postfix-3.2-20160527
This commit is contained in:
parent
84739fb911
commit
4a9d39443f
@ -22316,3 +22316,14 @@ Apologies for any names omitted.
|
|||||||
Cleanup: existing if/endif support for pcre and regexp
|
Cleanup: existing if/endif support for pcre and regexp
|
||||||
tables, in preparation for new if/endif support for cidr
|
tables, in preparation for new if/endif support for cidr
|
||||||
tables. Files: util/dict_regexp.c, util/dict_pcre.c.
|
tables. Files: util/dict_regexp.c, util/dict_pcre.c.
|
||||||
|
|
||||||
|
20160526
|
||||||
|
|
||||||
|
Feature: cidr tables now support if/endif and negation (by
|
||||||
|
prepending "!" to a pattern), just like regexp and pcre
|
||||||
|
tables. The primarily purpose is to improve readability of
|
||||||
|
complex tables. Files: util/cidr_match.[hc], util/dict_cidr.c,
|
||||||
|
proto/cidr_table.
|
||||||
|
|
||||||
|
Cleanup: make regexp: and pcre: parser warning messages more
|
||||||
|
similar. Files: dict_regexp.c, dict_pcre.c.
|
||||||
|
@ -15,3 +15,12 @@ specifies the release date of a stable release or snapshot release.
|
|||||||
|
|
||||||
If you upgrade from Postfix 3.0 or earlier, read RELEASE_NOTES-3.1
|
If you upgrade from Postfix 3.0 or earlier, read RELEASE_NOTES-3.1
|
||||||
before proceeding.
|
before proceeding.
|
||||||
|
|
||||||
|
Major changes with snapshot 20160527
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Postfix cidr tables now support if..endif, and pattern negation
|
||||||
|
with "!", just like regexp and pcre tables. The if..endif can speed
|
||||||
|
up lookups by skipping over irrelevant patterns, and can make rule
|
||||||
|
maintenance easier because rules for a network can now be placed
|
||||||
|
inside if..endif. See the cidr_table(5) manpage for syntax details.
|
||||||
|
@ -30,30 +30,39 @@ CIDR_TABLE(5) CIDR_TABLE(5)
|
|||||||
<b>TABLE FORMAT</b>
|
<b>TABLE FORMAT</b>
|
||||||
The general form of a Postfix CIDR table is:
|
The general form of a Postfix CIDR table is:
|
||||||
|
|
||||||
<i>network</i><b>_</b><i>address</i><b>/</b><i>network</i><b>_</b><i>mask result</i>
|
<i>pattern result</i>
|
||||||
When a search string matches the specified network block, use
|
When a search string matches the specified <i>pattern</i>, use the cor-
|
||||||
the corresponding <i>result</i> value. Specify 0.0.0.0/0 to match every
|
responding <i>result</i> value. The <i>pattern</i> must be in <i>network/prefix</i>
|
||||||
IPv4 address, and ::/0 to match every IPv6 address.
|
or <i>network</i><b>_</b><i>address</i> form (see ADDRESS PATTERN SYNTAX below).
|
||||||
|
|
||||||
An IPv4 network address is a sequence of four decimal octets
|
<b>!</b><i>pattern result</i>
|
||||||
separated by ".", and an IPv6 network address is a sequence of
|
When a search string does not match the specified <i>pattern</i>, use
|
||||||
three to eight hexadecimal octet pairs separated by ":".
|
the specified <i>result</i> value. The <i>pattern</i> must be in <i>network/pre-</i>
|
||||||
|
<i>fix</i> or <i>network</i><b>_</b><i>address</i> form (see ADDRESS PATTERN SYNTAX below).
|
||||||
|
|
||||||
The <i>network</i><b>_</b><i>mask</i> is the number of high-order bits in the <i>net-</i>
|
This feature is available in Postfix 3.2 and later.
|
||||||
<i>work</i><b>_</b><i>address</i> that the search string must match.
|
|
||||||
|
|
||||||
Before comparisons are made, lookup keys and table entries are
|
<b>if</b> <i>pattern</i>
|
||||||
converted from string to binary. Therefore table entries will be
|
|
||||||
matched regardless of redundant zero characters.
|
|
||||||
|
|
||||||
Note: address information may be enclosed inside "[]" but this
|
<b>endif</b> When a search string matches the specified <i>pattern</i>, match that
|
||||||
form is not required.
|
search string against the patterns between <b>if</b> and <b>endif</b>. The
|
||||||
|
<i>pattern</i> must be in <i>network/prefix</i> or <i>network</i><b>_</b><i>address</i> form (see
|
||||||
|
ADDRESS PATTERN SYNTAX below). The <b>if</b>..<b>endif</b> can nest.
|
||||||
|
|
||||||
IPv6 support is available in Postfix 2.2 and later.
|
Note: do not prepend whitespace to text between <b>if</b>..<b>endif</b>.
|
||||||
|
|
||||||
<i>network</i><b>_</b><i>address result</i>
|
This feature is available in Postfix 3.2 and later.
|
||||||
When a search string matches the specified network address, use
|
|
||||||
the corresponding <i>result</i> value.
|
<b>if !</b><i>pattern</i>
|
||||||
|
|
||||||
|
<b>endif</b> When a search string does not match the specified <i>pattern</i>, match
|
||||||
|
that search string against the patterns between <b>if</b> and <b>endif</b>.
|
||||||
|
The <i>pattern</i> must be in <i>network/prefix</i> or <i>network</i><b>_</b><i>address</i> form
|
||||||
|
(see ADDRESS PATTERN SYNTAX below). The <b>if</b>..<b>endif</b> can nest.
|
||||||
|
|
||||||
|
Note: do not prepend whitespace to text between <b>if</b>..<b>endif</b>.
|
||||||
|
|
||||||
|
This feature is available in Postfix 3.2 and later.
|
||||||
|
|
||||||
blank lines and comments
|
blank lines and comments
|
||||||
Empty lines and whitespace-only lines are ignored, as are lines
|
Empty lines and whitespace-only lines are ignored, as are lines
|
||||||
@ -67,6 +76,27 @@ CIDR_TABLE(5) CIDR_TABLE(5)
|
|||||||
Patterns are applied in the order as specified in the table, until a
|
Patterns are applied in the order as specified in the table, until a
|
||||||
pattern is found that matches the search string.
|
pattern is found that matches the search string.
|
||||||
|
|
||||||
|
<b>ADDRESS PATTERN SYNTAX</b>
|
||||||
|
Postfix CIDR tables are pattern-based. A pattern is either a <i>net-</i>
|
||||||
|
<i>work</i><b>_</b><i>address</i> which requires an exact match, or a <i>network</i><b>_</b><i>address/pre-</i>
|
||||||
|
<i>fix</i><b>_</b><i>length</i> where the <i>prefix</i><b>_</b><i>length</i> part specifies the length of the
|
||||||
|
<i>network</i><b>_</b><i>address</i> prefix that must be matched (the other bits in the <i>net-</i>
|
||||||
|
<i>work</i><b>_</b><i>address</i> part must be zero).
|
||||||
|
|
||||||
|
An IPv4 network address is a sequence of four decimal octets separated
|
||||||
|
by ".", and an IPv6 network address is a sequence of three to eight
|
||||||
|
hexadecimal octets or octet pairs separated by ":". The pattern
|
||||||
|
0.0.0.0/0 matches every IPv4 address, and ::/0 matches every IPv6
|
||||||
|
address. IPv6 support is available in Postfix 2.2 and later.
|
||||||
|
|
||||||
|
Before comparisons are made, lookup keys and table entries are con-
|
||||||
|
verted from string to binary. Therefore, IPv6 patterns will be matched
|
||||||
|
regardless of leading zeros (a leading zero in an IPv4 address octet
|
||||||
|
indicates octal notation).
|
||||||
|
|
||||||
|
Note: address information may be enclosed inside "[]" but this form is
|
||||||
|
not required.
|
||||||
|
|
||||||
<b>EXAMPLE SMTPD ACCESS MAP</b>
|
<b>EXAMPLE SMTPD ACCESS MAP</b>
|
||||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||||
<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> = ... <a href="cidr_table.5.html">cidr</a>:/etc/postfix/client.cidr ...
|
<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> = ... <a href="cidr_table.5.html">cidr</a>:/etc/postfix/client.cidr ...
|
||||||
|
@ -33,30 +33,42 @@ described in the SYNOPSIS above.
|
|||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
The general form of a Postfix CIDR table is:
|
The general form of a Postfix CIDR table is:
|
||||||
.IP "\fInetwork_address\fB/\fInetwork_mask result\fR"
|
.IP "\fIpattern result\fR"
|
||||||
When a search string matches the specified network block,
|
When a search string matches the specified \fIpattern\fR, use
|
||||||
use the corresponding \fIresult\fR value. Specify
|
the corresponding \fIresult\fR value. The \fIpattern\fR must be
|
||||||
0.0.0.0/0 to match every IPv4 address, and ::/0 to match
|
in \fInetwork/prefix\fR or \fInetwork_address\fR form (see
|
||||||
every IPv6 address.
|
ADDRESS PATTERN SYNTAX below).
|
||||||
|
.IP "\fB!\fIpattern result\fR"
|
||||||
An IPv4 network address is a sequence of four decimal octets
|
When a search string does not match the specified \fIpattern\fR,
|
||||||
separated by ".", and an IPv6 network address is a sequence
|
use the specified \fIresult\fR value. The \fIpattern\fR must
|
||||||
of three to eight hexadecimal octet pairs separated by ":".
|
be in \fInetwork/prefix\fR or \fInetwork_address\fR form (see
|
||||||
|
ADDRESS PATTERN SYNTAX below).
|
||||||
The \fInetwork_mask\fR is the number of high\-order bits in
|
.sp
|
||||||
the \fInetwork_address\fR that the search string must match.
|
This feature is available in Postfix 3.2 and later.
|
||||||
|
.IP "\fBif \fIpattern\fR"
|
||||||
Before comparisons are made, lookup keys and table entries
|
.IP "\fBendif\fR"
|
||||||
are converted from string to binary. Therefore table entries
|
When a search string matches the specified \fIpattern\fR, match
|
||||||
will be matched regardless of redundant zero characters.
|
that search string against the patterns between \fBif\fR and
|
||||||
|
\fBendif\fR. The \fIpattern\fR must be in \fInetwork/prefix\fR or
|
||||||
Note: address information may be enclosed inside "[]" but
|
\fInetwork_address\fR form (see ADDRESS PATTERN SYNTAX below). The
|
||||||
this form is not required.
|
\fBif\fR..\fBendif\fR can nest.
|
||||||
|
.sp
|
||||||
IPv6 support is available in Postfix 2.2 and later.
|
Note: do not prepend whitespace to text between
|
||||||
.IP "\fInetwork_address result\fR"
|
\fBif\fR..\fBendif\fR.
|
||||||
When a search string matches the specified network address,
|
.sp
|
||||||
use the corresponding \fIresult\fR value.
|
This feature is available in Postfix 3.2 and later.
|
||||||
|
.IP "\fBif !\fIpattern\fR"
|
||||||
|
.IP "\fBendif\fR"
|
||||||
|
When a search string does not match the specified \fIpattern\fR,
|
||||||
|
match that search string against the patterns between \fBif\fR and
|
||||||
|
\fBendif\fR. The \fIpattern\fR must be in \fInetwork/prefix\fR or
|
||||||
|
\fInetwork_address\fR form (see ADDRESS PATTERN SYNTAX below). The
|
||||||
|
\fBif\fR..\fBendif\fR can nest.
|
||||||
|
.sp
|
||||||
|
Note: do not prepend whitespace to text between
|
||||||
|
\fBif\fR..\fBendif\fR.
|
||||||
|
.sp
|
||||||
|
This feature is available in Postfix 3.2 and later.
|
||||||
.IP "blank lines and comments"
|
.IP "blank lines and comments"
|
||||||
Empty lines and whitespace\-only lines are ignored, as
|
Empty lines and whitespace\-only lines are ignored, as
|
||||||
are lines whose first non\-whitespace character is a `#'.
|
are lines whose first non\-whitespace character is a `#'.
|
||||||
@ -70,6 +82,32 @@ starts with whitespace continues a logical line.
|
|||||||
.fi
|
.fi
|
||||||
Patterns are applied in the order as specified in the table, until a
|
Patterns are applied in the order as specified in the table, until a
|
||||||
pattern is found that matches the search string.
|
pattern is found that matches the search string.
|
||||||
|
.SH "ADDRESS PATTERN SYNTAX"
|
||||||
|
.na
|
||||||
|
.nf
|
||||||
|
.ad
|
||||||
|
.fi
|
||||||
|
Postfix CIDR tables are pattern\-based. A pattern is either
|
||||||
|
a \fInetwork_address\fR which requires an exact match, or a
|
||||||
|
\fInetwork_address/prefix_length\fR where the \fIprefix_length\fR
|
||||||
|
part specifies the length of the \fInetwork_address\fR prefix
|
||||||
|
that must be matched (the other bits in the \fInetwork_address\fR
|
||||||
|
part must be zero).
|
||||||
|
|
||||||
|
An IPv4 network address is a sequence of four decimal octets
|
||||||
|
separated by ".", and an IPv6 network address is a sequence
|
||||||
|
of three to eight hexadecimal octets or octet pairs separated by
|
||||||
|
":". The pattern 0.0.0.0/0 matches every IPv4 address, and ::/0
|
||||||
|
matches every IPv6 address. IPv6 support is available in
|
||||||
|
Postfix 2.2 and later.
|
||||||
|
|
||||||
|
Before comparisons are made, lookup keys and table entries
|
||||||
|
are converted from string to binary. Therefore, IPv6 patterns
|
||||||
|
will be matched regardless of leading zeros (a leading zero in
|
||||||
|
an IPv4 address octet indicates octal notation).
|
||||||
|
|
||||||
|
Note: address information may be enclosed inside "[]" but
|
||||||
|
this form is not required.
|
||||||
.SH "EXAMPLE SMTPD ACCESS MAP"
|
.SH "EXAMPLE SMTPD ACCESS MAP"
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
|
@ -25,30 +25,42 @@
|
|||||||
# .ad
|
# .ad
|
||||||
# .fi
|
# .fi
|
||||||
# The general form of a Postfix CIDR table is:
|
# The general form of a Postfix CIDR table is:
|
||||||
# .IP "\fInetwork_address\fB/\fInetwork_mask result\fR"
|
# .IP "\fIpattern result\fR"
|
||||||
# When a search string matches the specified network block,
|
# When a search string matches the specified \fIpattern\fR, use
|
||||||
# use the corresponding \fIresult\fR value. Specify
|
# the corresponding \fIresult\fR value. The \fIpattern\fR must be
|
||||||
# 0.0.0.0/0 to match every IPv4 address, and ::/0 to match
|
# in \fInetwork/prefix\fR or \fInetwork_address\fR form (see
|
||||||
# every IPv6 address.
|
# ADDRESS PATTERN SYNTAX below).
|
||||||
#
|
# .IP "\fB!\fIpattern result\fR"
|
||||||
# An IPv4 network address is a sequence of four decimal octets
|
# When a search string does not match the specified \fIpattern\fR,
|
||||||
# separated by ".", and an IPv6 network address is a sequence
|
# use the specified \fIresult\fR value. The \fIpattern\fR must
|
||||||
# of three to eight hexadecimal octet pairs separated by ":".
|
# be in \fInetwork/prefix\fR or \fInetwork_address\fR form (see
|
||||||
#
|
# ADDRESS PATTERN SYNTAX below).
|
||||||
# The \fInetwork_mask\fR is the number of high-order bits in
|
# .sp
|
||||||
# the \fInetwork_address\fR that the search string must match.
|
# This feature is available in Postfix 3.2 and later.
|
||||||
#
|
# .IP "\fBif \fIpattern\fR"
|
||||||
# Before comparisons are made, lookup keys and table entries
|
# .IP "\fBendif\fR"
|
||||||
# are converted from string to binary. Therefore table entries
|
# When a search string matches the specified \fIpattern\fR, match
|
||||||
# will be matched regardless of redundant zero characters.
|
# that search string against the patterns between \fBif\fR and
|
||||||
#
|
# \fBendif\fR. The \fIpattern\fR must be in \fInetwork/prefix\fR or
|
||||||
# Note: address information may be enclosed inside "[]" but
|
# \fInetwork_address\fR form (see ADDRESS PATTERN SYNTAX below). The
|
||||||
# this form is not required.
|
# \fBif\fR..\fBendif\fR can nest.
|
||||||
#
|
# .sp
|
||||||
# IPv6 support is available in Postfix 2.2 and later.
|
# Note: do not prepend whitespace to text between
|
||||||
# .IP "\fInetwork_address result\fR"
|
# \fBif\fR..\fBendif\fR.
|
||||||
# When a search string matches the specified network address,
|
# .sp
|
||||||
# use the corresponding \fIresult\fR value.
|
# This feature is available in Postfix 3.2 and later.
|
||||||
|
# .IP "\fBif !\fIpattern\fR"
|
||||||
|
# .IP "\fBendif\fR"
|
||||||
|
# When a search string does not match the specified \fIpattern\fR,
|
||||||
|
# match that search string against the patterns between \fBif\fR and
|
||||||
|
# \fBendif\fR. The \fIpattern\fR must be in \fInetwork/prefix\fR or
|
||||||
|
# \fInetwork_address\fR form (see ADDRESS PATTERN SYNTAX below). The
|
||||||
|
# \fBif\fR..\fBendif\fR can nest.
|
||||||
|
# .sp
|
||||||
|
# Note: do not prepend whitespace to text between
|
||||||
|
# \fBif\fR..\fBendif\fR.
|
||||||
|
# .sp
|
||||||
|
# This feature is available in Postfix 3.2 and later.
|
||||||
# .IP "blank lines and comments"
|
# .IP "blank lines and comments"
|
||||||
# Empty lines and whitespace-only lines are ignored, as
|
# Empty lines and whitespace-only lines are ignored, as
|
||||||
# are lines whose first non-whitespace character is a `#'.
|
# are lines whose first non-whitespace character is a `#'.
|
||||||
@ -60,6 +72,30 @@
|
|||||||
# .fi
|
# .fi
|
||||||
# Patterns are applied in the order as specified in the table, until a
|
# Patterns are applied in the order as specified in the table, until a
|
||||||
# pattern is found that matches the search string.
|
# pattern is found that matches the search string.
|
||||||
|
# ADDRESS PATTERN SYNTAX
|
||||||
|
# .ad
|
||||||
|
# .fi
|
||||||
|
# Postfix CIDR tables are pattern-based. A pattern is either
|
||||||
|
# a \fInetwork_address\fR which requires an exact match, or a
|
||||||
|
# \fInetwork_address/prefix_length\fR where the \fIprefix_length\fR
|
||||||
|
# part specifies the length of the \fInetwork_address\fR prefix
|
||||||
|
# that must be matched (the other bits in the \fInetwork_address\fR
|
||||||
|
# part must be zero).
|
||||||
|
#
|
||||||
|
# An IPv4 network address is a sequence of four decimal octets
|
||||||
|
# separated by ".", and an IPv6 network address is a sequence
|
||||||
|
# of three to eight hexadecimal octets or octet pairs separated by
|
||||||
|
# ":". The pattern 0.0.0.0/0 matches every IPv4 address, and ::/0
|
||||||
|
# matches every IPv6 address. IPv6 support is available in
|
||||||
|
# Postfix 2.2 and later.
|
||||||
|
#
|
||||||
|
# Before comparisons are made, lookup keys and table entries
|
||||||
|
# are converted from string to binary. Therefore, IPv6 patterns
|
||||||
|
# will be matched regardless of leading zeros (a leading zero in
|
||||||
|
# an IPv4 address octet indicates octal notation).
|
||||||
|
#
|
||||||
|
# Note: address information may be enclosed inside "[]" but
|
||||||
|
# this form is not required.
|
||||||
# EXAMPLE SMTPD ACCESS MAP
|
# EXAMPLE SMTPD ACCESS MAP
|
||||||
# .nf
|
# .nf
|
||||||
# /etc/postfix/main.cf:
|
# /etc/postfix/main.cf:
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* Patches change both the patchlevel and the release date. Snapshots have no
|
* Patches change both the patchlevel and the release date. Snapshots have no
|
||||||
* patchlevel; they change the release date only.
|
* patchlevel; they change the release date only.
|
||||||
*/
|
*/
|
||||||
#define MAIL_RELEASE_DATE "20160522"
|
#define MAIL_RELEASE_DATE "20160527"
|
||||||
#define MAIL_VERSION_NUMBER "3.2"
|
#define MAIL_VERSION_NUMBER "3.2"
|
||||||
|
|
||||||
#ifdef SNAPSHOT
|
#ifdef SNAPSHOT
|
||||||
|
@ -14,6 +14,14 @@
|
|||||||
/* int cidr_match_execute(info, address)
|
/* int cidr_match_execute(info, address)
|
||||||
/* CIDR_MATCH *info;
|
/* CIDR_MATCH *info;
|
||||||
/* const char *address;
|
/* const char *address;
|
||||||
|
/* AUXILIARY FUNCTIONS
|
||||||
|
/* VSTRING *cidr_match_parse_if(info, address, why)
|
||||||
|
/* CIDR_MATCH *info;
|
||||||
|
/* char *address;
|
||||||
|
/* VSTRING *why;
|
||||||
|
/*
|
||||||
|
/* void cidr_match_endif(info)
|
||||||
|
/* CIDR_MATCH *info;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module parses address or address/length patterns and
|
/* This module parses address or address/length patterns and
|
||||||
/* provides simple address matching. The implementation is
|
/* provides simple address matching. The implementation is
|
||||||
@ -29,6 +37,12 @@
|
|||||||
/* (the caller should give the latter to vstring_free()).
|
/* (the caller should give the latter to vstring_free()).
|
||||||
/* The pattern argument is destroyed.
|
/* The pattern argument is destroyed.
|
||||||
/*
|
/*
|
||||||
|
/* cidr_match_parse_if() parses the address that follows an IF
|
||||||
|
/* token, and stores the result into the info argument.
|
||||||
|
/*
|
||||||
|
/* cidr_match_endif() handles the occurrence of an ENDIF token,
|
||||||
|
/* and updates the info argument.
|
||||||
|
/*
|
||||||
/* cidr_match_execute() matches the specified address against
|
/* cidr_match_execute() matches the specified address against
|
||||||
/* a list of parsed expressions, and returns the matching
|
/* a list of parsed expressions, and returns the matching
|
||||||
/* expression's data structure.
|
/* expression's data structure.
|
||||||
@ -39,6 +53,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -88,15 +107,44 @@
|
|||||||
(msg_panic("%s: bad address family %d", myname, (f)), 0))
|
(msg_panic("%s: bad address family %d", myname, (f)), 0))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* cidr_match_entry - match one entry */
|
||||||
|
|
||||||
|
static inline int cidr_match_entry(CIDR_MATCH *entry,
|
||||||
|
unsigned char *addr_bytes)
|
||||||
|
{
|
||||||
|
unsigned char *mp;
|
||||||
|
unsigned char *np;
|
||||||
|
unsigned char *ap;
|
||||||
|
|
||||||
|
/* Unoptimized case: netmask with some or all bits zero. */
|
||||||
|
if (entry->mask_shift < entry->addr_bit_count) {
|
||||||
|
for (np = entry->net_bytes, mp = entry->mask_bytes,
|
||||||
|
ap = addr_bytes; /* void */ ; np++, mp++, ap++) {
|
||||||
|
if (ap >= addr_bytes + entry->addr_byte_count)
|
||||||
|
return (entry->match);
|
||||||
|
if ((*ap & *mp) != *np)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Optimized case: all 1 netmask (i.e. no netmask specified). */
|
||||||
|
else {
|
||||||
|
for (np = entry->net_bytes,
|
||||||
|
ap = addr_bytes; /* void */ ; np++, ap++) {
|
||||||
|
if (ap >= addr_bytes + entry->addr_byte_count)
|
||||||
|
return (entry->match);
|
||||||
|
if (*ap != *np)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (!entry->match);
|
||||||
|
}
|
||||||
|
|
||||||
/* cidr_match_execute - match address against compiled CIDR pattern list */
|
/* cidr_match_execute - match address against compiled CIDR pattern list */
|
||||||
|
|
||||||
CIDR_MATCH *cidr_match_execute(CIDR_MATCH *list, const char *addr)
|
CIDR_MATCH *cidr_match_execute(CIDR_MATCH *list, const char *addr)
|
||||||
{
|
{
|
||||||
unsigned char addr_bytes[CIDR_MATCH_ABYTES];
|
unsigned char addr_bytes[CIDR_MATCH_ABYTES];
|
||||||
unsigned addr_family;
|
unsigned addr_family;
|
||||||
unsigned char *mp;
|
|
||||||
unsigned char *np;
|
|
||||||
unsigned char *ap;
|
|
||||||
CIDR_MATCH *entry;
|
CIDR_MATCH *entry;
|
||||||
|
|
||||||
addr_family = CIDR_MATCH_ADDR_FAMILY(addr);
|
addr_family = CIDR_MATCH_ADDR_FAMILY(addr);
|
||||||
@ -104,27 +152,26 @@ CIDR_MATCH *cidr_match_execute(CIDR_MATCH *list, const char *addr)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
for (entry = list; entry; entry = entry->next) {
|
for (entry = list; entry; entry = entry->next) {
|
||||||
if (entry->addr_family == addr_family) {
|
|
||||||
/* Unoptimized case: netmask with some or all bits zero. */
|
switch (entry->op) {
|
||||||
if (entry->mask_shift < entry->addr_bit_count) {
|
|
||||||
for (np = entry->net_bytes, mp = entry->mask_bytes,
|
case CIDR_MATCH_OP_MATCH:
|
||||||
ap = addr_bytes; /* void */ ; np++, mp++, ap++) {
|
if (entry->addr_family == addr_family)
|
||||||
if (ap >= addr_bytes + entry->addr_byte_count)
|
if (cidr_match_entry(entry, addr_bytes))
|
||||||
return (entry);
|
return (entry);
|
||||||
if ((*ap & *mp) != *np)
|
break;
|
||||||
break;
|
|
||||||
}
|
case CIDR_MATCH_OP_IF:
|
||||||
}
|
if (entry->addr_family == addr_family)
|
||||||
/* Optimized case: all 1 netmask (i.e. no netmask specified). */
|
if (cidr_match_entry(entry, addr_bytes))
|
||||||
else {
|
continue;
|
||||||
for (np = entry->net_bytes,
|
/* An IF without matching ENDIF has no end-of block entry. */
|
||||||
ap = addr_bytes; /* void */ ; np++, ap++) {
|
if ((entry = entry->block_end) == 0)
|
||||||
if (ap >= addr_bytes + entry->addr_byte_count)
|
break;
|
||||||
return (entry);
|
/* FALLTHROUGH */
|
||||||
if (*ap != *np)
|
|
||||||
break;
|
case CIDR_MATCH_OP_ENDIF:
|
||||||
}
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
@ -141,6 +188,23 @@ VSTRING *cidr_match_parse(CIDR_MATCH *ip, char *pattern, VSTRING *why)
|
|||||||
unsigned char *np;
|
unsigned char *np;
|
||||||
unsigned char *mp;
|
unsigned char *mp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process negation operators. XXX unlike dict_regexp_get_pat() and
|
||||||
|
* dict_pcre_get_pattern(), dict_cidr_parse_rule() does not allow space
|
||||||
|
* between ! and the remainder of a pattern. However, those spaces are
|
||||||
|
* not documented, they were more a helpful thing.
|
||||||
|
*/
|
||||||
|
ip->match = 1;
|
||||||
|
while (*pattern == '!') {
|
||||||
|
ip->match = !ip->match;
|
||||||
|
pattern++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*pattern == 0) {
|
||||||
|
vstring_sprintf(why ? why : (why = vstring_alloc(20)), "no pattern");
|
||||||
|
return (why);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strip [] from [addr/len] or [addr]/len, destroying the pattern. CIDR
|
* Strip [] from [addr/len] or [addr]/len, destroying the pattern. CIDR
|
||||||
* maps don't need [] to eliminate syntax ambiguity, but matchlists need
|
* maps don't need [] to eliminate syntax ambiguity, but matchlists need
|
||||||
@ -224,7 +288,30 @@ VSTRING *cidr_match_parse(CIDR_MATCH *ip, char *pattern, VSTRING *why)
|
|||||||
/*
|
/*
|
||||||
* Wrap up the result.
|
* Wrap up the result.
|
||||||
*/
|
*/
|
||||||
|
ip->op = CIDR_MATCH_OP_MATCH;
|
||||||
ip->next = 0;
|
ip->next = 0;
|
||||||
|
ip->block_end = 0;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* cidr_match_parse_if - parse CIDR pattern after IF */
|
||||||
|
|
||||||
|
VSTRING *cidr_match_parse_if(CIDR_MATCH *ip, char *pattern, VSTRING *why)
|
||||||
|
{
|
||||||
|
VSTRING *ret;
|
||||||
|
|
||||||
|
if ((ret = cidr_match_parse(ip, pattern, why)) == 0)
|
||||||
|
ip->op = CIDR_MATCH_OP_IF;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cidr_match_endif - handle ENDIF pattern */
|
||||||
|
|
||||||
|
void cidr_match_endif(CIDR_MATCH *ip)
|
||||||
|
{
|
||||||
|
memset(ip, 0, sizeof(*ip));
|
||||||
|
ip->op = CIDR_MATCH_OP_ENDIF;
|
||||||
|
ip->next = 0; /* maybe not all bits 0 */
|
||||||
|
ip->block_end = 0;
|
||||||
|
}
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
* Each parsed CIDR pattern can be member of a linked list.
|
* Each parsed CIDR pattern can be member of a linked list.
|
||||||
*/
|
*/
|
||||||
typedef struct CIDR_MATCH {
|
typedef struct CIDR_MATCH {
|
||||||
|
int op; /* operation, match or control flow */
|
||||||
|
int match; /* positive or negative match */
|
||||||
unsigned char net_bytes[CIDR_MATCH_ABYTES]; /* network portion */
|
unsigned char net_bytes[CIDR_MATCH_ABYTES]; /* network portion */
|
||||||
unsigned char mask_bytes[CIDR_MATCH_ABYTES]; /* network mask */
|
unsigned char mask_bytes[CIDR_MATCH_ABYTES]; /* network mask */
|
||||||
unsigned char addr_family; /* AF_XXX */
|
unsigned char addr_family; /* AF_XXX */
|
||||||
@ -45,9 +47,17 @@ typedef struct CIDR_MATCH {
|
|||||||
unsigned char addr_bit_count; /* optimization */
|
unsigned char addr_bit_count; /* optimization */
|
||||||
unsigned char mask_shift; /* optimization */
|
unsigned char mask_shift; /* optimization */
|
||||||
struct CIDR_MATCH *next; /* next entry */
|
struct CIDR_MATCH *next; /* next entry */
|
||||||
|
struct CIDR_MATCH *block_end; /* block terminator */
|
||||||
} CIDR_MATCH;
|
} CIDR_MATCH;
|
||||||
|
|
||||||
|
#define CIDR_MATCH_OP_MATCH 1 /* Match this pattern */
|
||||||
|
#define CIDR_MATCH_OP_IF 2 /* Increase if/endif nesting on match */
|
||||||
|
#define CIDR_MATCH_OP_ENDIF 3 /* Decrease if/endif nesting on match */
|
||||||
|
|
||||||
extern VSTRING *cidr_match_parse(CIDR_MATCH *, char *, VSTRING *);
|
extern VSTRING *cidr_match_parse(CIDR_MATCH *, char *, VSTRING *);
|
||||||
|
extern VSTRING *cidr_match_parse_if(CIDR_MATCH *, char *, VSTRING *);
|
||||||
|
extern void cidr_match_endif(CIDR_MATCH *);
|
||||||
|
|
||||||
extern CIDR_MATCH *cidr_match_execute(CIDR_MATCH *, const char *);
|
extern CIDR_MATCH *cidr_match_execute(CIDR_MATCH *, const char *);
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
@ -59,6 +69,11 @@ extern CIDR_MATCH *cidr_match_execute(CIDR_MATCH *, const char *);
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -54,6 +59,7 @@
|
|||||||
#include <cidr_match.h>
|
#include <cidr_match.h>
|
||||||
#include <dict_cidr.h>
|
#include <dict_cidr.h>
|
||||||
#include <warn_stat.h>
|
#include <warn_stat.h>
|
||||||
|
#include <mvect.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@ -63,6 +69,7 @@
|
|||||||
typedef struct DICT_CIDR_ENTRY {
|
typedef struct DICT_CIDR_ENTRY {
|
||||||
CIDR_MATCH cidr_info; /* must be first */
|
CIDR_MATCH cidr_info; /* must be first */
|
||||||
char *value; /* lookup result */
|
char *value; /* lookup result */
|
||||||
|
int lineno;
|
||||||
} DICT_CIDR_ENTRY;
|
} DICT_CIDR_ENTRY;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -106,7 +113,8 @@ static void dict_cidr_close(DICT *dict)
|
|||||||
|
|
||||||
/* dict_cidr_parse_rule - parse CIDR table rule into network, mask and value */
|
/* dict_cidr_parse_rule - parse CIDR table rule into network, mask and value */
|
||||||
|
|
||||||
static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why)
|
static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, int lineno, int nesting,
|
||||||
|
VSTRING *why)
|
||||||
{
|
{
|
||||||
DICT_CIDR_ENTRY *rule;
|
DICT_CIDR_ENTRY *rule;
|
||||||
char *pattern;
|
char *pattern;
|
||||||
@ -115,33 +123,76 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why)
|
|||||||
MAI_HOSTADDR_STR hostaddr;
|
MAI_HOSTADDR_STR hostaddr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Split the rule into key and value. We already eliminated leading
|
* IF must be followed by a pattern.
|
||||||
* whitespace, comments, empty lines or lines with whitespace only. This
|
|
||||||
* means a null key can't happen but we will handle this anyway.
|
|
||||||
*/
|
*/
|
||||||
pattern = p;
|
if (strncasecmp(p, "IF", 2) == 0 && !ISALNUM(p[2])) {
|
||||||
while (*p && !ISSPACE(*p)) /* Skip over key */
|
p += 2;
|
||||||
p++;
|
while (*p && ISSPACE(*p)) /* Skip whitespace */
|
||||||
if (*p) /* Terminate key */
|
p++;
|
||||||
*p++ = 0;
|
if (*p == 0) {
|
||||||
while (*p && ISSPACE(*p)) /* Skip whitespace */
|
vstring_sprintf(why, "no address pattern");
|
||||||
p++;
|
return (0);
|
||||||
value = p;
|
}
|
||||||
trimblanks(value, 0)[0] = 0; /* Trim trailing blanks */
|
trimblanks(p, 0)[0] = 0; /* Trim trailing blanks */
|
||||||
if (*pattern == 0) {
|
if (cidr_match_parse_if(&cidr_info, p, why) != 0)
|
||||||
vstring_sprintf(why, "no address pattern");
|
return (0);
|
||||||
return (0);
|
value = "";
|
||||||
}
|
|
||||||
if (*value == 0) {
|
|
||||||
vstring_sprintf(why, "no lookup result");
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the pattern, destroying it in the process.
|
* ENDIF must not be followed by other text.
|
||||||
*/
|
*/
|
||||||
if (cidr_match_parse(&cidr_info, pattern, why) != 0)
|
else if (strncasecmp(p, "ENDIF", 5) == 0 && !ISALNUM(p[5])) {
|
||||||
return (0);
|
p += 5;
|
||||||
|
while (*p && ISSPACE(*p)) /* Skip whitespace */
|
||||||
|
p++;
|
||||||
|
if (*p != 0) {
|
||||||
|
vstring_sprintf(why, "garbage after ENDIF");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (nesting == 0) {
|
||||||
|
vstring_sprintf(why, "ENDIF without IF");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
cidr_match_endif(&cidr_info);
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An address pattern.
|
||||||
|
*/
|
||||||
|
else {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split the rule into key and value. We already eliminated leading
|
||||||
|
* whitespace, comments, empty lines or lines with whitespace only.
|
||||||
|
* This means a null key can't happen but we will handle this anyway.
|
||||||
|
*/
|
||||||
|
pattern = p;
|
||||||
|
while (*p && !ISSPACE(*p)) /* Skip over key */
|
||||||
|
p++;
|
||||||
|
if (*p) /* Terminate key */
|
||||||
|
*p++ = 0;
|
||||||
|
while (*p && ISSPACE(*p)) /* Skip whitespace */
|
||||||
|
p++;
|
||||||
|
value = p;
|
||||||
|
trimblanks(value, 0)[0] = 0; /* Trim trailing blanks */
|
||||||
|
if (*pattern == 0) {
|
||||||
|
vstring_sprintf(why, "no address pattern");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the pattern, destroying it in the process.
|
||||||
|
*/
|
||||||
|
if (cidr_match_parse(&cidr_info, pattern, why) != 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
if (*value == 0) {
|
||||||
|
vstring_sprintf(why, "no lookup result");
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Bundle up the result.
|
* Bundle up the result.
|
||||||
@ -149,6 +200,7 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why)
|
|||||||
rule = (DICT_CIDR_ENTRY *) mymalloc(sizeof(DICT_CIDR_ENTRY));
|
rule = (DICT_CIDR_ENTRY *) mymalloc(sizeof(DICT_CIDR_ENTRY));
|
||||||
rule->cidr_info = cidr_info;
|
rule->cidr_info = cidr_info;
|
||||||
rule->value = mystrdup(value);
|
rule->value = mystrdup(value);
|
||||||
|
rule->lineno = lineno;
|
||||||
|
|
||||||
if (msg_verbose) {
|
if (msg_verbose) {
|
||||||
if (inet_ntop(cidr_info.addr_family, cidr_info.net_bytes,
|
if (inet_ntop(cidr_info.addr_family, cidr_info.net_bytes,
|
||||||
@ -164,6 +216,7 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why)
|
|||||||
|
|
||||||
DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
|
DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
|
||||||
{
|
{
|
||||||
|
const char myname[] = "dict_cidr_open";
|
||||||
DICT_CIDR *dict_cidr;
|
DICT_CIDR *dict_cidr;
|
||||||
VSTREAM *map_fp = 0;
|
VSTREAM *map_fp = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -173,6 +226,9 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
|
|||||||
DICT_CIDR_ENTRY *last_rule = 0;
|
DICT_CIDR_ENTRY *last_rule = 0;
|
||||||
int last_line = 0;
|
int last_line = 0;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
int nesting = 0;
|
||||||
|
DICT_CIDR_ENTRY **rule_stack = 0;
|
||||||
|
MVECT mvect;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let the optimizer worry about eliminating redundant code.
|
* Let the optimizer worry about eliminating redundant code.
|
||||||
@ -225,12 +281,35 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
|
|||||||
dict_cidr->dict.owner.status = (st.st_uid != 0);
|
dict_cidr->dict.owner.status = (st.st_uid != 0);
|
||||||
|
|
||||||
while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
|
while (readllines(line_buffer, map_fp, &last_line, &lineno)) {
|
||||||
rule = dict_cidr_parse_rule(vstring_str(line_buffer), why);
|
rule = dict_cidr_parse_rule(vstring_str(line_buffer), lineno,
|
||||||
|
nesting, why);
|
||||||
if (rule == 0) {
|
if (rule == 0) {
|
||||||
msg_warn("cidr map %s, line %d: %s: skipping this rule",
|
msg_warn("cidr map %s, line %d: %s: skipping this rule",
|
||||||
mapname, lineno, vstring_str(why));
|
mapname, lineno, vstring_str(why));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (rule->cidr_info.op == CIDR_MATCH_OP_IF) {
|
||||||
|
if (rule_stack == 0)
|
||||||
|
rule_stack = (DICT_CIDR_ENTRY **) mvect_alloc(&mvect,
|
||||||
|
sizeof(*rule_stack), nesting + 1,
|
||||||
|
(MVECT_FN) 0, (MVECT_FN) 0);
|
||||||
|
else
|
||||||
|
rule_stack =
|
||||||
|
(DICT_CIDR_ENTRY **) mvect_realloc(&mvect, nesting + 1);
|
||||||
|
rule_stack[nesting] = rule;
|
||||||
|
nesting++;
|
||||||
|
} else if (rule->cidr_info.op == CIDR_MATCH_OP_ENDIF) {
|
||||||
|
DICT_CIDR_ENTRY *if_rule;
|
||||||
|
|
||||||
|
if (nesting-- <= 0)
|
||||||
|
/* Already handled in dict_cidr_parse_rule(). */
|
||||||
|
msg_panic("%s: ENDIF without IF", myname);
|
||||||
|
if_rule = rule_stack[nesting];
|
||||||
|
if (if_rule->cidr_info.op != CIDR_MATCH_OP_IF)
|
||||||
|
msg_panic("%s: unexpected rule stack element type %d",
|
||||||
|
myname, if_rule->cidr_info.op);
|
||||||
|
if_rule->cidr_info.block_end = &(rule->cidr_info);
|
||||||
|
}
|
||||||
if (last_rule == 0)
|
if (last_rule == 0)
|
||||||
dict_cidr->head = rule;
|
dict_cidr->head = rule;
|
||||||
else
|
else
|
||||||
@ -238,5 +317,12 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
|
|||||||
last_rule = rule;
|
last_rule = rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (nesting-- > 0)
|
||||||
|
msg_warn("cidr map %s, line %d: IF has no matching ENDIF",
|
||||||
|
mapname, rule_stack[nesting]->lineno);
|
||||||
|
|
||||||
|
if (rule_stack)
|
||||||
|
(void) mvect_free(&mvect);
|
||||||
|
|
||||||
DICT_CIDR_OPEN_RETURN(DICT_DEBUG (&dict_cidr->dict));
|
DICT_CIDR_OPEN_RETURN(DICT_DEBUG (&dict_cidr->dict));
|
||||||
}
|
}
|
||||||
|
@ -9,3 +9,15 @@ get 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
|
|||||||
get 2001:240:5c7:0:2d0:b7ff:febe:ca9f
|
get 2001:240:5c7:0:2d0:b7ff:febe:ca9f
|
||||||
get 1.1.1.1
|
get 1.1.1.1
|
||||||
get 1:1:1:1:1:1:1:1
|
get 1:1:1:1:1:1:1:1
|
||||||
|
get 1.2.3.3
|
||||||
|
get 1.2.3.4
|
||||||
|
get 1.2.3.5
|
||||||
|
get 1.2.3.6
|
||||||
|
get 1.2.3.7
|
||||||
|
get 1.2.3.8
|
||||||
|
get ::f3
|
||||||
|
get ::f4
|
||||||
|
get ::f5
|
||||||
|
get ::f6
|
||||||
|
get ::f7
|
||||||
|
get ::f8
|
||||||
|
@ -7,6 +7,32 @@
|
|||||||
172.999.0.0/21 whatever
|
172.999.0.0/21 whatever
|
||||||
172.16.1.999 whatever
|
172.16.1.999 whatever
|
||||||
172.16.1.4
|
172.16.1.4
|
||||||
|
if 1.2.0.0/16
|
||||||
|
if 1.2.3.4/30
|
||||||
|
1.2.3.3 1.2.3.3 can't happen
|
||||||
|
1.2.3.4 1.2.3.4 can happen
|
||||||
|
1.2.3.5 1.2.3.5 can happen
|
||||||
|
1.2.3.6 1.2.3.6 can happen
|
||||||
|
1.2.3.7 1.2.3.7 can happen
|
||||||
|
1.2.3.8 1.2.3.8 can't happen
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
if !1.2.3.4/30
|
||||||
|
1.2.3.3 1.2.3.3 can happen
|
||||||
|
1.2.3.8 1.2.3.8 can happen
|
||||||
|
endif
|
||||||
|
if ::f4/126
|
||||||
|
::f3 ::f3 can't happen
|
||||||
|
::f4 ::f4 can happen
|
||||||
|
::f5 ::f5 can happen
|
||||||
|
::f6 ::f6 can happen
|
||||||
|
::f7 ::f7 can happen
|
||||||
|
::f8 ::f8 can't happen
|
||||||
|
endif
|
||||||
|
if !::f4/126
|
||||||
|
::f3 ::f3 can happen
|
||||||
|
::f8 ::f8 can happen
|
||||||
|
endif
|
||||||
2001:240:5c7:0:2d0:b7ff:fe88:2ca7 match 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
|
2001:240:5c7:0:2d0:b7ff:fe88:2ca7 match 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
|
||||||
2001:240:5c7::/64 match netblock 2001:240:5c7::/64
|
2001:240:5c7::/64 match netblock 2001:240:5c7::/64
|
||||||
1.0.0.0/0 match 0.0.0.0/0
|
1.0.0.0/0 match 0.0.0.0/0
|
||||||
@ -16,3 +42,9 @@
|
|||||||
[1234 foo
|
[1234 foo
|
||||||
[1234]junk bar
|
[1234]junk bar
|
||||||
172.16.1.3/3x whatever
|
172.16.1.3/3x whatever
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
if 1:2::3:4
|
||||||
|
if 1:2::3:5
|
||||||
|
if !
|
||||||
|
!
|
||||||
|
@ -3,11 +3,17 @@
|
|||||||
./dict_open: warning: cidr map dict_cidr.map, line 7: bad net/mask pattern: "172.999.0.0/21": skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 7: bad net/mask pattern: "172.999.0.0/21": skipping this rule
|
||||||
./dict_open: warning: cidr map dict_cidr.map, line 8: bad address pattern: "172.16.1.999": skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 8: bad address pattern: "172.16.1.999": skipping this rule
|
||||||
./dict_open: warning: cidr map dict_cidr.map, line 9: no lookup result: skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 9: no lookup result: skipping this rule
|
||||||
./dict_open: warning: cidr map dict_cidr.map, line 12: non-null host address bits in "1.0.0.0/0", perhaps you should use "0.0.0.0/0" instead: skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 38: non-null host address bits in "1.0.0.0/0", perhaps you should use "0.0.0.0/0" instead: skipping this rule
|
||||||
./dict_open: warning: cidr map dict_cidr.map, line 14: non-null host address bits in "1::/0", perhaps you should use "::/0" instead: skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 40: non-null host address bits in "1::/0", perhaps you should use "::/0" instead: skipping this rule
|
||||||
./dict_open: warning: cidr map dict_cidr.map, line 16: missing ']' character after "[1234": skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 42: missing ']' character after "[1234": skipping this rule
|
||||||
./dict_open: warning: cidr map dict_cidr.map, line 17: garbage after "[1234]": skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 43: garbage after "[1234]": skipping this rule
|
||||||
./dict_open: warning: cidr map dict_cidr.map, line 18: bad net/mask pattern: "172.16.1.3/3x": skipping this rule
|
./dict_open: warning: cidr map dict_cidr.map, line 44: bad net/mask pattern: "172.16.1.3/3x": skipping this rule
|
||||||
|
./dict_open: warning: cidr map dict_cidr.map, line 45: ENDIF without IF: skipping this rule
|
||||||
|
./dict_open: warning: cidr map dict_cidr.map, line 46: ENDIF without IF: skipping this rule
|
||||||
|
./dict_open: warning: cidr map dict_cidr.map, line 49: no pattern: skipping this rule
|
||||||
|
./dict_open: warning: cidr map dict_cidr.map, line 50: no pattern: skipping this rule
|
||||||
|
./dict_open: warning: cidr map dict_cidr.map, line 48: IF has no matching ENDIF
|
||||||
|
./dict_open: warning: cidr map dict_cidr.map, line 47: IF has no matching ENDIF
|
||||||
owner=untrusted (uid=USER)
|
owner=untrusted (uid=USER)
|
||||||
> get 172.16.0.0
|
> get 172.16.0.0
|
||||||
172.16.0.0=554 match bad netblock 172.16.0.0/21
|
172.16.0.0=554 match bad netblock 172.16.0.0/21
|
||||||
@ -31,3 +37,27 @@ owner=untrusted (uid=USER)
|
|||||||
1.1.1.1=match 0.0.0.0/0
|
1.1.1.1=match 0.0.0.0/0
|
||||||
> get 1:1:1:1:1:1:1:1
|
> get 1:1:1:1:1:1:1:1
|
||||||
1:1:1:1:1:1:1:1=match ::/0
|
1:1:1:1:1:1:1:1=match ::/0
|
||||||
|
> get 1.2.3.3
|
||||||
|
1.2.3.3=1.2.3.3 can happen
|
||||||
|
> get 1.2.3.4
|
||||||
|
1.2.3.4=1.2.3.4 can happen
|
||||||
|
> get 1.2.3.5
|
||||||
|
1.2.3.5=1.2.3.5 can happen
|
||||||
|
> get 1.2.3.6
|
||||||
|
1.2.3.6=1.2.3.6 can happen
|
||||||
|
> get 1.2.3.7
|
||||||
|
1.2.3.7=1.2.3.7 can happen
|
||||||
|
> get 1.2.3.8
|
||||||
|
1.2.3.8=1.2.3.8 can happen
|
||||||
|
> get ::f3
|
||||||
|
::f3=::f3 can happen
|
||||||
|
> get ::f4
|
||||||
|
::f4=::f4 can happen
|
||||||
|
> get ::f5
|
||||||
|
::f5=::f5 can happen
|
||||||
|
> get ::f6
|
||||||
|
::f6=::f6 can happen
|
||||||
|
> get ::f7
|
||||||
|
::f7=::f7 can happen
|
||||||
|
> get ::f8
|
||||||
|
::f8=::f8 can happen
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
#include "sys_defs.h"
|
#include "sys_defs.h"
|
||||||
@ -614,8 +619,8 @@ static DICT_PCRE_RULE *dict_pcre_parse_rule(const char *mapname, int lineno,
|
|||||||
while (*p && ISSPACE(*p))
|
while (*p && ISSPACE(*p))
|
||||||
++p;
|
++p;
|
||||||
if (!*p)
|
if (!*p)
|
||||||
msg_warn("%s, line %d: no replacement text: using empty string",
|
msg_warn("pcre map %s, line %d: no replacement text: "
|
||||||
mapname, lineno);
|
"using empty string", mapname, lineno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check the $number instances in the replacement text.
|
* Sanity check the $number instances in the replacement text.
|
||||||
@ -882,6 +887,7 @@ DICT *dict_pcre_open(const char *mapname, int open_flags, int dict_flags)
|
|||||||
DICT_PCRE_IF_RULE *if_rule;
|
DICT_PCRE_IF_RULE *if_rule;
|
||||||
|
|
||||||
if (nesting-- <= 0)
|
if (nesting-- <= 0)
|
||||||
|
/* Already handled in dict_pcre_parse_rule(). */
|
||||||
msg_panic("%s: ENDIF without IF", myname);
|
msg_panic("%s: ENDIF without IF", myname);
|
||||||
if (rule_stack[nesting]->op != DICT_PCRE_OP_IF)
|
if (rule_stack[nesting]->op != DICT_PCRE_OP_IF)
|
||||||
msg_panic("%s: unexpected rule stack element type %d",
|
msg_panic("%s: unexpected rule stack element type %d",
|
||||||
|
@ -6,6 +6,7 @@ get 3
|
|||||||
get true3
|
get true3
|
||||||
get c
|
get c
|
||||||
get d
|
get d
|
||||||
|
get 1235
|
||||||
get 1234
|
get 1234
|
||||||
get 123
|
get 123
|
||||||
get bar/find
|
get bar/find
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
./dict_open: warning: pcre map dict_pcre.map, line 1: do not prepend whitespace to statements between IF and ENDIF
|
./dict_open: warning: pcre map dict_pcre.map, line 1: do not prepend whitespace to statements between IF and ENDIF
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 5: ignoring extra text after ENDIF
|
./dict_open: warning: pcre map dict_pcre.map, line 5: ignoring extra text after ENDIF
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 8: unknown regexp option "!": skipping this rule
|
./dict_open: warning: pcre map dict_pcre.map, line 8: unknown regexp option "!": skipping this rule
|
||||||
./dict_open: warning: dict_pcre.map, line 9: no replacement text: using empty string
|
./dict_open: warning: pcre map dict_pcre.map, line 9: no replacement text: using empty string
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 10: out of range replacement index "5": skipping this rule
|
./dict_open: warning: pcre map dict_pcre.map, line 10: out of range replacement index "5": skipping this rule
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 17: $number found in negative match replacement text: skipping this rule
|
./dict_open: warning: pcre map dict_pcre.map, line 17: $number found in negative match replacement text: skipping this rule
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 22: no regexp: skipping this rule
|
./dict_open: warning: pcre map dict_pcre.map, line 22: no regexp: skipping this rule
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 23: ignoring ENDIF without matching IF
|
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 24: ignoring ENDIF without matching IF
|
./dict_open: warning: pcre map dict_pcre.map, line 24: ignoring ENDIF without matching IF
|
||||||
|
./dict_open: warning: pcre map dict_pcre.map, line 25: ignoring ENDIF without matching IF
|
||||||
|
./dict_open: warning: pcre map dict_pcre.map, line 27: IF has no matching ENDIF
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 26: IF has no matching ENDIF
|
./dict_open: warning: pcre map dict_pcre.map, line 26: IF has no matching ENDIF
|
||||||
./dict_open: warning: pcre map dict_pcre.map, line 25: IF has no matching ENDIF
|
|
||||||
owner=untrusted (uid=USER)
|
owner=untrusted (uid=USER)
|
||||||
> get true
|
> get true
|
||||||
true: not found
|
true: not found
|
||||||
@ -27,6 +27,8 @@ true3=3
|
|||||||
c=
|
c=
|
||||||
> get d
|
> get d
|
||||||
d: not found
|
d: not found
|
||||||
|
> get 1235
|
||||||
|
1235=(1)(2)(3)
|
||||||
> get 1234
|
> get 1234
|
||||||
1234=(1)(2)(3)(4)
|
1234=(1)(2)(3)(4)
|
||||||
> get 123
|
> get 123
|
||||||
|
@ -31,6 +31,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
@ -575,8 +580,8 @@ static DICT_REGEXP_RULE *dict_regexp_parseline(const char *mapname, int lineno,
|
|||||||
while (*p && ISSPACE(*p))
|
while (*p && ISSPACE(*p))
|
||||||
++p;
|
++p;
|
||||||
if (!*p) {
|
if (!*p) {
|
||||||
msg_warn("regexp map %s, line %d: using empty replacement string",
|
msg_warn("regexp map %s, line %d: no replacement text: "
|
||||||
mapname, lineno);
|
"using empty string", mapname, lineno);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -819,6 +824,7 @@ DICT *dict_regexp_open(const char *mapname, int open_flags, int dict_flags)
|
|||||||
DICT_REGEXP_IF_RULE *if_rule;
|
DICT_REGEXP_IF_RULE *if_rule;
|
||||||
|
|
||||||
if (nesting-- <= 0)
|
if (nesting-- <= 0)
|
||||||
|
/* Already handled in dict_regexp_parseline(). */
|
||||||
msg_panic("%s: ENDIF without IF", myname);
|
msg_panic("%s: ENDIF without IF", myname);
|
||||||
if (rule_stack[nesting]->op != DICT_REGEXP_OP_IF)
|
if (rule_stack[nesting]->op != DICT_REGEXP_OP_IF)
|
||||||
msg_panic("%s: unexpected rule stack element type %d",
|
msg_panic("%s: unexpected rule stack element type %d",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
./dict_open: warning: regexp map dict_regexp.map, line 1: ignoring extra text after IF statement: "fodder"
|
./dict_open: warning: regexp map dict_regexp.map, line 1: ignoring extra text after IF statement: "fodder"
|
||||||
./dict_open: warning: regexp map dict_regexp.map, line 1: do not prepend whitespace to statements between IF and ENDIF
|
./dict_open: warning: regexp map dict_regexp.map, line 1: do not prepend whitespace to statements between IF and ENDIF
|
||||||
./dict_open: warning: regexp map dict_regexp.map, line 5: ignoring extra text after ENDIF
|
./dict_open: warning: regexp map dict_regexp.map, line 5: ignoring extra text after ENDIF
|
||||||
./dict_open: warning: regexp map dict_regexp.map, line 9: using empty replacement string
|
./dict_open: warning: regexp map dict_regexp.map, line 9: no replacement text: using empty string
|
||||||
./dict_open: warning: regexp map dict_regexp.map, line 10: out of range replacement index "5": skipping this rule
|
./dict_open: warning: regexp map dict_regexp.map, line 10: out of range replacement index "5": skipping this rule
|
||||||
./dict_open: warning: regexp map dict_regexp.map, line 17: $number found in negative match replacement text: skipping this rule
|
./dict_open: warning: regexp map dict_regexp.map, line 17: $number found in negative match replacement text: skipping this rule
|
||||||
./dict_open: warning: regexp map dict_regexp.map, line 22: no regexp: skipping this rule
|
./dict_open: warning: regexp map dict_regexp.map, line 22: no regexp: skipping this rule
|
||||||
|
@ -54,6 +54,11 @@
|
|||||||
/* IBM T.J. Watson Research
|
/* IBM T.J. Watson Research
|
||||||
/* P.O. Box 704
|
/* P.O. Box 704
|
||||||
/* Yorktown Heights, NY 10598, USA
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*
|
||||||
|
/* Wietse Venema
|
||||||
|
/* Google, Inc.
|
||||||
|
/* 111 8th Avenue
|
||||||
|
/* New York, NY 10011, USA
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
/* System library. */
|
/* System library. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user