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