11de7b4b8SPedro F. Giffuni /*-
21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
31de7b4b8SPedro F. Giffuni *
4b59ba7dfSPoul-Henning Kamp * Copyright (c) 2003, Trent Nelson, <trent@arpa.com>.
5b59ba7dfSPoul-Henning Kamp * All rights reserved.
6b59ba7dfSPoul-Henning Kamp *
7b59ba7dfSPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without
8b59ba7dfSPoul-Henning Kamp * modification, are permitted provided that the following conditions
9b59ba7dfSPoul-Henning Kamp * are met:
10b59ba7dfSPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright
11b59ba7dfSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer.
12b59ba7dfSPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright
13b59ba7dfSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the
14b59ba7dfSPoul-Henning Kamp * documentation and/or other materials provided with the distribution.
15b59ba7dfSPoul-Henning Kamp * 3. The name of the author may not be used to endorse or promote products
16b59ba7dfSPoul-Henning Kamp * derived from this software without specific prior written permission.
17b59ba7dfSPoul-Henning Kamp *
18b59ba7dfSPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19b59ba7dfSPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20b59ba7dfSPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21b59ba7dfSPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22b59ba7dfSPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23b59ba7dfSPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24b59ba7dfSPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTIFSTAT_ERRUPTION)
25b59ba7dfSPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26b59ba7dfSPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27b59ba7dfSPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28b59ba7dfSPoul-Henning Kamp * SUCH DAMAGE.
29b59ba7dfSPoul-Henning Kamp */
30b59ba7dfSPoul-Henning Kamp
31b59ba7dfSPoul-Henning Kamp #include <sys/types.h>
32b59ba7dfSPoul-Henning Kamp #include <sys/socket.h>
336bff85ffSDag-Erling Smørgrav #include <sys/queue.h>
34b59ba7dfSPoul-Henning Kamp #include <sys/sysctl.h>
35b59ba7dfSPoul-Henning Kamp #include <net/if.h>
36b59ba7dfSPoul-Henning Kamp #include <net/if_mib.h>
37b59ba7dfSPoul-Henning Kamp
384b9ac8a0SMichael Reifenberger #include <stdbool.h>
39b59ba7dfSPoul-Henning Kamp #include <stdlib.h>
4033dc5491SDavid Malone #include <string.h>
41b59ba7dfSPoul-Henning Kamp #include <err.h>
425abb148fSXin LI #include <errno.h>
43b0214723SAlexander V. Chernikov #include <fnmatch.h>
44b59ba7dfSPoul-Henning Kamp
45b59ba7dfSPoul-Henning Kamp #include "systat.h"
46b59ba7dfSPoul-Henning Kamp #include "extern.h"
47b59ba7dfSPoul-Henning Kamp #include "convtbl.h"
48b59ba7dfSPoul-Henning Kamp
49b59ba7dfSPoul-Henning Kamp /* Column numbers */
50b59ba7dfSPoul-Henning Kamp
51b59ba7dfSPoul-Henning Kamp #define C1 0 /* 0-19 */
52b59ba7dfSPoul-Henning Kamp #define C2 20 /* 20-39 */
53b59ba7dfSPoul-Henning Kamp #define C3 40 /* 40-59 */
54b59ba7dfSPoul-Henning Kamp #define C4 60 /* 60-80 */
55b59ba7dfSPoul-Henning Kamp #define C5 80 /* Used for label positioning. */
56b59ba7dfSPoul-Henning Kamp
5733dc5491SDavid Malone static const int col2 = C2;
5833dc5491SDavid Malone static const int col3 = C3;
5933dc5491SDavid Malone static const int col4 = C4;
60b59ba7dfSPoul-Henning Kamp
616d88f9feSMateusz Guzik static SLIST_HEAD(, if_stat) curlist;
62b59ba7dfSPoul-Henning Kamp
63b59ba7dfSPoul-Henning Kamp struct if_stat {
64b59ba7dfSPoul-Henning Kamp SLIST_ENTRY(if_stat) link;
654b9ac8a0SMichael Reifenberger char display_name[IF_NAMESIZE];
664b9ac8a0SMichael Reifenberger char dev_name[IFNAMSIZ]; /* copied from ifmibdata */
67b59ba7dfSPoul-Henning Kamp struct ifmibdata if_mib;
68b59ba7dfSPoul-Henning Kamp struct timeval tv;
69b59ba7dfSPoul-Henning Kamp struct timeval tv_lastchanged;
709daa89f3SRyan Stone uint64_t if_in_curtraffic;
719daa89f3SRyan Stone uint64_t if_out_curtraffic;
729daa89f3SRyan Stone uint64_t if_in_traffic_peak;
739daa89f3SRyan Stone uint64_t if_out_traffic_peak;
749daa89f3SRyan Stone uint64_t if_in_curpps;
759daa89f3SRyan Stone uint64_t if_out_curpps;
769daa89f3SRyan Stone uint64_t if_in_pps_peak;
779daa89f3SRyan Stone uint64_t if_out_pps_peak;
78b59ba7dfSPoul-Henning Kamp u_int if_row; /* Index into ifmib sysctl */
796052df8eSAlexander V. Chernikov int if_ypos; /* -1 if not being displayed */
804b9ac8a0SMichael Reifenberger bool display;
81b0214723SAlexander V. Chernikov u_int match;
82b59ba7dfSPoul-Henning Kamp };
83b59ba7dfSPoul-Henning Kamp
84b0214723SAlexander V. Chernikov static int needclear = 0;
854b9ac8a0SMichael Reifenberger static bool displayall = false;
86b59ba7dfSPoul-Henning Kamp
874b9ac8a0SMichael Reifenberger static void format_device_name(struct if_stat *);
884b9ac8a0SMichael Reifenberger static int getifmibdata(const int, struct ifmibdata *);
89b59ba7dfSPoul-Henning Kamp static void sort_interface_list(void);
90b59ba7dfSPoul-Henning Kamp static u_int getifnum(void);
914b9ac8a0SMichael Reifenberger static void clearifstat(void);
92b59ba7dfSPoul-Henning Kamp
93b59ba7dfSPoul-Henning Kamp #define IFSTAT_ERR(n, s) do { \
94627d915eSEd Schouten putchar('\014'); \
95b59ba7dfSPoul-Henning Kamp closeifstat(wnd); \
96b59ba7dfSPoul-Henning Kamp err((n), (s)); \
97b59ba7dfSPoul-Henning Kamp } while (0)
98b59ba7dfSPoul-Henning Kamp
998aa22952SBruce Evans #define TOPLINE 3
100b59ba7dfSPoul-Henning Kamp #define TOPLABEL \
101b59ba7dfSPoul-Henning Kamp " Interface Traffic Peak Total"
102b59ba7dfSPoul-Henning Kamp
1038aa22952SBruce Evans #define STARTING_ROW (TOPLINE + 1)
1048aa22952SBruce Evans #define ROW_SPACING (3)
1058aa22952SBruce Evans
106b0214723SAlexander V. Chernikov #define IN_col2 (showpps ? ifp->if_in_curpps : ifp->if_in_curtraffic)
107b0214723SAlexander V. Chernikov #define OUT_col2 (showpps ? ifp->if_out_curpps : ifp->if_out_curtraffic)
108b0214723SAlexander V. Chernikov #define IN_col3 (showpps ? \
109b0214723SAlexander V. Chernikov ifp->if_in_pps_peak : ifp->if_in_traffic_peak)
110b0214723SAlexander V. Chernikov #define OUT_col3 (showpps ? \
111b0214723SAlexander V. Chernikov ifp->if_out_pps_peak : ifp->if_out_traffic_peak)
112b0214723SAlexander V. Chernikov #define IN_col4 (showpps ? \
113b0214723SAlexander V. Chernikov ifp->if_mib.ifmd_data.ifi_ipackets : ifp->if_mib.ifmd_data.ifi_ibytes)
114b0214723SAlexander V. Chernikov #define OUT_col4 (showpps ? \
115b0214723SAlexander V. Chernikov ifp->if_mib.ifmd_data.ifi_opackets : ifp->if_mib.ifmd_data.ifi_obytes)
116b59ba7dfSPoul-Henning Kamp
117b59ba7dfSPoul-Henning Kamp #define EMPTY_COLUMN " "
118b59ba7dfSPoul-Henning Kamp #define CLEAR_COLUMN(y, x) mvprintw((y), (x), "%20s", EMPTY_COLUMN);
119b59ba7dfSPoul-Henning Kamp
120b59ba7dfSPoul-Henning Kamp #define DOPUTRATE(c, r, d) do { \
121b59ba7dfSPoul-Henning Kamp CLEAR_COLUMN(r, c); \
122b0214723SAlexander V. Chernikov if (showpps) { \
123b0214723SAlexander V. Chernikov mvprintw(r, (c), "%10.3f %cp%s ", \
124b0214723SAlexander V. Chernikov convert(d##_##c, curscale), \
125b0214723SAlexander V. Chernikov *get_string(d##_##c, curscale), \
126b0214723SAlexander V. Chernikov "/s"); \
127b0214723SAlexander V. Chernikov } \
128b0214723SAlexander V. Chernikov else { \
129b59ba7dfSPoul-Henning Kamp mvprintw(r, (c), "%10.3f %s%s ", \
130b59ba7dfSPoul-Henning Kamp convert(d##_##c, curscale), \
131b59ba7dfSPoul-Henning Kamp get_string(d##_##c, curscale), \
132b59ba7dfSPoul-Henning Kamp "/s"); \
133b0214723SAlexander V. Chernikov } \
134b59ba7dfSPoul-Henning Kamp } while (0)
135b59ba7dfSPoul-Henning Kamp
136b59ba7dfSPoul-Henning Kamp #define DOPUTTOTAL(c, r, d) do { \
137b59ba7dfSPoul-Henning Kamp CLEAR_COLUMN((r), (c)); \
138b0214723SAlexander V. Chernikov if (showpps) { \
139b0214723SAlexander V. Chernikov mvprintw((r), (c), "%12.3f %cp ", \
140b0214723SAlexander V. Chernikov convert(d##_##c, SC_AUTO), \
141b0214723SAlexander V. Chernikov *get_string(d##_##c, SC_AUTO)); \
142b0214723SAlexander V. Chernikov } \
143b0214723SAlexander V. Chernikov else { \
144b59ba7dfSPoul-Henning Kamp mvprintw((r), (c), "%12.3f %s ", \
145b59ba7dfSPoul-Henning Kamp convert(d##_##c, SC_AUTO), \
146b59ba7dfSPoul-Henning Kamp get_string(d##_##c, SC_AUTO)); \
147b0214723SAlexander V. Chernikov } \
148b59ba7dfSPoul-Henning Kamp } while (0)
149b59ba7dfSPoul-Henning Kamp
150b59ba7dfSPoul-Henning Kamp #define PUTRATE(c, r) do { \
151b59ba7dfSPoul-Henning Kamp DOPUTRATE(c, (r), IN); \
152b59ba7dfSPoul-Henning Kamp DOPUTRATE(c, (r)+1, OUT); \
153b59ba7dfSPoul-Henning Kamp } while (0)
154b59ba7dfSPoul-Henning Kamp
155b59ba7dfSPoul-Henning Kamp #define PUTTOTAL(c, r) do { \
156b59ba7dfSPoul-Henning Kamp DOPUTTOTAL(c, (r), IN); \
157b59ba7dfSPoul-Henning Kamp DOPUTTOTAL(c, (r)+1, OUT); \
158b59ba7dfSPoul-Henning Kamp } while (0)
159b59ba7dfSPoul-Henning Kamp
160b59ba7dfSPoul-Henning Kamp #define PUTNAME(p) do { \
1614b9ac8a0SMichael Reifenberger mvprintw(p->if_ypos, 0, "%s", p->display_name); \
162b59ba7dfSPoul-Henning Kamp mvprintw(p->if_ypos, col2-3, "%s", (const char *)"in"); \
163b59ba7dfSPoul-Henning Kamp mvprintw(p->if_ypos+1, col2-3, "%s", (const char *)"out"); \
164b59ba7dfSPoul-Henning Kamp } while (0)
165b59ba7dfSPoul-Henning Kamp
166b59ba7dfSPoul-Henning Kamp WINDOW *
openifstat(void)167b59ba7dfSPoul-Henning Kamp openifstat(void)
168b59ba7dfSPoul-Henning Kamp {
1698aa22952SBruce Evans return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0));
170b59ba7dfSPoul-Henning Kamp }
171b59ba7dfSPoul-Henning Kamp
172b59ba7dfSPoul-Henning Kamp void
closeifstat(WINDOW * w)173b59ba7dfSPoul-Henning Kamp closeifstat(WINDOW *w)
174b59ba7dfSPoul-Henning Kamp {
175b59ba7dfSPoul-Henning Kamp struct if_stat *node = NULL;
176b59ba7dfSPoul-Henning Kamp
177b59ba7dfSPoul-Henning Kamp while (!SLIST_EMPTY(&curlist)) {
178b59ba7dfSPoul-Henning Kamp node = SLIST_FIRST(&curlist);
179b59ba7dfSPoul-Henning Kamp SLIST_REMOVE_HEAD(&curlist, link);
180b59ba7dfSPoul-Henning Kamp free(node);
181b59ba7dfSPoul-Henning Kamp }
182b59ba7dfSPoul-Henning Kamp
183b59ba7dfSPoul-Henning Kamp if (w != NULL) {
184b59ba7dfSPoul-Henning Kamp wclear(w);
185b59ba7dfSPoul-Henning Kamp wrefresh(w);
186b59ba7dfSPoul-Henning Kamp delwin(w);
187b59ba7dfSPoul-Henning Kamp }
188b59ba7dfSPoul-Henning Kamp
189b59ba7dfSPoul-Henning Kamp return;
190b59ba7dfSPoul-Henning Kamp }
191b59ba7dfSPoul-Henning Kamp
192b59ba7dfSPoul-Henning Kamp void
labelifstat(void)193b59ba7dfSPoul-Henning Kamp labelifstat(void)
194b59ba7dfSPoul-Henning Kamp {
195b59ba7dfSPoul-Henning Kamp
196b59ba7dfSPoul-Henning Kamp wmove(wnd, TOPLINE, 0);
197b59ba7dfSPoul-Henning Kamp wclrtoeol(wnd);
198b59ba7dfSPoul-Henning Kamp mvprintw(TOPLINE, 0, "%s", TOPLABEL);
199b59ba7dfSPoul-Henning Kamp
200b59ba7dfSPoul-Henning Kamp return;
201b59ba7dfSPoul-Henning Kamp }
202b59ba7dfSPoul-Henning Kamp
203b59ba7dfSPoul-Henning Kamp void
showifstat(void)204b59ba7dfSPoul-Henning Kamp showifstat(void)
205b59ba7dfSPoul-Henning Kamp {
206b59ba7dfSPoul-Henning Kamp struct if_stat *ifp = NULL;
207b0214723SAlexander V. Chernikov
208b59ba7dfSPoul-Henning Kamp SLIST_FOREACH(ifp, &curlist, link) {
2096d88f9feSMateusz Guzik if (ifp->if_ypos < LINES - 3 && ifp->if_ypos != -1) {
2104b9ac8a0SMichael Reifenberger if (!ifp->display || ifp->match == 0) {
2116052df8eSAlexander V. Chernikov wmove(wnd, ifp->if_ypos, 0);
2126052df8eSAlexander V. Chernikov wclrtoeol(wnd);
2136052df8eSAlexander V. Chernikov wmove(wnd, ifp->if_ypos + 1, 0);
2146052df8eSAlexander V. Chernikov wclrtoeol(wnd);
2156d88f9feSMateusz Guzik } else {
216b59ba7dfSPoul-Henning Kamp PUTNAME(ifp);
217b59ba7dfSPoul-Henning Kamp PUTRATE(col2, ifp->if_ypos);
218b59ba7dfSPoul-Henning Kamp PUTRATE(col3, ifp->if_ypos);
219b59ba7dfSPoul-Henning Kamp PUTTOTAL(col4, ifp->if_ypos);
220b59ba7dfSPoul-Henning Kamp }
2216052df8eSAlexander V. Chernikov }
2226d88f9feSMateusz Guzik }
223b59ba7dfSPoul-Henning Kamp
224b59ba7dfSPoul-Henning Kamp return;
225b59ba7dfSPoul-Henning Kamp }
226b59ba7dfSPoul-Henning Kamp
227b59ba7dfSPoul-Henning Kamp int
initifstat(void)228b59ba7dfSPoul-Henning Kamp initifstat(void)
229b59ba7dfSPoul-Henning Kamp {
230b59ba7dfSPoul-Henning Kamp struct if_stat *p = NULL;
2314b9ac8a0SMichael Reifenberger u_int n, i;
232b59ba7dfSPoul-Henning Kamp
233b59ba7dfSPoul-Henning Kamp n = getifnum();
234b59ba7dfSPoul-Henning Kamp if (n <= 0)
235297c1ec1SAlexander V. Chernikov return (-1);
236b59ba7dfSPoul-Henning Kamp
237b59ba7dfSPoul-Henning Kamp SLIST_INIT(&curlist);
238b59ba7dfSPoul-Henning Kamp
239b59ba7dfSPoul-Henning Kamp for (i = 0; i < n; i++) {
2405abb148fSXin LI p = (struct if_stat *)calloc(1, sizeof(struct if_stat));
241b59ba7dfSPoul-Henning Kamp if (p == NULL)
242b59ba7dfSPoul-Henning Kamp IFSTAT_ERR(1, "out of memory");
243b59ba7dfSPoul-Henning Kamp p->if_row = i+1;
2444b9ac8a0SMichael Reifenberger if (getifmibdata(p->if_row, &p->if_mib) == -1) {
2454b9ac8a0SMichael Reifenberger free(p);
2464b9ac8a0SMichael Reifenberger continue;
2474b9ac8a0SMichael Reifenberger }
2484b9ac8a0SMichael Reifenberger SLIST_INSERT_HEAD(&curlist, p, link);
2494b9ac8a0SMichael Reifenberger format_device_name(p);
250b0214723SAlexander V. Chernikov p->match = 1;
251b59ba7dfSPoul-Henning Kamp
252b59ba7dfSPoul-Henning Kamp /*
253b59ba7dfSPoul-Henning Kamp * Initially, we only display interfaces that have
2544b9ac8a0SMichael Reifenberger * received some traffic unless display-all is on.
255b59ba7dfSPoul-Henning Kamp */
2564b9ac8a0SMichael Reifenberger if (displayall || p->if_mib.ifmd_data.ifi_ibytes != 0)
2574b9ac8a0SMichael Reifenberger p->display = true;
258b59ba7dfSPoul-Henning Kamp }
259b59ba7dfSPoul-Henning Kamp
260b59ba7dfSPoul-Henning Kamp sort_interface_list();
261b59ba7dfSPoul-Henning Kamp
262297c1ec1SAlexander V. Chernikov return (1);
263b59ba7dfSPoul-Henning Kamp }
264b59ba7dfSPoul-Henning Kamp
265b59ba7dfSPoul-Henning Kamp void
fetchifstat(void)266b59ba7dfSPoul-Henning Kamp fetchifstat(void)
267b59ba7dfSPoul-Henning Kamp {
2684b9ac8a0SMichael Reifenberger struct if_stat *ifp = NULL, *temp_var;
269b59ba7dfSPoul-Henning Kamp struct timeval tv, new_tv, old_tv;
270b59ba7dfSPoul-Henning Kamp double elapsed = 0.0;
2719daa89f3SRyan Stone uint64_t new_inb, new_outb, old_inb, old_outb = 0;
2729daa89f3SRyan Stone uint64_t new_inp, new_outp, old_inp, old_outp = 0;
273b59ba7dfSPoul-Henning Kamp
2744b9ac8a0SMichael Reifenberger SLIST_FOREACH_SAFE(ifp, &curlist, link, temp_var) {
275b59ba7dfSPoul-Henning Kamp /*
276b59ba7dfSPoul-Henning Kamp * Grab a copy of the old input/output values before we
277b59ba7dfSPoul-Henning Kamp * call getifmibdata().
278b59ba7dfSPoul-Henning Kamp */
279b59ba7dfSPoul-Henning Kamp old_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
280b59ba7dfSPoul-Henning Kamp old_outb = ifp->if_mib.ifmd_data.ifi_obytes;
281b0214723SAlexander V. Chernikov old_inp = ifp->if_mib.ifmd_data.ifi_ipackets;
282b0214723SAlexander V. Chernikov old_outp = ifp->if_mib.ifmd_data.ifi_opackets;
283b59ba7dfSPoul-Henning Kamp ifp->tv_lastchanged = ifp->if_mib.ifmd_data.ifi_lastchange;
284b59ba7dfSPoul-Henning Kamp
285902d9eafSEd Schouten (void)gettimeofday(&new_tv, NULL);
2864b9ac8a0SMichael Reifenberger if (getifmibdata(ifp->if_row, &ifp->if_mib) == -1 ) {
2874b9ac8a0SMichael Reifenberger /* if a device was removed */
2884b9ac8a0SMichael Reifenberger SLIST_REMOVE(&curlist, ifp, if_stat, link);
2894b9ac8a0SMichael Reifenberger free(ifp);
2904b9ac8a0SMichael Reifenberger needsort = 1;
291*f6fdf921SJohn Baldwin continue;
2924b9ac8a0SMichael Reifenberger } else if (strcmp(ifp->dev_name, ifp->if_mib.ifmd_name) != 0 ) {
2934b9ac8a0SMichael Reifenberger /* a device was removed and another one was added */
2944b9ac8a0SMichael Reifenberger format_device_name(ifp);
2954b9ac8a0SMichael Reifenberger /* clear to the current value for the new device */
2964b9ac8a0SMichael Reifenberger old_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
2974b9ac8a0SMichael Reifenberger old_outb = ifp->if_mib.ifmd_data.ifi_obytes;
2984b9ac8a0SMichael Reifenberger old_inp = ifp->if_mib.ifmd_data.ifi_ipackets;
2994b9ac8a0SMichael Reifenberger old_outp = ifp->if_mib.ifmd_data.ifi_opackets;
3004b9ac8a0SMichael Reifenberger needsort = 1;
3014b9ac8a0SMichael Reifenberger }
302b59ba7dfSPoul-Henning Kamp
303b59ba7dfSPoul-Henning Kamp new_inb = ifp->if_mib.ifmd_data.ifi_ibytes;
304b59ba7dfSPoul-Henning Kamp new_outb = ifp->if_mib.ifmd_data.ifi_obytes;
305b0214723SAlexander V. Chernikov new_inp = ifp->if_mib.ifmd_data.ifi_ipackets;
306b0214723SAlexander V. Chernikov new_outp = ifp->if_mib.ifmd_data.ifi_opackets;
307b59ba7dfSPoul-Henning Kamp
308b59ba7dfSPoul-Henning Kamp /* Display interface if it's received some traffic. */
3094b9ac8a0SMichael Reifenberger if (!ifp->display && new_inb > 0 && old_inb == 0) {
3104b9ac8a0SMichael Reifenberger ifp->display = true;
311b0214723SAlexander V. Chernikov needsort = 1;
312b59ba7dfSPoul-Henning Kamp }
313b59ba7dfSPoul-Henning Kamp
314b59ba7dfSPoul-Henning Kamp /*
315b59ba7dfSPoul-Henning Kamp * The rest is pretty trivial. Calculate the new values
316b59ba7dfSPoul-Henning Kamp * for our current traffic rates, and while we're there,
317b59ba7dfSPoul-Henning Kamp * see if we have new peak rates.
318b59ba7dfSPoul-Henning Kamp */
319b59ba7dfSPoul-Henning Kamp old_tv = ifp->tv;
320b59ba7dfSPoul-Henning Kamp timersub(&new_tv, &old_tv, &tv);
321b59ba7dfSPoul-Henning Kamp elapsed = tv.tv_sec + (tv.tv_usec * 1e-6);
322b59ba7dfSPoul-Henning Kamp
323b59ba7dfSPoul-Henning Kamp ifp->if_in_curtraffic = new_inb - old_inb;
324b59ba7dfSPoul-Henning Kamp ifp->if_out_curtraffic = new_outb - old_outb;
325b59ba7dfSPoul-Henning Kamp
326b0214723SAlexander V. Chernikov ifp->if_in_curpps = new_inp - old_inp;
327b0214723SAlexander V. Chernikov ifp->if_out_curpps = new_outp - old_outp;
328b0214723SAlexander V. Chernikov
329b59ba7dfSPoul-Henning Kamp /*
330b59ba7dfSPoul-Henning Kamp * Rather than divide by the time specified on the comm-
331b59ba7dfSPoul-Henning Kamp * and line, we divide by ``elapsed'' as this is likely
332b59ba7dfSPoul-Henning Kamp * to be more accurate.
333b59ba7dfSPoul-Henning Kamp */
334b59ba7dfSPoul-Henning Kamp ifp->if_in_curtraffic /= elapsed;
335b59ba7dfSPoul-Henning Kamp ifp->if_out_curtraffic /= elapsed;
336b0214723SAlexander V. Chernikov ifp->if_in_curpps /= elapsed;
337b0214723SAlexander V. Chernikov ifp->if_out_curpps /= elapsed;
338b59ba7dfSPoul-Henning Kamp
339b59ba7dfSPoul-Henning Kamp if (ifp->if_in_curtraffic > ifp->if_in_traffic_peak)
340b59ba7dfSPoul-Henning Kamp ifp->if_in_traffic_peak = ifp->if_in_curtraffic;
341b59ba7dfSPoul-Henning Kamp
342b59ba7dfSPoul-Henning Kamp if (ifp->if_out_curtraffic > ifp->if_out_traffic_peak)
343b59ba7dfSPoul-Henning Kamp ifp->if_out_traffic_peak = ifp->if_out_curtraffic;
344b59ba7dfSPoul-Henning Kamp
345b0214723SAlexander V. Chernikov if (ifp->if_in_curpps > ifp->if_in_pps_peak)
346b0214723SAlexander V. Chernikov ifp->if_in_pps_peak = ifp->if_in_curpps;
347b0214723SAlexander V. Chernikov
348b0214723SAlexander V. Chernikov if (ifp->if_out_curpps > ifp->if_out_pps_peak)
349b0214723SAlexander V. Chernikov ifp->if_out_pps_peak = ifp->if_out_curpps;
350b0214723SAlexander V. Chernikov
351b59ba7dfSPoul-Henning Kamp ifp->tv.tv_sec = new_tv.tv_sec;
352b59ba7dfSPoul-Henning Kamp ifp->tv.tv_usec = new_tv.tv_usec;
353b59ba7dfSPoul-Henning Kamp
354b59ba7dfSPoul-Henning Kamp }
355b59ba7dfSPoul-Henning Kamp
356b0214723SAlexander V. Chernikov if (needsort)
357b59ba7dfSPoul-Henning Kamp sort_interface_list();
358b59ba7dfSPoul-Henning Kamp
359b59ba7dfSPoul-Henning Kamp return;
360b59ba7dfSPoul-Henning Kamp }
361b59ba7dfSPoul-Henning Kamp
362b59ba7dfSPoul-Henning Kamp /*
363b59ba7dfSPoul-Henning Kamp * We want to right justify our interface names against the first column
364b59ba7dfSPoul-Henning Kamp * (first sixteen or so characters), so we need to do some alignment.
3654b9ac8a0SMichael Reifenberger * We save original name so that we can find a same spot is take by a
3664b9ac8a0SMichael Reifenberger * different device.
367b59ba7dfSPoul-Henning Kamp */
368b59ba7dfSPoul-Henning Kamp static void
format_device_name(struct if_stat * ifp)3694b9ac8a0SMichael Reifenberger format_device_name(struct if_stat *ifp)
370b59ba7dfSPoul-Henning Kamp {
371b59ba7dfSPoul-Henning Kamp
3724b9ac8a0SMichael Reifenberger if (ifp != NULL ) {
3734b9ac8a0SMichael Reifenberger snprintf(ifp->display_name, IF_NAMESIZE, "%*s", IF_NAMESIZE-1,
3744b9ac8a0SMichael Reifenberger ifp->if_mib.ifmd_name);
3754b9ac8a0SMichael Reifenberger strcpy(ifp->dev_name, ifp->if_mib.ifmd_name);
376b59ba7dfSPoul-Henning Kamp }
377b59ba7dfSPoul-Henning Kamp }
378b59ba7dfSPoul-Henning Kamp
379b0214723SAlexander V. Chernikov static int
check_match(const char * ifname)380b0214723SAlexander V. Chernikov check_match(const char *ifname)
381b0214723SAlexander V. Chernikov {
3826d88f9feSMateusz Guzik char *p = matchline, *ch, t;
383b0214723SAlexander V. Chernikov int match = 0, mlen;
384b0214723SAlexander V. Chernikov
385297c1ec1SAlexander V. Chernikov if (matchline == NULL)
386297c1ec1SAlexander V. Chernikov return (0);
387297c1ec1SAlexander V. Chernikov
388b0214723SAlexander V. Chernikov /* Strip leading whitespaces */
389b0214723SAlexander V. Chernikov while (*p == ' ')
390b0214723SAlexander V. Chernikov p ++;
391b0214723SAlexander V. Chernikov
3926d88f9feSMateusz Guzik ch = p;
3936d88f9feSMateusz Guzik while ((mlen = strcspn(ch, " ;,")) != 0) {
3946d88f9feSMateusz Guzik p = ch + mlen;
395b0214723SAlexander V. Chernikov t = *p;
3966d88f9feSMateusz Guzik if (p - ch > 0) {
397b0214723SAlexander V. Chernikov *p = '\0';
3986d88f9feSMateusz Guzik if (fnmatch(ch, ifname, FNM_CASEFOLD) == 0) {
399b0214723SAlexander V. Chernikov *p = t;
400297c1ec1SAlexander V. Chernikov return (1);
401b0214723SAlexander V. Chernikov }
402b0214723SAlexander V. Chernikov *p = t;
4036d88f9feSMateusz Guzik ch = p + strspn(p, " ;,");
404b0214723SAlexander V. Chernikov }
405b0214723SAlexander V. Chernikov else {
4066d88f9feSMateusz Guzik ch = p + strspn(p, " ;,");
407b0214723SAlexander V. Chernikov }
408b0214723SAlexander V. Chernikov }
409b0214723SAlexander V. Chernikov
410297c1ec1SAlexander V. Chernikov return (match);
411b0214723SAlexander V. Chernikov }
412b0214723SAlexander V. Chernikov
413b59ba7dfSPoul-Henning Kamp /*
414b59ba7dfSPoul-Henning Kamp * This function iterates through our list of interfaces, identifying
415b59ba7dfSPoul-Henning Kamp * those that are to be displayed (ifp->display = 1). For each interf-
416b59ba7dfSPoul-Henning Kamp * rface that we're displaying, we generate an appropriate position for
417b59ba7dfSPoul-Henning Kamp * it on the screen (ifp->if_ypos).
418b59ba7dfSPoul-Henning Kamp *
419b59ba7dfSPoul-Henning Kamp * This function is called any time a change is made to an interface's
420b59ba7dfSPoul-Henning Kamp * ``display'' state.
421b59ba7dfSPoul-Henning Kamp */
422b59ba7dfSPoul-Henning Kamp void
sort_interface_list(void)423b59ba7dfSPoul-Henning Kamp sort_interface_list(void)
424b59ba7dfSPoul-Henning Kamp {
425b59ba7dfSPoul-Henning Kamp struct if_stat *ifp = NULL;
426b59ba7dfSPoul-Henning Kamp u_int y = 0;
427b59ba7dfSPoul-Henning Kamp
428b59ba7dfSPoul-Henning Kamp y = STARTING_ROW;
429b59ba7dfSPoul-Henning Kamp SLIST_FOREACH(ifp, &curlist, link) {
430b0214723SAlexander V. Chernikov if (matchline && !check_match(ifp->if_mib.ifmd_name))
431b0214723SAlexander V. Chernikov ifp->match = 0;
432b0214723SAlexander V. Chernikov else
433b0214723SAlexander V. Chernikov ifp->match = 1;
434b0214723SAlexander V. Chernikov if (ifp->display && ifp->match) {
435b59ba7dfSPoul-Henning Kamp ifp->if_ypos = y;
436b59ba7dfSPoul-Henning Kamp y += ROW_SPACING;
437b59ba7dfSPoul-Henning Kamp }
4386052df8eSAlexander V. Chernikov else
4396052df8eSAlexander V. Chernikov ifp->if_ypos = -1;
440b59ba7dfSPoul-Henning Kamp }
441b0214723SAlexander V. Chernikov
442b0214723SAlexander V. Chernikov needsort = 0;
443b0214723SAlexander V. Chernikov needclear = 1;
444b59ba7dfSPoul-Henning Kamp }
445b59ba7dfSPoul-Henning Kamp
446b59ba7dfSPoul-Henning Kamp static
447b59ba7dfSPoul-Henning Kamp unsigned int
getifnum(void)448b59ba7dfSPoul-Henning Kamp getifnum(void)
449b59ba7dfSPoul-Henning Kamp {
450b59ba7dfSPoul-Henning Kamp u_int data = 0;
451b59ba7dfSPoul-Henning Kamp size_t datalen = 0;
452b59ba7dfSPoul-Henning Kamp static int name[] = { CTL_NET,
453b59ba7dfSPoul-Henning Kamp PF_LINK,
454b59ba7dfSPoul-Henning Kamp NETLINK_GENERIC,
455b59ba7dfSPoul-Henning Kamp IFMIB_SYSTEM,
456b59ba7dfSPoul-Henning Kamp IFMIB_IFCOUNT };
457b59ba7dfSPoul-Henning Kamp
458b59ba7dfSPoul-Henning Kamp datalen = sizeof(data);
45933dc5491SDavid Malone if (sysctl(name, 5, (void *)&data, (size_t *)&datalen, (void *)NULL,
46033dc5491SDavid Malone (size_t)0) != 0)
461b59ba7dfSPoul-Henning Kamp IFSTAT_ERR(1, "sysctl error");
462297c1ec1SAlexander V. Chernikov return (data);
463b59ba7dfSPoul-Henning Kamp }
464b59ba7dfSPoul-Henning Kamp
4654b9ac8a0SMichael Reifenberger static int
getifmibdata(int row,struct ifmibdata * data)466b59ba7dfSPoul-Henning Kamp getifmibdata(int row, struct ifmibdata *data)
467b59ba7dfSPoul-Henning Kamp {
4684b9ac8a0SMichael Reifenberger int ret = 0;
469b59ba7dfSPoul-Henning Kamp size_t datalen = 0;
470b59ba7dfSPoul-Henning Kamp static int name[] = { CTL_NET,
471b59ba7dfSPoul-Henning Kamp PF_LINK,
472b59ba7dfSPoul-Henning Kamp NETLINK_GENERIC,
473b59ba7dfSPoul-Henning Kamp IFMIB_IFDATA,
474b59ba7dfSPoul-Henning Kamp 0,
475b59ba7dfSPoul-Henning Kamp IFDATA_GENERAL };
476b59ba7dfSPoul-Henning Kamp datalen = sizeof(*data);
477b59ba7dfSPoul-Henning Kamp name[4] = row;
478b59ba7dfSPoul-Henning Kamp
4794b9ac8a0SMichael Reifenberger ret = sysctl(name, 6, (void *)data, (size_t *)&datalen, (void *)NULL,
4804b9ac8a0SMichael Reifenberger (size_t)0);
4814b9ac8a0SMichael Reifenberger if ((ret != 0) && (errno != ENOENT))
482b59ba7dfSPoul-Henning Kamp IFSTAT_ERR(2, "sysctl error getting interface data");
4834b9ac8a0SMichael Reifenberger
4844b9ac8a0SMichael Reifenberger return (ret);
485b59ba7dfSPoul-Henning Kamp }
486b59ba7dfSPoul-Henning Kamp
487b59ba7dfSPoul-Henning Kamp int
cmdifstat(const char * cmd,const char * args)488b59ba7dfSPoul-Henning Kamp cmdifstat(const char *cmd, const char *args)
489b59ba7dfSPoul-Henning Kamp {
490b59ba7dfSPoul-Henning Kamp int retval = 0;
491b59ba7dfSPoul-Henning Kamp
492b59ba7dfSPoul-Henning Kamp retval = ifcmd(cmd, args);
493b59ba7dfSPoul-Henning Kamp /* ifcmd() returns 1 on success */
494b59ba7dfSPoul-Henning Kamp if (retval == 1) {
4954b9ac8a0SMichael Reifenberger if (needclear)
4964b9ac8a0SMichael Reifenberger clearifstat();
4974b9ac8a0SMichael Reifenberger }
4984b9ac8a0SMichael Reifenberger else if (prefix(cmd, "all")) {
4994b9ac8a0SMichael Reifenberger retval = 1;
5004b9ac8a0SMichael Reifenberger displayall = true;
5014b9ac8a0SMichael Reifenberger }
5024b9ac8a0SMichael Reifenberger return (retval);
5034b9ac8a0SMichael Reifenberger }
5044b9ac8a0SMichael Reifenberger
5054b9ac8a0SMichael Reifenberger static void
clearifstat(void)5064b9ac8a0SMichael Reifenberger clearifstat(void)
5074b9ac8a0SMichael Reifenberger {
5084b9ac8a0SMichael Reifenberger
509b59ba7dfSPoul-Henning Kamp showifstat();
510b59ba7dfSPoul-Henning Kamp refresh();
511b0214723SAlexander V. Chernikov werase(wnd);
512b0214723SAlexander V. Chernikov labelifstat();
513b0214723SAlexander V. Chernikov needclear = 0;
514b0214723SAlexander V. Chernikov }
515