Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
pymilter
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
misc
pymilter
Commits
fa440854
Commit
fa440854
authored
14 years ago
by
Stuart Gathman
Browse files
Options
Downloads
Patches
Plain Diff
Handle IP6 in iniplist()
parent
65986632
No related branches found
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
Milter/pyip6.py
+117
-0
117 additions, 0 deletions
Milter/pyip6.py
Milter/utils.py
+52
-5
52 additions, 5 deletions
Milter/utils.py
with
169 additions
and
5 deletions
Milter/pyip6.py
0 → 100644
+
117
−
0
View file @
fa440854
"""
Pure Python IP6 parsing and formatting
Copyright (c) 2006 Stuart Gathman <stuart@bmsi.com>
This module is free software, and you may redistribute it and/or modify
it under the same terms as Python itself, so long as this copyright message
and disclaimer are retained in their original form.
"""
import
struct
#from spf import RE_IP4
import
re
PAT_IP4
=
r
'
\.
'
.
join
([
r
'
(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])
'
]
*
4
)
RE_IP4
=
re
.
compile
(
PAT_IP4
+
'
$
'
)
def
inet_ntop
(
s
):
"""
Convert ip6 address to standard hex notation.
Examples:
>>>
inet_ntop
(
struct
.
pack
(
"
!HHHHHHHH
"
,
0
,
0
,
0
,
0
,
0
,
0xFFFF
,
0x0102
,
0x0304
))
'
::FFFF:1.2.3.4
'
>>>
inet_ntop
(
struct
.
pack
(
"
!HHHHHHHH
"
,
0x1234
,
0x5678
,
0
,
0
,
0
,
0
,
0x0102
,
0x0304
))
'
1234:5678::102:304
'
>>>
inet_ntop
(
struct
.
pack
(
"
!HHHHHHHH
"
,
0
,
0
,
0
,
0x1234
,
0x5678
,
0
,
0x0102
,
0x0304
))
'
::1234:5678:0:102:304
'
>>>
inet_ntop
(
struct
.
pack
(
"
!HHHHHHHH
"
,
0x1234
,
0x5678
,
0
,
0x0102
,
0x0304
,
0
,
0
,
0
))
'
1234:5678:0:102:304::
'
>>>
inet_ntop
(
struct
.
pack
(
"
!HHHHHHHH
"
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
))
'
::
'
"""
# convert to 8 words
a
=
struct
.
unpack
(
"
!HHHHHHHH
"
,
s
)
n
=
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
# null ip6
if
a
==
n
:
return
'
::
'
# check for ip4 mapped
if
a
[:
5
]
==
(
0
,
0
,
0
,
0
,
0
)
and
a
[
5
]
in
(
0
,
0xFFFF
):
ip4
=
'
.
'
.
join
([
str
(
i
)
for
i
in
struct
.
unpack
(
"
!BBBB
"
,
s
[
12
:])])
if
a
[
5
]:
return
"
::FFFF:
"
+
ip4
return
"
::
"
+
ip4
# find index of longest sequence of 0
for
l
in
(
7
,
6
,
5
,
4
,
3
,
2
,
1
):
e
=
n
[:
l
]
for
i
in
range
(
9
-
l
):
if
a
[
i
:
i
+
l
]
==
e
:
if
i
==
0
:
return
'
:
'
+
'
:%x
'
*
(
8
-
l
)
%
a
[
l
:]
if
i
==
8
-
l
:
return
'
%x:
'
*
(
8
-
l
)
%
a
[:
-
l
]
+
'
:
'
return
'
%x:
'
*
i
%
a
[:
i
]
+
'
:%x
'
*
(
8
-
l
-
i
)
%
a
[
i
+
l
:]
return
"
%x:%x:%x:%x:%x:%x:%x:%x
"
%
a
def
inet_pton
(
p
):
"""
Convert ip6 standard hex notation to ip6 address.
Examples:
>>>
struct
.
unpack
(
'
!HHHHHHHH
'
,
inet_pton
(
'
::
'
))
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
>>>
struct
.
unpack
(
'
!HHHHHHHH
'
,
inet_pton
(
'
::1234
'
))
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
4660
)
>>>
struct
.
unpack
(
'
!HHHHHHHH
'
,
inet_pton
(
'
1234::
'
))
(
4660
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
>>>
struct
.
unpack
(
'
!HHHHHHHH
'
,
inet_pton
(
'
1234::5678
'
))
(
4660
,
0
,
0
,
0
,
0
,
0
,
0
,
22136
)
>>>
struct
.
unpack
(
'
!HHHHHHHH
'
,
inet_pton
(
'
::FFFF:1.2.3.4
'
))
(
0
,
0
,
0
,
0
,
0
,
65535
,
258
,
772
)
>>>
struct
.
unpack
(
'
!HHHHHHHH
'
,
inet_pton
(
'
1.2.3.4
'
))
(
0
,
0
,
0
,
0
,
0
,
65535
,
258
,
772
)
>>>
try
:
inet_pton
(
'
::1.2.3.4.5
'
)
...
except
ValueError
,
x
:
print
x
::
1.2
.
3.4
.
5
"""
if
p
==
'
::
'
:
return
'
\0
'
*
16
s
=
p
m
=
RE_IP4
.
search
(
s
)
try
:
if
m
:
pos
=
m
.
start
()
ip4
=
[
int
(
i
)
for
i
in
s
[
pos
:].
split
(
'
.
'
)]
if
not
pos
:
return
struct
.
pack
(
'
!QLBBBB
'
,
0
,
65535
,
*
ip4
)
s
=
s
[:
pos
]
+
'
%x%02x:%x%02x
'
%
tuple
(
ip4
)
a
=
s
.
split
(
'
::
'
)
if
len
(
a
)
==
2
:
l
,
r
=
a
if
not
l
:
r
=
r
.
split
(
'
:
'
)
return
struct
.
pack
(
'
!HHHHHHHH
'
,
*
[
0
]
*
(
8
-
len
(
r
))
+
[
int
(
s
,
16
)
for
s
in
r
])
if
not
r
:
l
=
l
.
split
(
'
:
'
)
return
struct
.
pack
(
'
!HHHHHHHH
'
,
*
[
int
(
s
,
16
)
for
s
in
l
]
+
[
0
]
*
(
8
-
len
(
l
)))
l
=
l
.
split
(
'
:
'
)
r
=
r
.
split
(
'
:
'
)
return
struct
.
pack
(
'
!HHHHHHHH
'
,
*
[
int
(
s
,
16
)
for
s
in
l
]
+
[
0
]
*
(
8
-
len
(
l
)
-
len
(
r
))
+
[
int
(
s
,
16
)
for
s
in
r
])
if
len
(
a
)
==
1
:
return
struct
.
pack
(
'
!HHHHHHHH
'
,
*
[
int
(
s
,
16
)
for
s
in
a
[
0
].
split
(
'
:
'
)])
except
ValueError
:
pass
raise
ValueError
,
p
This diff is collapsed.
Click to expand it.
Milter/utils.py
+
52
−
5
View file @
fa440854
...
...
@@ -11,17 +11,48 @@ from email.Header import decode_header
#import email.Utils
import
rfc822
ip4re
=
re
.
compile
(
r
'
^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*$
'
)
PAT_IP4
=
r
'
\.
'
.
join
([
r
'
(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])
'
]
*
4
)
ip4re
=
re
.
compile
(
PAT_IP4
+
'
$
'
)
ip6re
=
re
.
compile
(
'
(?:%(hex4)s:){6}%(ls32)s$
'
'
|::(?:%(hex4)s:){5}%(ls32)s$
'
'
|(?:%(hex4)s)?::(?:%(hex4)s:){4}%(ls32)s$
'
'
|(?:(?:%(hex4)s:){0,1}%(hex4)s)?::(?:%(hex4)s:){3}%(ls32)s$
'
'
|(?:(?:%(hex4)s:){0,2}%(hex4)s)?::(?:%(hex4)s:){2}%(ls32)s$
'
'
|(?:(?:%(hex4)s:){0,3}%(hex4)s)?::%(hex4)s:%(ls32)s$
'
'
|(?:(?:%(hex4)s:){0,4}%(hex4)s)?::%(ls32)s$
'
'
|(?:(?:%(hex4)s:){0,5}%(hex4)s)?::%(hex4)s$
'
'
|(?:(?:%(hex4)s:){0,6}%(hex4)s)?::$
'
%
{
'
ls32
'
:
r
'
(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|%s)
'
%
PAT_IP4
,
'
hex4
'
:
r
'
[0-9a-f]{1,4}
'
},
re
.
IGNORECASE
)
# from spf.py
def
addr2bin
(
str
):
"""
Convert a string IPv4 address into an unsigned integer.
"""
try
:
return
struct
.
unpack
(
"
!L
"
,
socket
.
inet_aton
(
str
))[
0
]
except
socket
.
error
:
raise
socket
.
error
(
"
Invalid IP4 address:
"
+
str
)
def
bin2long6
(
str
):
"""
Convert binary IP6 address into an unsigned Python long integer.
"""
h
,
l
=
struct
.
unpack
(
"
!QQ
"
,
str
)
return
h
<<
64
|
l
if
hasattr
(
socket
,
'
has_ipv6
'
)
and
socket
.
has_ipv6
:
def
inet_ntop
(
s
):
return
socket
.
inet_ntop
(
socket
.
AF_INET6
,
s
)
def
inet_pton
(
s
):
return
socket
.
inet_pton
(
socket
.
AF_INET6
,
s
)
else
:
from
pyip6
import
inet_ntop
,
inet_pton
MASK
=
0xFFFFFFFF
L
MASK6
=
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
L
def
cidr
(
i
,
n
):
return
~
(
MASK
>>
n
)
&
MASK
&
i
def
cidr
(
i
,
n
,
mask
=
MASK
):
return
~
(
mask
>>
n
)
&
mask
&
i
def
iniplist
(
ipaddr
,
iplist
):
"""
Return whether ip is in cidr list
...
...
@@ -31,8 +62,17 @@ def iniplist(ipaddr,iplist):
True
>>>
iniplist
(
'
192.168.0.45
'
,[
'
192.168.0.*
'
])
True
>>>
iniplist
(
'
2001:610:779:0:223:6cff:fe9a:9cf3
'
,[
'
127.0.0.1
'
,
'
172.20.1.0/24
'
,
'
2001:610:779::/48
'
])
True
>>>
iniplist
(
'
2G01:610:779:0:223:6cff:fe9a:9cf3
'
,[
'
127.0.0.1
'
,
'
172.20.1.0/24
'
,
'
2001:610:779::/48
'
])
True
"""
if
ip4re
.
match
(
ipaddr
):
ipnum
=
addr2bin
(
ipaddr
)
elif
ip6re
.
match
(
ipaddr
):
ipnum
=
bin2long6
(
inet_pton
(
ipaddr
))
else
:
raise
ValueError
(
'
Invalid ip syntax:
'
+
ipaddr
)
for
pat
in
iplist
:
p
=
pat
.
split
(
'
/
'
,
1
)
if
ip4re
.
match
(
p
[
0
]):
...
...
@@ -42,6 +82,13 @@ def iniplist(ipaddr,iplist):
n
=
32
if
cidr
(
addr2bin
(
p
[
0
]),
n
)
==
cidr
(
ipnum
,
n
):
return
True
elif
ip6re
.
match
(
p
[
0
]):
if
len
(
p
)
>
1
:
n
=
int
(
p
[
1
])
else
:
n
=
128
if
cidr
(
bin2long6
(
inet_pton
(
p
[
0
])),
n
,
MASK6
)
==
cidr
(
ipnum
,
n
,
MASK6
):
return
True
elif
fnmatchcase
(
ipaddr
,
pat
):
return
True
return
False
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment