.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Net::Interface::Developer 3pm" .TH Net::Interface::Developer 3pm "2020-11-09" "perl v5.32.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::Interface::Developer \- api, notes, hints .SH "DESCRIPTION" .IX Header "DESCRIPTION" This contains development notes and \s-1API\s0 documentation for the Net::Interface module. It is hoped that others will help fill in the missing pieces for \s-1OS\s0's and address families that are currently unsupported. .SH "ARCHITECTURE" .IX Header "ARCHITECTURE" Net::Interface gathers information about the network interfaces in an \s-1OS\s0 independent fashion by first attempting to use \f(CW\*(C`getifaddrs\*(C'\fR if \&\f(CW\*(C`getifaddrs\*(C'\fR is not supported on the \s-1OS\s0 it falls back to using system \&\f(CW\*(C`ioctl\*(Aqs\*(C'\fR and the \f(CW\*(C`ifreq, in6_ifreq, lifreq\*(C'\fR structures defined on the local host. Linux differs somewhat since ipV6 information is available only directly from the kernel on older versions where \f(CW\*(C`getifaddrs\*(C'\fR is not available. The \&\f(CW\*(C`ifreq\*(C'\fR and friends information is used to generate a \f(CW\*(C`getifaddrs\*(C'\fR response. .PP Herein lies the need for continued development by the opensource community. Many \s-1OS\s0's have peculiar \f(CW\*(C`ioctl\*(C'\fR variants and \s-1SIOC\s0's variants that require unique code solutions. I'm sure that all of them are not presently included. .PP Net::Interface is built in 5 layers, listed below from the base up. .SS "description: files code" .IX Subsection "description: files code" .SS "1) AF_xxx families: ni_af_inetcommon.c (C)" .IX Subsection "1) AF_xxx families: ni_af_inetcommon.c (C)" Code modules for \s-1AF\s0 families. Currently supported are \s-1AF_INET, AF_INET6.\s0 There is partial support for \s-1AF_LINK\s0 and \s-1AF_PACKET\s0 for retrieval of \s-1MAC\s0 address from the interface where it is needed. Where the code is reasonably universal for a particular address family and the methods used to retrieve the information from the \s-1OS,\s0 it resides in an af_xxxx.c file. .SS "2) \s-1IFREQ\s0 families: ni_xx_ifreq.c (C)" .IX Subsection "2) IFREQ families: ni_xx_ifreq.c (C)" Code modules for \s-1IFREQ\s0 families. Currently supported are: .IP "\(bu" 2 \&\f(CW\*(C`ifreq\*(C'\fR ni_ifreq.c .Sp Provides support for retrieval of ipV4 information. The structure \f(CW\*(C`ifreq\*(C'\fR does not provide enough space to return data about socket address families larger than \f(CW\*(C`struct sockaddr\*(C'\fR. All known operating systems support this flavor of data retrieval. ni_ifreq.c makes use of calls to ni_af_inet.c .IP "\(bu" 2 \&\f(CW\*(C`in6_ifreq\*(C'\fR ni_in6_ifreq.c .Sp Provides support for retrieval of both ipV4 and ipV6 information. \&\f(CW\*(C`in6_ifreq\*(C'\fR uses \f(CW\*(C`struct sockaddr_storage\*(C'\fR rather than the smaller \&\f(CW\*(C`struct sockaddr\*(C'\fR that is used in \f(CW\*(C`ifreq\*(C'\fR. This code modules support variants of the \s-1BSD\s0 operating system and a few others. ni_in6_ifreq makes use of calls to ni_af_inetcommon.c .IP "\(bu" 2 \&\f(CW\*(C`lifreq\*(C'\fR ni_lifreq.c .Sp Provides support for retrieval of both ipV4 and ipV6 information. \f(CW\*(C`lifreq\*(C'\fR has a custom format unique to the \s-1SUN\s0 operating systems. Pretty much everything in it, while similar to the two previous code modules, is custom. .IP "\(bu" 2 \&\f(CW\*(C`linuxproc\*(C'\fR ni_linuxproc.c .Sp Provides support for retrieval of both ipV4 and ipV6 information. \&\f(CW\*(C`linuxproc\*(C'\fR uses calls to ni_af_inet.c to get ipV4 information int \&\f(CW\*(C`getifaddrs\*(C'\fR format and custom code to collect similarly formatted ipV6 information directly from the /proc file system. It then performs a merge on these two data sets to put them into proper order and add \fBfake\fR \s-1AF_LINK\s0 or \s-1AF_PACKET\s0 records to provide \f(CW\*(C`getifaddrs\*(C'\fR compatiable access to the \s-1MAC\s0 address through the returned \f(CW\*(C`struct ifaddrs\*(C'\fR array. .ie n .SS "3) ""getifaddrs"" ni_getifaddrs.c (C)" .el .SS "3) \f(CWgetifaddrs\fP ni_getifaddrs.c (C)" .IX Subsection "3) getifaddrs ni_getifaddrs.c (C)" The \f(CW\*(C`getifaddrs\*(C'\fR code module contains the decision mechanism for how data is retrieved for a particular build of Net::Interface. At build time, portions of the code are #ifdef'd in/out depending on the availabiltiy of resource from the underlying \s-1OS.\s0 In addition, at run time, if the system does not have native \f(CW\*(C`getifaddrs\*(C'\fR then a decision tree is used depending on the response to calls for data to the various code modules described in section 2). .SS "4) Sub-system Interface.xs (\s-1PERLXS\s0)" .IX Subsection "4) Sub-system Interface.xs (PERLXS)" This file asks for the data about the interfaces with a generic call to \&\f(CW\*(C`getifaddrs\*(C'\fR. The data returned resides in memory allocated by the \s-1OS\s0 and must be freed or a memory leak will result as it is not tracked by Perl's garbage collector. \f(CW\*(C`Interface.xs\*(C'\fR moves the interface data from allocated memory to Perl managed memory where it can be reclaimed by the garbage collection mechanism if/when the user space program turns it loose. This eliminates the need for a \f(CW\*(C`close\*(C'\fR operation to free the \s-1OS\s0's allocated memory. .SS "5) User space Interface.pm (Perl)" .IX Subsection "5) User space Interface.pm (Perl)" .SH "DATA FLOW BLOCK DIAGRAM" .IX Header "DATA FLOW BLOCK DIAGRAM" The pure perl portion of this module performs most of the presentation operations for the user that are published in the \s-1API\s0 for Net::Interface. .PP .Vb 10 \& *\e \e \e | / / /* \& * user space * \& ************************* \& ^ Net::Interface \& | Architecture Block Diagram \& v \& ************************* \& * Interface.pm * \& ************************* \& | \& ************************* \& * Interface.xs * \& ************************* \& | \& ************************* ************************* \& * system getifaddrs * * ni_getifreqs * \& * via *<\-if missing \->* via * \& * (ni_getifaddrer.c) * * (ni_ifreq.c) * \& ************************* * (ni_lifreq.c) * \& * (ni_in6_ifreq.c) * \& * (ni_linuxproc.c) * \& ************************* \& | \& ************************* \& * (ni_af_inetcommon.c) * \& ************************* .Ve .SH "DEVELOPER API" .IX Header "DEVELOPER API" Access to the pieces of code in the block diagram above are available through a developer \s-1API.\s0 These codes snippets from Interfaces.xs describe the access. .PP .Vb 11 \& void \& _\|_developer(ref) \& SV *ref \& ALIAS: \& d_ni_ifreq = NI_IFREQ \& d_ni_lifreq = NI_LIFREQ \& d_ni_in6_ifreq = NI_IN6_IFREQ \& d_ni_linuxproc = NI_LINUXPROC \& PREINIT: \& char * process; \& int er = ni_developer(ix); .Ve .PP \&\fBand.....\fR .PP .Vb 10 \& void \& gifaddrs_base(ref) \& SV * ref \& ALIAS: \& # base = 0 \& gifa_ifreq = NI_IFREQ \& gifa_lifreq = NI_LIFREQ \& gifa_in6_ifreq = NI_IN6_IFREQ \& gifa_linuxproc = NI_LINUXPROC \& PREINIT: \& struct ifaddrs * ifap; \& int rv; \& CODE: \& if ((rv = ni_getifaddrs(&ifap,ix)) == \-1) { \& printf("failed PUNT!\en"); \& XSRETURN_EMPTY; .Ve .PP Both function sets result in a printed description to the terminal window to facilitate code creation and debug. Currently the \fBref\fR is unused. It is expected that future development will modify or add to function access. .PP .Vb 4 \& # test.pl for developer \& # \& use strict; \& use Net::Interface; \& \& # to call OS native getifaddrs if present \& print "\enifreq\en"; gifaddrs_base Net::Interface(); \& \& # to call ni_linuxproc fallback getifaddrs \& print "\enlxp\en"; gifa_linuxproc Net::Interface(); \& \& # to call ni_linuxproc ifreq emulation \& print "\englxp\en"; d_ni_linuxproc Net::Interface(); .Ve .PP See: test.pl.developer .SH "DEVELOPER API DESCRIPTION" .IX Header "DEVELOPER API DESCRIPTION" If you have gotten this far, it is time to read some of the code. AF_familes and IFREQ_families are accessed through constructor structs found at the bottom of each of the ni_af_xxx and ni_xx_ifreq source files. Their vectoring components are described in \f(CW\*(C`ni_func.h\*(C'\fR near the bottom and in \f(CW\*(C`ni_util.c\*(C'\fR in the section labeled \fBconstructor registration\fR the essence of which is described here. .PP .Vb 2 \& struct ni_ifconf_flavor * ni_ifcf_get(enum ni_FLAVOR type) \& struct ni_ifconf_flavor * ni_safe_ifcf_get(enum ni_FLAVOR type); \& \& nifp = ni_ifcf_get(NI_IFREQ); .Ve .PP Returns a pointer \f(CW\*(C`nifp\*(C'\fR to the structure for a particular flavor of \&\fBifreq\fR. If a flavor is unsupported on a particular architecture a \s-1NULL\s0 is returned by the first invocation and \s-1NI_IFREQ\s0 by the second. Currently supported flavors are: .PP .Vb 7 \& enum ni_FLAVOR { \& NI_NULL, reserved for the getifaddrs base system call \& NI_IFREQ, \& NI_LIFREQ, \& NI_IN6_IFREQ, \& NI_LINUXPROC \& }; \& \& struct ni_ifconf_flavor { \& enum ni_FLAVOR ni_type; \& int (*gifaddrs) \& int siocgifindex; \& int siocsifaddr; \& int siocgifaddr; \& int siocdifaddr; \& int siocaifaddr; \& int siocsifdstaddr; \& int siocgifdstaddr; \& int siocsifflags; \& int siocgifflags; \& int siocsifmtu; \& int siocgifmtu; \& int siocsifbrdaddr; \& int siocgifbrdaddr; \& int siocsifnetmask; \& int siocgifnetmask; \& int siocsifmetric; \& int siocgifmetric; \& int ifr_offset; \& void (*fifaddrs) howto free ifaddrs \& int (*refreshifr) howto refresh ifreq \& void * (*getifreqs) howto get ifreq \& int (*developer) developer access \& struct ni_ifconf_flavor * ni_ifcf_next; \& }; .Ve .SH "MACROS" .IX Header "MACROS" .IP "\s-1NI_PRINT_MAC\s0(u_char * hex_mac_string);" 4 .IX Item "NI_PRINT_MAC(u_char * hex_mac_string);" .Vb 1 \& printf statement for terminal output of the form \& \& XX:XX:XX:XX:XX:XX:XX:XX .Ve .IP "\s-1NI_MAC_NOT_ZERO\s0(u_char * hex_mac_string)" 4 .IX Item "NI_MAC_NOT_ZERO(u_char * hex_mac_string)" .Vb 2 \& if( NI_MAC_NOT_ZERO(macp)) \& do something .Ve .IP "\s-1NI_PRINT_IPV6\s0(struct sin6_addr);" 4 .IX Item "NI_PRINT_IPV6(struct sin6_addr);" .Vb 1 \& Takes an argument of the form sockaddr_in6.sin6_addr and prints \& \& XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX .Ve .SH "FUNCTIONS" .IX Header "FUNCTIONS" .IP "int ni_clos_reopn_dgrm(int fd, int af)" 4 .IX Item "int ni_clos_reopn_dgrm(int fd, int af)" Closes and then opens an \f(CW\*(C`ioctl\*(C'\fR socket of type \s-1SOCK_DGRAM\s0 and returns the socket value. If the socket value is \s-1NEGATIVE,\s0 no close is attempted an the call is equivalent to: .Sp .Vb 1 \& socket(af,SOCK_DGRAM,0) .Ve .IP "void ni_gifa_free(struct ifaddrs * ifap, int flavor)" 4 .IX Item "void ni_gifa_free(struct ifaddrs * ifap, int flavor)" Use the appropriate free memory function call depending on the flavor of the getifaddrs function that returned the ifaddrs structure list. .IP "int nifreq_gifaddrs(struct ifaddrs **ifap, struct ni_ifconf_flavor *nifp)" 4 .IX Item "int nifreq_gifaddrs(struct ifaddrs **ifap, struct ni_ifconf_flavor *nifp)" Our semi-standard version of \f(CW\*(C`getifaddrs\*(C'\fR used by \s-1OS\s0's that provide \f(CW\*(C`ifreq\*(C'\fR and \f(CW\*(C`in6_ifreq\*(C'\fR. .Sp \&\s-1NOTE:\s0 all calls to \f(CW\*(C`getifaddrs\*(C'\fR return \-1 on failure and and the \s-1FLAVOR\s0 as enumerated above on success. .Sp .Vb 1 \& i.e. NI_NULL for the native getifaddrs, NI_IFREQ, NI_LINUXPROC, etc... .Ve .IP "uint32_t ni_ipv6addr_gettype(struct in6_addr * in6p)" 4 .IX Item "uint32_t ni_ipv6addr_gettype(struct in6_addr * in6p)" Extracts information about the type of ipV6 address. The returned value may be passed to the \s-1NEXT\s0 function call to print. .IP "int ni_lx_map2scope(int lscope)" 4 .IX Item "int ni_lx_map2scope(int lscope)" This function maps \fILinux\fR style scope bits to their \s-1RFC\-2373\s0 equivalent. .Sp .Vb 10 \& scope flags rfc\-2373 \& 0 reserved \& 1 node\-local (aka loopback, interface\-local) \& 2 link\-local \& 3 unassigned \& 4 unassigned \& 5 site\-local \& 6 unassigned \& 7 unassigned \& 8 organization\-local \& 9 unassigned \& A unassigned \& B unassigned \& C unassigned \& D unassigned \& E global scope \& F reserved \& \& Linux rfc\-2372 \& 0x0000 0xe GLOBAL \& 0x0010u 0x1 NODELOCAL, LOOPBACK, INTERFACELOCAL \& 0x0020u 0x2 LINKLOCAL \& 0x0040u 0x5 SITELOCAL .Ve .IP "void ni_linux_scope2txt(uint32_t type)" 4 .IX Item "void ni_linux_scope2txt(uint32_t type)" Print information about an ipV6 address for each bit present in \f(CW\*(C`type\*(C'\fR. .Sp .Vb 10 \& const ni_iff_t ni_lx_type2txt[] = { \& { IPV6_ADDR_ANY, "unknown" }, \& { IPV6_ADDR_UNICAST, "unicast" }, \& { IPV6_ADDR_MULTICAST, "multicast" }, \& { IPV6_ADDR_ANYCAST, "anycast" }, \& { IPV6_ADDR_LOOPBACK, "loopback" }, \& { IPV6_ADDR_LINKLOCAL, "link\-local" }, \& { IPV6_ADDR_SITELOCAL, "site\-local" }, \& { IPV6_ADDR_COMPATv4, "compat\-v4" }, \& { IPV6_ADDR_SCOPE_MASK, "scope\-mask" }, \& { IPV6_ADDR_MAPPED, "mapped" }, \& { IPV6_ADDR_RESERVED, "reserved" }, \& { IPV6_ADDR_ULUA, "uniq\-lcl\-unicast" }, \& { IPV6_ADDR_6TO4, "6to4" }, \& { IPV6_ADDR_6BONE, "6bone" }, \& { IPV6_ADDR_AGU, "global\-unicast" }, \& { IPV6_ADDR_UNSPECIFIED, "unspecified" }, \& { IPV6_ADDR_SOLICITED_NODE, "solicited\-node" }, \& { IPV6_ADDR_ISATAP, "ISATAP" }, \& { IPV6_ADDR_PRODUCTIVE, "productive" }, \& { IPV6_ADDR_6TO4_MICROSOFT, "6to4\-ms" }, \& { IPV6_ADDR_TEREDO, "teredo" }, \& { IPV6_ADDR_ORCHID, "orchid" }, \& { IPV6_ADDR_NON_ROUTE_DOC, "non\-routeable\-doc" } \& }; .Ve .IP "int \fBni_sizeof_type2txt()\fR" 4 .IX Item "int ni_sizeof_type2txt()" Returns the size of the above table. .IP "u_int ni_get_scopeid(struct sockaddr_in6 * sin6)" 4 .IX Item "u_int ni_get_scopeid(struct sockaddr_in6 * sin6)" On systems using \s-1KAME,\s0 this function extracts and returns the scope from field 2 of the ipV6 address and sets fields 2,3 to zero. On all other systems it returns .Sp .Vb 1 \& sin6\->sin6_scopeid \& \& scope flags rfc\-2373 \& \& 0 reserved \& 1 node\-local \& 2 link\-local \& 3 unassigned \& 4 unassigned \& 5 site\-local \& 6 unassigned \& 7 unassigned \& 8 organization\-local \& 9 unassigned \& A unassigned \& B unassigned \& C unassigned \& D unassigned \& E global scope \& F reserved .Ve .IP "void * ni_memdup(void *memp, int size)" 4 .IX Item "void * ni_memdup(void *memp, int size)" Allocate memory of for \fBsize\fR and copy contents from \fBmemp\fR. Returns \s-1NULL\s0 on error and sets \fBerrno\fR to \s-1ENOMEM.\s0 .IP "void ni_plen2mask(void * in_addr, int plen, int sizeofaddr)" 4 .IX Item "void ni_plen2mask(void * in_addr, int plen, int sizeofaddr)" Create a \s-1NETMASK\s0 string from a prefix length .Sp For ipV4: ni_plen2mask(&in_addr, cidr, sizeof(struct in_addr)); .Sp For ipV6: ni_plen2mask(&in6_addr, cidr, sizeof(struct in6_addr)); .IP "int ni_prefix(void * ap, int len, int size)" 4 .IX Item "int ni_prefix(void * ap, int len, int size)" Calculated the prefix length for a \s-1NETMASK\s0 where *ap points to the binary representation of the \s-1NETMASK\s0 and size is the number of bytes in the mask. .Sp For ipV4: ni_prefix(&in_addr,sizeof(struct in_addr)); .Sp For ipV6: ni_prefix(&in6_addr,sizeof(struct(in6_addr)); .IP "int ni_refresh_ifreq(int fd, struct ifconf *ifc, void **oifr, void **olifr, struct ni_ifconf_flavor * nifp)" 4 .IX Item "int ni_refresh_ifreq(int fd, struct ifconf *ifc, void **oifr, void **olifr, struct ni_ifconf_flavor * nifp)" Some \s-1OS\s0 lose scope on the particular device/addr handle when certain ioctl's are performed. This function refreshs the ifconf chain and positions the pointers in the exact same spot with fresh scope. .Sp See ni_in6_ifreq.c and ni_af_net6.c for usage. Search for the string \fBrefreshifr\fR. Code snippit looks like: .Sp .Vb 1 \& nifp\->refreshir .Ve .SH "COPYRIGHT" .IX Header "COPYRIGHT" .Vb 1 \& Copyright 2008\-2009 \- Michael Robinton .Ve .PP This program is free software; you can redistribute it and/or modify it under the terms of the \s-1GNU\s0 General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. .PP This program is distributed in the hope that it will be useful, but \&\s-1WITHOUT ANY WARRANTY\s0; without even the implied warranty of \&\s-1MERCHANTABILITY\s0 or \s-1FITNESS FOR A PARTICULAR PURPOSE.\s0 See the \s-1GNU\s0 General Public License in the file named \*(L"Copying\*(R" for more details. .PP You should also have received a copy of the \s-1GNU\s0 General Public License along with this program in the file named \*(L"Copying\*(R". If not, write to the .PP .Vb 3 \& Free Software Foundation, Inc. \& 59 Temple Place, Suite 330 \& Boston, MA 02111\-1307, USA .Ve .PP or visit their web page on the internet at: .PP .Vb 1 \& http://www.gnu.org/copyleft/gpl.html. .Ve