1 /***************************************************************************
2  *                                                                         *
3  *   This program is free software; you can redistribute it and/or modify  *
4  *   it under the terms of the GNU General Public License as published by  *
5  *   the Free Software Foundation; either version 2 of the License, or     *
6  *   (at your option) any later version.                                   *
7  *                                                                         *
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * Free/Net/OpenBSD specific network code taken out of gkrellm:            *
12  * Copyright by Bill Wilson <bill@gkrellm.net>                             *
13  * FreeBSD code by Hajimu Umemoto <ume@mahoroba.org>                       *
14  * NetBSD code by Anthony Mallet <anthony.mallet@useless-ficus.net>        *
15  * Hajimu Umemoto merged Free/Net/OpenBSD code                             *
16  * adapted for nload by Roland Riegel <feedback@roland-riegel.de>          *
17  ***************************************************************************/
18 
19 #include "devreader-bsd.h"
20 
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <net/if.h>
30 #include <unistd.h>
31 #include <sys/param.h>
32 #include <sys/sysctl.h>
33 #include <net/if_dl.h>
34 #include <net/route.h>
35 
36 #include <string>
37 #include <list>
38 
39 using namespace std;
40 
DevReaderBsd(const string & deviceName)41 DevReaderBsd::DevReaderBsd(const string& deviceName)
42     : DevReader(deviceName)
43 {
44 }
45 
~DevReaderBsd()46 DevReaderBsd::~DevReaderBsd()
47 {
48 }
49 
findAllDevices()50 list<string> DevReaderBsd::findAllDevices()
51 {
52     list<string> interfaceNames;
53 
54     struct if_msghdr *ifm, *nextifm;
55     struct sockaddr_dl *sdl;
56     char *lim, *next;
57     size_t needed;
58     int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
59     char *buf = 0;
60 
61     if(sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
62         return interfaceNames;
63 
64     buf = (char *) malloc(needed);
65     if(buf == NULL)
66         return interfaceNames;
67 
68     if(sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
69         return interfaceNames;
70 
71     lim = buf + needed;
72 
73     next = buf;
74     while(next < lim)
75     {
76         ifm = (struct if_msghdr *) next;
77         if(ifm->ifm_type != RTM_IFINFO)
78             break;
79 
80         next += ifm->ifm_msglen;
81 
82         while(next < lim)
83         {
84             nextifm = (struct if_msghdr *) next;
85             if(nextifm->ifm_type != RTM_NEWADDR)
86                 break;
87             next += nextifm->ifm_msglen;
88         }
89 
90         sdl = (struct sockaddr_dl *) (ifm + 1);
91         if(sdl->sdl_family != AF_LINK)
92             continue;
93 
94         interfaceNames.push_back(string(sdl->sdl_data, sdl->sdl_nlen));
95     }
96 
97     free(buf);
98 
99     return interfaceNames;
100 }
101 
readFromDevice(DataFrame & dataFrame)102 void DevReaderBsd::readFromDevice(DataFrame& dataFrame)
103 {
104     struct if_msghdr *ifm, *nextifm;
105     struct sockaddr_dl *sdl;
106     char *lim, *next;
107     size_t needed;
108     int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
109     char *buf = 0;
110 
111     if(m_deviceName.empty())
112         return;
113 
114     do
115     {
116         if(sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
117             break;
118 
119         buf = (char *) malloc(needed);
120         if(buf == NULL)
121             break;
122 
123         if(sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
124             break;
125 
126         lim = buf + needed;
127 
128         next = buf;
129         while(next < lim)
130         {
131             ifm = (struct if_msghdr *) next;
132             if(ifm->ifm_type != RTM_IFINFO)
133                 break;
134 
135             next += ifm->ifm_msglen;
136 
137             while(next < lim)
138             {
139                 nextifm = (struct if_msghdr *) next;
140                 if(nextifm->ifm_type != RTM_NEWADDR)
141                     break;
142                 next += nextifm->ifm_msglen;
143             }
144 
145             if(ifm->ifm_flags & IFF_UP)
146             {
147                 sdl = (struct sockaddr_dl *) (ifm + 1);
148                 if(sdl->sdl_family != AF_LINK)
149                     continue;
150 
151                 if(strncmp(m_deviceName.c_str(), sdl->sdl_data, sdl->sdl_nlen) == 0)
152                 {
153                     dataFrame.setTotalDataIn(ifm->ifm_data.ifi_ibytes);
154                     dataFrame.setTotalDataOut(ifm->ifm_data.ifi_obytes);
155 
156                     dataFrame.setTotalPacketsIn(ifm->ifm_data.ifi_ipackets);
157                     dataFrame.setTotalPacketsOut(ifm->ifm_data.ifi_opackets);
158 
159                     dataFrame.setTotalErrorsIn(ifm->ifm_data.ifi_ierrors);
160                     dataFrame.setTotalErrorsOut(ifm->ifm_data.ifi_oerrors);
161 
162                     dataFrame.setTotalDropsIn(0); // ifi_iqdrops ?
163                     dataFrame.setTotalDropsOut(0);
164 
165                     dataFrame.setValid(true);
166 
167                     break;
168                 }
169             }
170         }
171     } while(0);
172 
173     free(buf);
174 }
175 
176