/* * Copyright (c) 2001 Hellmuth Michaelis. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *--------------------------------------------------------------------------- * * nifmon - network interface handling * ----------------------------------- * * last edit-date: [Sat Sep 8 15:28:18 2001] * *---------------------------------------------------------------------------*/ #include "nifmon.h" static int ifcount = 0; static int sockfd = -1; static int mrow; static struct ifconf ifc; static char buf[2048]; static int len; static char *ptr; static struct ifreq *ifr, *ifr1; static struct sockaddr_in *sin; static char *addr, *dstaddr; static char lastaddr[] = ""; static size_t slen; static int row; static struct ifmibdata ifmd; static int name[6]; static struct hostent he; static struct hostent *hep; static time_t lastchange; static time_t prevchange; static time_t lastdiff; static time_t prevdiff; static u_long ibs; static u_long obs; static u_long ips; static u_long ops; static time_t m_t; static u_long ibm; static u_long obm; static u_long ipm; static u_long opm; static time_t h_t; static u_long ibh; static u_long obh; static u_long iph; static u_long oph; static struct timeval tvlast; /*---------------------------------------------------------------------------* * initialize interface data *---------------------------------------------------------------------------*/ void init_interface(char *interface) { slen = sizeof(int); if (sysctlbyname("net.link.generic.system.ifcount", &ifcount, &slen, 0, 0) < 0) { perror("sysctl-ifcount"); do_exit(1); } sockfd = socket(AF_INET, SOCK_DGRAM, 0); ifc.ifc_len = sizeof(buf); ifc.ifc_req = (struct ifreq *) buf; ioctl(sockfd, SIOCGIFCONF, &ifc); for (ptr = buf; ptr < buf + ifc.ifc_len;) { ifr = (struct ifreq *) ptr; len = sizeof(struct sockaddr); if (ifr->ifr_addr.sa_len > len) len = ifr->ifr_addr.sa_len; ptr += sizeof(ifr->ifr_name) + len; if (strcmp(ifr->ifr_name, interface)) continue; if (ifr->ifr_addr.sa_family == AF_INET) { ifr1 = ifr; if (ioctl(sockfd, SIOCGIFFLAGS, ifr1) < 0) { perror("FLAGS"); do_exit(1); } if_flags = ifr1->ifr_flags; for (row = 1; row <= ifcount; row++) { slen = sizeof(ifmd); name[0] = CTL_NET; name[1] = PF_LINK; name[2] = NETLINK_GENERIC; name[3] = IFMIB_IFDATA; name[4] = row; name[5] = IFDATA_GENERAL; sysctl(name, 6, &ifmd, &slen, (void *) 0, 0); if (!strcmp(ifmd.ifmd_name, ifr->ifr_name)) { mrow = row; prevchange = ifmd.ifmd_data.ifi_lastchange. tv_sec; lastchange = prevchange = ifmd.ifmd_data.ifi_lastchange. tv_sec; gettimeofday(&tvlast, NULL); m_t = h_t = tvlast.tv_sec; ibs = ibm = ibh = ifmd.ifmd_data.ifi_ibytes; obs = obm = obh = ifmd.ifmd_data.ifi_obytes; ips = ipm = iph = ifmd.ifmd_data.ifi_ipackets; ops = opm = oph = ifmd.ifmd_data.ifi_opackets; break; } } break; } } } /*---------------------------------------------------------------------------* * update interface data *---------------------------------------------------------------------------*/ void update_interface(char *interface) { struct timeval tv; gettimeofday(&tv, NULL); if (tv.tv_sec == tvlast.tv_sec) return; if (tv.tv_sec == (tvlast.tv_sec + 1)) { if (tv.tv_usec < tvlast.tv_usec) return; } tvlast = tv; ifc.ifc_len = sizeof(buf); ifc.ifc_req = (struct ifreq *) buf; ioctl(sockfd, SIOCGIFCONF, &ifc); for (ptr = buf; ptr < buf + ifc.ifc_len;) { ifr = (struct ifreq *) ptr; len = sizeof(struct sockaddr); if (ifr->ifr_addr.sa_len > len) len = ifr->ifr_addr.sa_len; ptr += sizeof(ifr->ifr_name) + len; if (strcmp(ifr->ifr_name, interface)) continue; if (ifr->ifr_addr.sa_family == AF_INET) { ifr1 = ifr; if (ioctl(sockfd, SIOCGIFFLAGS, ifr1) < 0) { perror("FLAGS"); do_exit(1); } sin = (struct sockaddr_in *) &ifr1->ifr_addr; addr = inet_ntoa(sin->sin_addr); if(strcmp(addr, lastaddr)) { strcpy(lastaddr, addr); hep = &he; hep = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET); if (hep) hostname = hep->h_name; else hostname = "unknown hostname"; } mvwprintw(upper_w, V_IP, H_LOCIP, "%-15s", addr); mvwprintw(upper_w, V_IP, H_LOCHN, "%-36s", hostname); if (ifr1->ifr_flags & IFF_LOOPBACK) { } else if (ifr1->ifr_flags & IFF_POINTOPOINT) { if (ioctl(sockfd, SIOCGIFDSTADDR, ifr1) < 0) { perror("DST"); do_exit(1); } sin = (struct sockaddr_in *) &ifr1-> ifr_dstaddr; dstaddr = inet_ntoa(sin->sin_addr); mvwprintw(upper_w, V_IP, H_REMIP, "%-15s", dstaddr); } else { if (ioctl(sockfd, SIOCGIFBRDADDR, ifr1) < 0) { perror("BRD"); do_exit(1); } sin = (struct sockaddr_in *) &ifr1->ifr_broadaddr; dstaddr = inet_ntoa(sin->sin_addr); mvwprintw(upper_w, V_IP, H_REMIP, "%-15s", dstaddr); } slen = sizeof(ifmd); name[0] = CTL_NET; name[1] = PF_LINK; name[2] = NETLINK_GENERIC; name[3] = IFMIB_IFDATA; name[4] = mrow; name[5] = IFDATA_GENERAL; sysctl(name, 6, &ifmd, &slen, (void *) 0, 0); if (ifmd.ifmd_data.ifi_ibytes > 1024000000) sprintf(buf, "%lu (%dG)", ifmd.ifmd_data.ifi_ibytes, (int)ifmd.ifmd_data.ifi_ibytes / 1024000000); else if (ifmd.ifmd_data.ifi_ibytes > 1024000) sprintf(buf, "%lu (%dM)", ifmd.ifmd_data.ifi_ibytes, (int)ifmd.ifmd_data.ifi_ibytes / 1024000); else if (ifmd.ifmd_data.ifi_ibytes > 1024) sprintf(buf, "%lu (%dk)", ifmd.ifmd_data.ifi_ibytes, (int)ifmd.ifmd_data.ifi_ibytes / 1024); else sprintf(buf, "%lu", ifmd.ifmd_data.ifi_ibytes); mvwprintw(upper_w, V_BIO, H_BIN, "%-24s", buf); if (ifmd.ifmd_data.ifi_obytes > 1024000000) sprintf(buf, "%lu (%dG)", ifmd.ifmd_data.ifi_obytes, (int)ifmd.ifmd_data.ifi_obytes / 1024000000); else if (ifmd.ifmd_data.ifi_obytes > 1024000) sprintf(buf, "%lu (%dM)", ifmd.ifmd_data.ifi_obytes, (int)ifmd.ifmd_data.ifi_obytes / 1024000); else if (ifmd.ifmd_data.ifi_obytes > 1024) sprintf(buf, "%lu (%dk)", ifmd.ifmd_data.ifi_obytes, (int)ifmd.ifmd_data.ifi_obytes / 1024); else sprintf(buf, "%lu", ifmd.ifmd_data.ifi_obytes); mvwprintw(upper_w, V_BIO, H_BOUT, "%-24s", buf); mvwprintw(upper_w, V_PIO, H_PIN, "%lu", ifmd.ifmd_data.ifi_ipackets); mvwprintw(upper_w, V_PIO, H_POUT, "%lu", ifmd.ifmd_data.ifi_opackets); if (ifmd.ifmd_data.ifi_lastchange.tv_sec) { time_t diff; time_t d, h, m, r; diff = (time_t) difftime(tv.tv_sec, ifmd.ifmd_data. ifi_lastchange. tv_sec); d = diff / (24 * 60 * 60); r = diff % (24 * 60 * 60); h = r / (60 * 60); r = r % (60 * 60); m = r / 60; sprintf(buf, "%24.24s (%d:%d:%d)", ctime(&ifmd.ifmd_data. ifi_lastchange.tv_sec), (int)d, (int)h, (int)m); mvwprintw(upper_w, V_LADCD, H_LADMCHG, "%-35s", buf); if (ifmd.ifmd_data.ifi_lastchange.tv_sec != lastchange) { prevdiff = lastdiff; prevchange = lastchange; lastchange = ifmd.ifmd_data.ifi_lastchange. tv_sec; d = prevdiff / (24 * 60 * 60); r = prevdiff % (24 * 60 * 60); h = r / (60 * 60); r = r % (60 * 60); m = r / 60; sprintf(buf, "%24.24s (%d:%d:%d)", ctime(&prevchange), (int)d, (int)h, (int)m); mvwprintw(upper_w, V_LADCD, H_PADMCHG, "%-35s", buf); } lastdiff = diff; } else { mvwprintw(upper_w, V_LADCD, H_LADMCHG, "last administrative change time unsupported by driver"); } mvwprintw(upper_w, V_IBYTE, H_SEC, "%-9lu", ifmd.ifmd_data.ifi_ibytes - ibs); ibs = ifmd.ifmd_data.ifi_ibytes; mvwprintw(upper_w, V_OBYTE, H_SEC, "%-9lu", ifmd.ifmd_data.ifi_obytes - obs); obs = ifmd.ifmd_data.ifi_obytes; mvwprintw(upper_w, V_IPACK, H_SEC, "%-9lu", ifmd.ifmd_data.ifi_ipackets - ips); ips = ifmd.ifmd_data.ifi_ipackets; mvwprintw(upper_w, V_OPACK, H_SEC, "%-9lu", ifmd.ifmd_data.ifi_opackets - ops); ops = ifmd.ifmd_data.ifi_opackets; if (tv.tv_sec > (m_t + 60)) { m_t = tv.tv_sec; mvwprintw(upper_w, V_IBYTE, H_MIN, "%-16lu", ifmd.ifmd_data.ifi_ibytes - ibm); ibm = ifmd.ifmd_data.ifi_ibytes; mvwprintw(upper_w, V_OBYTE, H_MIN, "%-16lu", ifmd.ifmd_data.ifi_obytes - obm); obm = ifmd.ifmd_data.ifi_obytes; mvwprintw(upper_w, V_IPACK, H_MIN, "%-16lu", ifmd.ifmd_data.ifi_ipackets - ipm); ipm = ifmd.ifmd_data.ifi_ipackets; mvwprintw(upper_w, V_OPACK, H_MIN, "%-16lu", ifmd.ifmd_data.ifi_opackets - opm); opm = ifmd.ifmd_data.ifi_opackets; } if (tv.tv_sec > (h_t + (60 * 60))) { h_t = tv.tv_sec; mvwprintw(upper_w, V_IBYTE, H_HR, "%-16lu", ifmd.ifmd_data.ifi_ibytes - ibh); ibh = ifmd.ifmd_data.ifi_ibytes; mvwprintw(upper_w, V_OBYTE, H_HR, "%-16lu", ifmd.ifmd_data.ifi_obytes - obh); obh = ifmd.ifmd_data.ifi_obytes; mvwprintw(upper_w, V_IPACK, H_HR, "%-16lu", ifmd.ifmd_data.ifi_ipackets - iph); iph = ifmd.ifmd_data.ifi_ipackets; mvwprintw(upper_w, V_OPACK, H_HR, "%-16lu", ifmd.ifmd_data.ifi_opackets - oph); oph = ifmd.ifmd_data.ifi_opackets; } wrefresh(upper_w); break; } } } /* EOF */