1package Ocsinventory::Agent::Backend::OS::BSD::Networks;
2
3use strict;
4
5sub check {
6    my $params = shift;
7    my $common = $params->{common};
8    $common->can_run("ifconfig") && $common->can_load("Net::IP qw(:PROC)")
9}
10
11
12sub _ipdhcp {
13    my $if = shift;
14
15    my $path;
16    my $ipdhcp;
17    my $leasepath;
18
19    foreach ( # XXX BSD paths
20      "/var/db/dhclient.leases.%s",
21      "/var/db/dhclient.leases",
22      # Linux path for some kFreeBSD based GNU system
23      "/var/lib/dhcp3/dhclient.%s.leases",
24      "/var/lib/dhcp3/dhclient.%s.leases",
25      "/var/lib/dhcp/dhclient.leases") {
26
27        $leasepath = sprintf($_,$if);
28        last if (-e $leasepath);
29    }
30    return undef unless -e $leasepath;
31
32    if (open DHCP, $leasepath) {
33        my $lease;
34        my $dhcp;
35        my $expire;
36        # find the last lease for the interface with its expire date
37        while(<DHCP>){
38            $lease = 1 if(/lease\s*{/i);
39            $lease = 0 if(/^\s*}\s*$/);
40            if ($lease) { #inside a lease section
41                if (/interface\s+"(.+?)"\s*/){
42                    $dhcp = ($1 =~ /^$if$/);
43                }
44                #Server IP
45                if (/option\s+dhcp-server-identifier\s+(\d{1,3}(?:\.\d{1,3}){3})\s*;/x) {
46                    $ipdhcp = $1;
47                }
48                if (/^\s*expire\s*\d\s*(\d*)\/(\d*)\/(\d*)\s*(\d*):(\d*):(\d*)/x) {
49                    $expire=sprintf "%04d%02d%02d%02d%02d%02d",$1,$2,$3,$4,$5,$6;
50                }
51            }
52        }
53        close DHCP or warn;
54        chomp (my $currenttime = `date +"%Y%m%d%H%M%S"`);
55        undef $ipdhcp unless $currenttime <= $expire;
56    } else {
57        warn "Can't open $leasepath\n";
58    }
59    return $ipdhcp;
60}
61
62# Initialise the distro entry
63sub run {
64    my $params = shift;
65    my $common = $params->{common};
66
67    my $description;
68    my $duplex;
69    my $ipaddress;
70    my $ipmask;
71    my $ipsubnet;
72    my $ipaddress6;
73    my $ipmask6;
74    my $ipsubnet6;
75    my $macaddr;
76    my $mtu;
77    my $speed;
78    my $status;
79    my $type;
80
81
82    my @ifconfig = `ifconfig -a`; # -a option required on *BSD
83
84    # first make the list available interfaces
85    # too bad there's no -l option on OpenBSD
86    my @list;
87    foreach (@ifconfig){
88        # skip loopback, pseudo-devices and point-to-point interfaces
89        next if /^(lo|fwe|vmnet|sit|pflog|pfsync|enc|strip|plip|sl|ppp)\d+/;
90        if (/^(\S+):/) { push @list , $1; } # new interface name
91    }
92
93    # for each interface get it's parameters
94    foreach $description (@list) {
95        $ipaddress = $ipmask = $macaddr = $status =  $type = $mtu = $speed = $ipaddress6 = $ipmask6 = $ipsubnet6 = undef;
96        # search interface infos
97        @ifconfig = `ifconfig $description`;
98        foreach (@ifconfig){
99            $ipaddress = $1 if /inet (\S+)/i;
100            if (/inet6 ([\w:]+)\S* prefixlen (\d+)/) {
101                $ipaddress6=$1;
102                $ipmask6=getIPNetmaskV6($2);
103                $ipsubnet6=getSubnetAddressIPv6($ipaddress6,$ipmask6);
104            }
105            $ipmask = $1 if /netmask\s+(\S+)/i;
106            $macaddr = $2 if /(address:|ether|lladdr)\s+(\S+)/i;
107            $status = 1 if /<UP/i;
108            $type = $1 if /media:\s+(\S+)/i;
109            $speed = $1 if /media:\s+\S+\s\S+\s\((\d+)/i;  # Ethernet autoselect (1000baseT <full-duplex>)
110            $mtu = $1 if /mtu (\d+)/i;
111        }
112
113        # In BSD, netmask is given in hex form
114        my $binmask = sprintf("%b", oct($ipmask));
115        $ipmask = ip_bintoip($binmask,4);
116
117        if ($description & $ipaddress ) {
118            $common->addNetwork({
119                DESCRIPTION => $description,
120                IPADDRESS => $ipaddress,
121                IPDHCP => _ipdhcp($description),
122                IPGATEWAY => getRoute($ipaddress),
123                IPMASK => $ipmask,
124                IPSUBNET => getSubnetAddressIPv4($ipaddress,$ipmask),
125                MACADDR => $macaddr,
126                MTU => $mtu,
127                SPEED => getSpeed($speed),
128                STATUS => $status?"Up":"Down",
129                TYPE => $type,
130            });
131            # Set default gateway in hardware info
132            $common->setHardware({
133                DEFAULTGATEWAY => getRoute($ipaddress6)
134            });
135        } else {
136            $common->addNetwork({
137                DESCRIPTION => $description,
138                IPADDRESS => $ipaddress6,
139                IPDHCP => _ipdhcp($description),
140                IPGATEWAY => getRoute($ipaddress6),
141                IPMASK => getIPNetmaskV6($ipaddress6),
142                IPSUBNET => getSubnetAddressIPv6($ipaddress6,$ipmask6),
143                MACADDR => $macaddr,
144                MTU => $mtu,
145                SPEED => getSpeed($speed),
146                STATUS => $status?"Up":"Down",
147                TYPE => $type,
148            });
149            # Set default gateway in hardware info
150            $common->setHardware({
151                DEFAULTGATEWAY => getRoute($ipaddress6)
152            });
153        }
154    }
155}
156
157sub getSpeed{
158    my ($speed)=@_;
159
160    return unless $speed;
161
162    if ($speed gt 100 ){
163        $speed = ($speed/1000)." Gbps";
164    } else {
165        $speed = $speed." Mbps";
166    }
167
168    return $speed;
169
170}
171
172sub getSubnetAddressIPv4 {
173    my ($address,$mask)=@_;
174
175    return undef unless $address && $mask;
176
177    my $binaddress=ip_iptobin($address, 4);
178    my $binmask=ip_iptobin($mask, 4);
179    my $binsubnet=$binaddress & $binmask;
180
181    return ip_bintoip($binsubnet, 4);
182}
183
184sub getSubnetAddressIPv6 {
185    my ($address,$mask)=@_;
186
187    return undef unless $address && $mask;
188
189    my $binaddress = ip_iptobin(ip_expand_address($address, 6),6);
190    my $binmask    = ip_iptobin(ip_expand_address($mask, 6),6);
191    my $binsubnet  = $binaddress & $binmask;
192
193    return ip_compress_address(ip_bintoip($binsubnet, 6),6);
194}
195
196sub getIPNetmaskV6 {
197    my ($prefix) = @_;
198
199    return undef unless $prefix;
200    return ip_compress_address(ip_bintoip(ip_get_mask($prefix, 6), 6),6);
201}
202
203sub getRoute {
204    # Looking for the gateway
205    # 'route show' doesn't work on FreeBSD so we use netstat
206    # XXX IPV4 only
207    my ($prefix) = @_;
208    my $route;
209
210    return undef unless $prefix;
211
212    if (ip_is_ipv4($prefix)) {
213        for (`netstat -rn -f inet`){
214            $route = $1 if /^default\s+(\S+)/i;
215        }
216    } elsif (ip_is_ipv6($prefix)) {
217        for (`netstat -rn -f inet6`){
218            $route = $1 if /^default\s+(\S+)/i;
219        }
220    }
221    return $route;
222}
223
2241;
225__END__
226
227=head1 NAME
228
229OCSInventory::Agent::Backend::OS::BSD::Networks - Network-related information
230
231=head1 DESCRIPTION
232
233This module retrieves network information.
234
235=head1 FUNCTIONS
236
237=head2 getSpeed
238
239Returns the speed of the card.
240
241=head2 getRoute
242
243Returns the gateway
244
245=head2 getIPNetmaskV4
246
247Returns the IP v4 network mask
248
249=head2 getIPNetmaskV6
250
251Returns the IP v6 network mask
252
253=head2 getSubnetAddressIPv4
254
255Returns the subnet of ip v4 network
256
257=head2 getSubnetAddressIPv6
258
259Returns the subnet of ip v6 network
260