Check Arbitrary Network Blocks in CIDR Notation

Last Update 1998-08-27
From: ad@ultra.net (Alex Petrov)
Newsgroups: comp.mail.sendmail
Subject: support for CIDR networks
Date: Wed, 19 Aug 1998 23:54:48 GMT
Message-ID: <35db61a5.38855432@10.20.30.41>


i noticed that majority of (ruleset) code which implements access
control based on {client_addr} supports only classfull networks:

A.B.C.D - host (/32)
A.B.C   - class C (/24)
A.B     - class B (/16)
A       - class A (/8)

here is an example of this kind of code:

SLookUpAddress
R<$+> <$+> <$*>         $: < $(access $1 $: ? $) > <$1> <$2> <$3>
R<?> <$+.$-> <$+> <$*>  $@ $>LookUpAddress <$1> <$3> <$4>
R<?> <$+> <$+> <$*>     $@ <$2> <$3>
R<$*> <$+> <$+> <$*>    $@ <$1> <$4>




i have a jcode which supports arbitrary network blocks in cidr
notation A.B.C.D/N. it uses "netmasks" class which helps determine
supernet for a given host or network. (for example, supernet for host
12.34.56.78 is 12.34.56.78/31, supernet for network 12.34.56.78/31 is
12.34.56.76/30, etc see the table bellow (note that table continues
only up to /16 which is enough for practical purpuses).

host/network    supernet
==============================
12.34.56.78     12.34.56.78/31
12.34.56.78/31  12.34.56.76/30
12.34.56.76/30  12.34.56.72/29
12.34.56.72/29  12.34.56.64/28
12.34.56.64/28  12.34.56.64/27
12.34.56.64/27  12.34.56.64/26
12.34.56.64/26  12.34.56.0/25
12.34.56.0/25   12.34.56.0/24
12.34.56.0/24   12.34.56.0/23
12.34.56.0/23   12.34.56.0/22
12.34.56.0/22   12.34.56.0/21
12.34.56.0/21   12.34.48.0/20
12.34.48.0/20   12.34.32.0/19
12.34.32.0/19   12.34.0.0/18
12.34.0.0/18    12.34.0.0/17
12.34.0.0/17    12.34.0.0/16

"netmasks" class contains pairs like:

78      78/31
78/31   76/30
76/30   72/29
72/29   64/28
64/28   64/27
64/27   64/26
64/26   0/25
0/25    0/24
56.0/24 56.0/23
56.0/23 56.0/22
56.0/22 56.0/21
56.0/21 48.0/20
48.0/20 32.0/19
32.0/19 0.0/18
0.0/18  0.0/17
0.0/17  0.0/16

total size of "netmasks" file is 1276 records. netmasks.db file size
is 57344 bytes. I have a small perl script which generates netmaksks
file.

the code bellow supports access file entries like:

12.34.56.64/26          ok
12.34.56.0/22           relay
12.34.56.29/30          discard
12.34.56.128/25         reject


the algorithm is the following: for each network containing
{client_addr} starting from a /32 (host address) to maximum
of /16 check if this network has an entry in access class.

and finaly here is the code:


C{notfound}     notfound
Knetmask        hash /etc/mail/netmasks.db

Sexample
R$*             $: $(dequote "" $&{client_addr} $)
R$*.$*          $>check_all_supernets $1.$2
R$~{notfound}   $@ $1                   return if match found
# if match not found other tests may follow
...



##
Scheck_all_supernets
R$*             $: $>supernet $1
R notfound      $@ notfound
R$*             $: $1 $| $>check_access $1
R$* $| notfound $@ $1
R$* $| $*       $@ $2
R$*             $# 4.3.5. $: 435 <$1> internal error in supernet block



Scheck_access
R$*             $@$(access $1$:notfound$)


Ssupernet
R$+.$+.$+.$+/$+ $: $1.$2.$3.$(netmask $4/$5 $:$4^$5 $)
R$+.$+.$+.$+^$+ $: $1.$2.$(netmask $3.$4/$5 $:notfound $)
R$* notfound    $@ notfound
R$+.$+.$+.$+/$+ $@ $1.$2.$3.$4/$5
R$+.$+.$+.$+    $: $1.$2.$3.$(netmask $4 $:$4^ $)
R$*^            $# 4.3.5. $: 435 internal error in netmasks database
R$*             $@ $1



let me know if you found this interesting or have any questions.

-alex
ad@ultra.net






[Content]
Claus Aßmann Please send comments to: <ca@sendmail.org>