/*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /*************************************************************************** * Free/Net/OpenBSD specific network code taken out of gkrellm: * * Copyright by Bill Wilson * * FreeBSD code by Hajimu Umemoto * * NetBSD code by Anthony Mallet * * Hajimu Umemoto merged Free/Net/OpenBSD code * * adapted for nload by Roland Riegel * ***************************************************************************/ #include "devreader-bsd.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; DevReaderBsd::DevReaderBsd(const string& deviceName) : DevReader(deviceName) { } DevReaderBsd::~DevReaderBsd() { } list DevReaderBsd::findAllDevices() { list interfaceNames; struct if_msghdr *ifm, *nextifm; struct sockaddr_dl *sdl; char *lim, *next; size_t needed; int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; char *buf = 0; if(sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) return interfaceNames; buf = (char *) malloc(needed); if(buf == NULL) return interfaceNames; if(sysctl(mib, 6, buf, &needed, NULL, 0) < 0) return interfaceNames; lim = buf + needed; next = buf; while(next < lim) { ifm = (struct if_msghdr *) next; if(ifm->ifm_type != RTM_IFINFO) break; next += ifm->ifm_msglen; while(next < lim) { nextifm = (struct if_msghdr *) next; if(nextifm->ifm_type != RTM_NEWADDR) break; next += nextifm->ifm_msglen; } sdl = (struct sockaddr_dl *) (ifm + 1); if(sdl->sdl_family != AF_LINK) continue; interfaceNames.push_back(string(sdl->sdl_data)); } free(buf); return interfaceNames; } void DevReaderBsd::readFromDevice(DataFrame& dataFrame) { struct if_msghdr *ifm, *nextifm; struct sockaddr_dl *sdl; char *lim, *next; size_t needed; int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0}; char *buf = 0; if(m_deviceName.empty()) return; do { if(sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) break; buf = (char *) malloc(needed); if(buf == NULL) break; if(sysctl(mib, 6, buf, &needed, NULL, 0) < 0) break; lim = buf + needed; next = buf; while(next < lim) { ifm = (struct if_msghdr *) next; if(ifm->ifm_type != RTM_IFINFO) break; next += ifm->ifm_msglen; while(next < lim) { nextifm = (struct if_msghdr *) next; if(nextifm->ifm_type != RTM_NEWADDR) break; next += nextifm->ifm_msglen; } if(ifm->ifm_flags & IFF_UP) { sdl = (struct sockaddr_dl *) (ifm + 1); if(sdl->sdl_family != AF_LINK) continue; if(strncmp(m_deviceName.c_str(), sdl->sdl_data, sdl->sdl_nlen) == 0) { dataFrame.setTotalDataIn(ifm->ifm_data.ifi_ibytes); dataFrame.setTotalDataOut(ifm->ifm_data.ifi_obytes); dataFrame.setTotalPacketsIn(ifm->ifm_data.ifi_ipackets); dataFrame.setTotalPacketsOut(ifm->ifm_data.ifi_opackets); dataFrame.setTotalErrorsIn(ifm->ifm_data.ifi_ierrors); dataFrame.setTotalErrorsOut(ifm->ifm_data.ifi_oerrors); dataFrame.setTotalDropsIn(0); // ifi_iqdrops ? dataFrame.setTotalDropsOut(0); dataFrame.setValid(true); break; } } } } while(0); free(buf); }