Network info

getprotobynumber#

Look up a network protocol entry by its assigned protocol number.

getprotobynumber wraps the system getprotobynumber(3) call. Given a numeric protocol identifier — the same values named by constants like IPPROTO_TCP (6), IPPROTO_UDP (17), IPPROTO_ICMP (1) — it returns the matching entry from the system’s protocol database (typically /etc/protocols). The common use is turning a protocol number pulled off the wire, out of a routing table, or returned by getsockopt into a human-readable name.

Synopsis#

getprotobynumber NUMBER

What you get back#

In list context, a four-element list:

my ($name, $aliases, $proto) = getprotobynumber($number);
  • $name — canonical protocol name ("tcp", "udp", "icmp").

  • $aliases — space-separated string of alternative names for the protocol, or the empty string if none.

  • $proto — the protocol number you passed in, echoed back from the database entry.

In scalar context, you get $name alone. If the number is not in the database, the scalar return is undef and the list return is empty.

my $name = getprotobynumber(6);         # "tcp"
my @rec  = getprotobynumber(6);         # ("tcp", "", 6)
my $none = getprotobynumber(9999);      # undef

Global state it touches#

Shares the protocol-database cursor with getprotobyname, getprotoent, setprotoent, and endprotoent. Calling getprotobynumber does not disturb an iteration in progress on most systems, but portable code that interleaves single lookups with getprotoent iteration should call setprotoent afterwards to reset the cursor.

On failure, $! is set to the underlying errno, though most implementations simply return “not found” without setting errno.

Examples#

Resolve the canonical name of a protocol number:

my $name = getprotobynumber(6);
print "$name\n";                        # "tcp"

Full record with aliases:

my ($name, $aliases, $proto) = getprotobynumber(1);
print "$name ($proto): $aliases\n";     # e.g. "icmp (1): ICMP"

Reverse-lookup a protocol pulled out of a packet header:

sub protocol_label {
    my ($num) = @_;
    my $name = getprotobynumber($num);
    return defined $name ? $name : "proto-$num";
}

Round-trip against getprotobyname — useful as a sanity check that your system’s protocol database knows the name you expect:

my $num  = getprotobyname("tcp");       # 6
my $back = getprotobynumber($num);      # "tcp"

Pretty-print a getsockopt level. The level argument to getsockopt is a protocol number; getprotobynumber turns it back into a label for logging:

my ($level) = unpack("I", $packed_level);
printf "socket option at level %s\n", getprotobynumber($level) // $level;

Edge cases#

  • List-operator precedence trap. Even though getprotobynumber takes a single argument, it parses with list-operator precedence. The function name swallows everything to its right as one big list expression:

    getprotobynumber $number eq 'icmp'    # WRONG — equivalent to:
    getprotobynumber($number eq 'icmp')   # looks up protocol 0 or 1
    getprotobynumber($number) eq 'icmp'   # what you meant
    

    Always parenthesise the argument when comparing the result, or assign the lookup to a variable first.

  • Unknown number: scalar return is undef; list return is the empty list. Guard with defined:

    defined(my $name = getprotobynumber($n))
        or die "unknown protocol number $n";
    
  • Non-integer argument: converted to an integer via the usual numeric coercion before the lookup. A string like "tcp" coerces to 0 and you get whatever entry (if any) is registered for protocol 0, which is usually "ip". For name-based lookup, use getprotobyname.

  • Negative or out-of-range numbers: no entry, returns empty / undef. No warning is raised.

  • The Net::protoent object interface. If you import Net::protoent, getprotobynumber is overridden to return a blessed object with named accessors ($p->name, $p->aliases, $p->proto). Handy when you do not want to remember positional field order.

  • Database lookup, not protocol stack introspection. This function reads /etc/protocols (or the equivalent NSS source). It tells you what name the system assigns to a number; it does not tell you whether the kernel actually supports that protocol or whether a socket of that type can be opened.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • getprotobyname — the inverse: look up a protocol entry by name when you have a label like "tcp" and need the number

  • getprotoent — iterate every entry in the protocol database, when you want to list or index them all

  • setprotoent — reopen / rewind the protocol-database cursor; pair with endprotoent around an iteration

  • getservbyport — the service-table analogue, turning a port number into a service name

  • getsockopt — returns a protocol number as its level argument; feed it to getprotobynumber for readable logs

  • Socket — exports the IPPROTO_* constants whose numeric values are what you pass in