Simplify subnet math with Perl's Net::Patricia
Image generated by CoPilot 2024

Simplify subnet math with Perl's Net::Patricia

There's more than one way to do it

The very mantra that defines Perl (TMTOWTDI) also causes some hesitancy in its adoption, in my observation. "Choose your own adventure" was once a leading franchise in the Scholastic book sales back when I was a kid, but I don't know about kids these days ... Before I get to the point of yelling at everyone to "get off my lawn" let me turn the corner from philosophy to tutorial. (But first, one last parting shot from Perl's founder, Larry Wall: Three Virtues.)

If you haven't already learned of MetaCpan and App::cpanminus, then take a minute and catch up on those topics. And while you're popping open new tabs on your browser, add this one too: Net::Patricia. (My introduction to Net::Patricia came from reading something written by jtk.)

If you're familiar with the basics of IP routing, then handing you the link to Net::Patricia (I'll just call it NP henceforth) is like giving a light saber to a Jedi master. The logic behind NP is the same as is used by an IP router: choose the longest matching prefix, and go!

The logic behind Net::Patricia is the same as is used by an IP router.

I explain further below via a couple of code snippets, below.

TL;DR:

  • create the NP object, then upload your subnet info with add_string
  • NP->??????_????????????( [IP or CIDR], [optional: tag info] )
  • when you're ready to search against what you've added, query match_string
  • NP->??????????_???????????? ( [IP or CIDR] ) - returns the tag info, or binary true

By example:

Let's say I have a service running somewhere in my shop that will tell me the names and cidrs of all the subnets in our core routers' FIBs. (I do have that service, but that's another write-up that I haven't written up yet.)

Step 1: load up your NP object with all the rows of named subnets

use Net::Patricia;
use LWP::UserAgent;
use Text::CSV;

my $ua = new LWP::UserAgent(
    ssl_opts => { verify_hostname => 0 },
    cookie_jar => {},
  );

my $resp = $ua->get(q{https://ipmanager.internal/subnets.php});

my $csv = new Text::CSV;
my $str = $resp->content;
my $pt = new Net::Patricia;
{
  # DATA FORMAT: CSV
  # "SubnetName","CIDR"
  open(my $fh,"<",\$str);
  while(my $row = $csv->getline($fh)) {
    # some knucklehead put commas in our subnet names
    $row->[0] =~ s/,//g;
    $pt->add_string($row->[1],$row->[0]);
  }
}        

Step 2: Query your subnets

Now, any time you want to know what subnet a particular IP address comes from, you ask your $pt variable if it can match_string($ip). I throw it into a subroutine for convenience, er - efficiency. Laziness! Now that's a virtue ??.

# Given an IP address, return the subnet name
sub ip2subnetName {
  my ($ip) = @_;
  return "Unknown" unless $ip && ($ip =~ /\d+\.\d+\.\d+\.\d+/);
  my $res = $pt->match($ip);
# Catch all for unnamed or unknown subnet
  $res ||= "Core Router FIB entry";
  return $res;
}        

I recently learned that Socket::inet_aton's return value is a nifty trick for validating an IP address format. If the return value is false or undef then your input isn't a correctly formatted IP address:

use Socket q/inet_aton/;

sub is_valid_ip {
  return inet_aton($_[0]);
}        

Step 3: integrate this technique into existing code

So let's say you've already come up with a log parser that can find all the DHCPACK messages to tell you what MAC landed on which IP ... now plug in this NP trick, and you can group together DHCP utilization by named subnet!

The code snippets above come from my DHCP log parser that feeds my monthly Power BI report. I also use NP to enforce the whitelist on my RTBH project.

And so concludes my brief introduction. Comment with your questions. Be sure to scroll back to the links up top for more details and other features available in the Net::Patricia module.

Torsten Raudssus

In IT, there are no problems—only IT solutions. Or you can just throw AI at it.

5 个月

There is always more Perl to do! :D Ride your Moose into battle!

  • 该图片无替代文字

要查看或添加评论,请登录

Jeffrey Wilson的更多文章

  • Crafting a Career, Ch 37

    Crafting a Career, Ch 37

    I missed posting my weekly article last week. Did you miss hearing from me? Let's all play nice and just go with, "Yes"…

  • Crafting a Career, Ch 36

    Crafting a Career, Ch 36

    Reduction in force. RIF.

  • Crafting a Career, Ch 35

    Crafting a Career, Ch 35

    Last week I attended online training from Palo Alto Networks. Among the 7 students attending that class were my…

  • F5 - utilize 3rd party for backups

    F5 - utilize 3rd party for backups

    [Review other tutorials from my table of contents.] Vendor Support for Backups Congratulations on your successful…

  • Palo Alto operations - uploading UserID data

    Palo Alto operations - uploading UserID data

    [Review other tutorials from my table of contents.] If you're familiar with Palo Alto Networks, then you can understand…

  • Crafting a Career, Ch 34

    Crafting a Career, Ch 34

    I've spent this week in all-day online training, diving deep into Palo Alto firewall operations. I've had enough…

  • Palo Alto firewall operations - audit unused rules

    Palo Alto firewall operations - audit unused rules

    [Review other tutorials from my table of contents.] I've touched on Palo Alto's XML API before.

  • Crafting a Career, Ch 33

    Crafting a Career, Ch 33

    [Select a different chapter from ToC] I love how Brené Brown encourages her audience to ..

  • Crafting a Career, Ch 32

    Crafting a Career, Ch 32

    [Cover Photo credit 2025 by Rebecca Wilson] [Review the Table of Contents to pick a different chapter.] PTSD and…

  • DHCP - bootstrap and service discovery

    DHCP - bootstrap and service discovery

    [Review other tutorials from my table of contents.] Introduction The dynamic host configuration protocol fills a…

社区洞察

其他会员也浏览了