Subject: | [PATCH] IPv6 support |
Greetings!
We've been using Net::Patricia patched locally with IPv6 support for
almost three years now, and I realized that we've never submitted the
patch upstream. It's actually pretty simple - I don't know if I'd call
it pretty, and I'm not sure I can say it's "correct", but it does work
for all uses we've tried it on in production.
Attached is the patch, against the 1.15_01 development version from
CPAN. A couple of quick notes:
* We didn't patch the docs, sorry. Net::Patricia->new(AF_INET6) will
give you a v6 trie, no args or AF_INET will give you a v4 trie.
* The only quick simple test we came up with was this, not included in
the patch:
$t = new Net::Patricia (AF_INET6);
$t->add_string('2001:220::/35', 'hello world');
my $match = $t->match_string('2001:220::/128');
print $match, "\n";
* libpatricia/patricia.c needed a sizeof(prefix_t) instead of
sizeof(prefix6_t) in one location because prefix6_t isn't actually
defined anywhere in the headers.
* We just statically defined HAVE_IPV6, not sure if that would be better
done through MakeMaker or something else.
* A dependency is introduced for Socket6 - I thought this was in core,
but a quick search seems to indicate it may not be. :|
* The _ip_bits function was translated to an object method so it could
return appropriately depending on whether or not the object was v4 or v6.
Sorry that list is so long, hopefully we haven't created more work than
we've saved. :| If you have specific requests for changes, ways to make
the patch better/more acceptable, etc, please let me know and I'll see
what I can do - making extra work for you as the package maintainer is
definitely not my goal!
Thanks,
Tim Wilde
Subject: | Net-Patricia-ipv6.patch |
diff -u --recursive Net-Patricia-1.15_01/libpatricia/patricia.c Net-Patricia-1.15_01-mod/libpatricia/patricia.c
--- Net-Patricia-1.15_01/libpatricia/patricia.c 2009-04-19 04:28:15.000000000 +0000
+++ Net-Patricia-1.15_01-mod/libpatricia/patricia.c 2009-11-12 17:12:00.000000000 +0000
@@ -226,7 +226,7 @@
if (family == AF_INET6) {
default_bitlen = 128;
if (prefix == NULL) {
- prefix = calloc(1, sizeof (prefix6_t));
+ prefix = calloc(1, sizeof (prefix_t));
dynamic_allocated++;
}
memcpy (&prefix->add.sin6, dest, 16);
diff -u --recursive Net-Patricia-1.15_01/libpatricia/patricia.h Net-Patricia-1.15_01-mod/libpatricia/patricia.h
--- Net-Patricia-1.15_01/libpatricia/patricia.h 2009-04-19 04:28:15.000000000 +0000
+++ Net-Patricia-1.15_01-mod/libpatricia/patricia.h 2009-11-12 16:47:17.000000000 +0000
@@ -15,6 +15,8 @@
#ifndef _PATRICIA_H
#define _PATRICIA_H
+#define HAVE_IPV6
+
/* typedef unsigned int u_int; */
typedef void (*void_fn_t)();
/* { from defs.h */
diff -u --recursive Net-Patricia-1.15_01/Patricia.pm Net-Patricia-1.15_01-mod/Patricia.pm
--- Net-Patricia-1.15_01/Patricia.pm 2009-07-31 17:45:55.000000000 +0000
+++ Net-Patricia-1.15_01-mod/Patricia.pm 2009-11-12 17:04:26.000000000 +0000
@@ -26,6 +26,7 @@
use Carp;
use vars qw($VERSION @ISA);
use Socket qw(AF_INET inet_aton inet_ntoa);
+use Socket6 qw(AF_INET6 inet_pton inet_ntop);
require DynaLoader;
require 5.6.0;
@@ -37,12 +38,17 @@
sub new {
my ($class, $type) = @_;
+
$type ||= AF_INET;
if ($type == AF_INET) {
return bless _new(32), 'Net::Patricia::AF_INET';
}
+ if ($type == AF_INET6) {
+ return bless _new(128), 'Net::Patricia::AF_INET6';
+ }
+
undef;
}
@@ -51,25 +57,31 @@
##
sub _ip_bits {
- my $str = shift;
- my $bits = ($str =~ s,/(\d+)$,,) ? $1 : 32;
+ my ($self, $str) = @_;
+ my $bits;
+
+ if (ref ($self) eq 'Net::Patricia::AF_INET6') {
+ $bits = ($str =~ s,/(\d+)$,,) ? $1 : 128;
+ } else {
+ $bits = ($str =~ s,/(\d+)$,,) ? $1 : 32;
+ }
($str,$bits);
}
sub add_string {
my ($self,$str,$data) = @_;
$data = $str unless @_ > 2;
- $self->add(_ip_bits($str),$data);
+ $self->add($self->_ip_bits($str),$data);
}
sub match_string {
my ($self,$str) = @_;
- $self->match(_ip_bits($str))
+ $self->match($self->_ip_bits($str))
}
sub match_exact_string {
my ($self,$str) = @_;
- $self->exact(_ip_bits($str))
+ $self->exact($self->_ip_bits($str))
}
sub match_exact_integer {
@@ -78,7 +90,7 @@
sub remove_string {
my ($self,$str) = @_;
- $self->remove(_ip_bits($str))
+ $self->remove($self->_ip_bits($str))
}
##
@@ -135,6 +147,60 @@
_remove($self,AF_INET,pack("N",$num),(defined $bits ? $bits : 32));
}
+##
+## AF_INET6
+##
+
+@Net::Patricia::AF_INET6::ISA = qw(Net::Patricia);
+
+sub Net::Patricia::AF_INET6::add {
+ my ($self, $ip, $bits, $data) = @_;
+ $data ||= $bits ? "$ip/$bits" : $ip;
+ my $packed = inet_pton(AF_INET6, $ip) || croak("invalid key");
+ _add($self,AF_INET6,$packed,(defined $bits ? $bits : 128), $data);
+}
+
+sub Net::Patricia::AF_INET6::add_integer {
+ my ($self, $num, $bits, $data) = @_;
+ my $packed = pack("N", $num);
+ my $ip = inet_ntop(AF_INET6, $packed) || croak("invalid address");
+ $data ||= defined $bits ? "$ip/$bits" : $ip;
+ _add($self,AF_INET6,$packed,(defined $bits ? $bits : 128), $data);
+}
+
+sub Net::Patricia::AF_INET6::match_integer {
+ my ($self, $num, $bits) = @_;
+ _match($self,AF_INET6,pack("N",$num),(defined $bits ? $bits : 128));
+}
+
+sub Net::Patricia::AF_INET6::exact_integer {
+ my ($self, $num, $bits) = @_;
+ _exact($self,AF_INET6,pack("N",$num),(defined $bits ? $bits : 128));
+}
+
+sub Net::Patricia::AF_INET6::match {
+ my ($self, $ip, $bits) = @_;
+ my $packed = inet_pton(AF_INET6, $ip) || croak("invalid key");
+ _match($self,AF_INET6,$packed,(defined $bits ? $bits : 128));
+}
+
+sub Net::Patricia::AF_INET6::exact {
+ my ($self, $ip, $bits) = @_;
+ my $packed = inet_pton(AF_INET6, $ip) || croak("invalid key");
+ _exact($self,AF_INET6,$packed,(defined $bits ? $bits : 128));
+}
+
+sub Net::Patricia::AF_INET6::remove {
+ my ($self, $ip, $bits) = @_;
+ my $packed = inet_pton(AF_INET6, $ip) || return undef;
+ _remove($self,AF_INET6,$packed,(defined $bits ? $bits : 128));
+}
+
+sub Net::Patricia::AF_INET6::remove_integer {
+ my ($self, $num, $bits) = @_;
+ _remove($self,AF_INET6,pack("N",$num),(defined $bits ? $bits : 128));
+}
+
1;
__END__
# Below is the stub of documentation for your module. You better edit it!