16b463eedSChristian S.J. Peron /*- 26b463eedSChristian S.J. Peron * Copyright (c) 2005 Christian S.J. Peron 36b463eedSChristian S.J. Peron * All rights reserved. 46b463eedSChristian S.J. Peron * 56b463eedSChristian S.J. Peron * Redistribution and use in source and binary forms, with or without 66b463eedSChristian S.J. Peron * modification, are permitted provided that the following conditions 76b463eedSChristian S.J. Peron * are met: 86b463eedSChristian S.J. Peron * 1. Redistributions of source code must retain the above copyright 96b463eedSChristian S.J. Peron * notice, this list of conditions and the following disclaimer. 106b463eedSChristian S.J. Peron * 2. Redistributions in binary form must reproduce the above copyright 116b463eedSChristian S.J. Peron * notice, this list of conditions and the following disclaimer in the 126b463eedSChristian S.J. Peron * documentation and/or other materials provided with the distribution. 136b463eedSChristian S.J. Peron * 146b463eedSChristian S.J. Peron * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 156b463eedSChristian S.J. Peron * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 166b463eedSChristian S.J. Peron * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 176b463eedSChristian S.J. Peron * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 186b463eedSChristian S.J. Peron * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 196b463eedSChristian S.J. Peron * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 206b463eedSChristian S.J. Peron * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 216b463eedSChristian S.J. Peron * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 226b463eedSChristian S.J. Peron * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 236b463eedSChristian S.J. Peron * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 246b463eedSChristian S.J. Peron * SUCH DAMAGE. 256b463eedSChristian S.J. Peron */ 2665475bc8SDavid E. O'Brien 2765475bc8SDavid E. O'Brien #include <sys/cdefs.h> 2865475bc8SDavid E. O'Brien __FBSDID("$FreeBSD$"); 2965475bc8SDavid E. O'Brien 306b463eedSChristian S.J. Peron #include <sys/types.h> 316b463eedSChristian S.J. Peron #include <sys/protosw.h> 326b463eedSChristian S.J. Peron #include <sys/socket.h> 33feda1a43SJohn Baldwin #include <sys/socketvar.h> 346b463eedSChristian S.J. Peron #include <sys/sysctl.h> 356b463eedSChristian S.J. Peron #include <sys/param.h> 366b463eedSChristian S.J. Peron #include <sys/user.h> 376b463eedSChristian S.J. Peron 386b463eedSChristian S.J. Peron #include <net/if.h> 396b463eedSChristian S.J. Peron #include <net/if_var.h> 40560a54e1SJung-uk Kim #include <net/bpf.h> 416b463eedSChristian S.J. Peron #include <net/bpfdesc.h> 426b463eedSChristian S.J. Peron #include <arpa/inet.h> 436b463eedSChristian S.J. Peron 446b463eedSChristian S.J. Peron #include <err.h> 456b463eedSChristian S.J. Peron #include <errno.h> 467b95a1ebSYaroslav Tykhiy #include <stdint.h> 476b463eedSChristian S.J. Peron #include <stdio.h> 486b463eedSChristian S.J. Peron #include <stdlib.h> 49*ade9ccfeSMarcel Moolenaar #include <stdbool.h> 506b463eedSChristian S.J. Peron #include <string.h> 51821df508SXin LI #include <unistd.h> 52*ade9ccfeSMarcel Moolenaar #include <libxo/xo.h> 536b463eedSChristian S.J. Peron 546b463eedSChristian S.J. Peron #include "netstat.h" 556b463eedSChristian S.J. Peron 566b463eedSChristian S.J. Peron /* print bpf stats */ 576b463eedSChristian S.J. Peron 586b463eedSChristian S.J. Peron static char * 596b463eedSChristian S.J. Peron bpf_pidname(pid_t pid) 606b463eedSChristian S.J. Peron { 616b463eedSChristian S.J. Peron struct kinfo_proc newkp; 626b463eedSChristian S.J. Peron int error, mib[4]; 636b463eedSChristian S.J. Peron size_t size; 646b463eedSChristian S.J. Peron 656b463eedSChristian S.J. Peron mib[0] = CTL_KERN; 666b463eedSChristian S.J. Peron mib[1] = KERN_PROC; 676b463eedSChristian S.J. Peron mib[2] = KERN_PROC_PID; 686b463eedSChristian S.J. Peron mib[3] = pid; 696b463eedSChristian S.J. Peron size = sizeof(newkp); 706b463eedSChristian S.J. Peron error = sysctl(mib, 4, &newkp, &size, NULL, 0); 716f798df5SChristian S.J. Peron if (error < 0) { 72*ade9ccfeSMarcel Moolenaar xo_warn("kern.proc.pid failed"); 736b463eedSChristian S.J. Peron return (strdup("??????")); 746f798df5SChristian S.J. Peron } 756b463eedSChristian S.J. Peron return (strdup(newkp.ki_comm)); 766b463eedSChristian S.J. Peron } 776b463eedSChristian S.J. Peron 786b463eedSChristian S.J. Peron static void 796b463eedSChristian S.J. Peron bpf_flags(struct xbpf_d *bd, char *flagbuf) 806b463eedSChristian S.J. Peron { 816b463eedSChristian S.J. Peron 826b463eedSChristian S.J. Peron *flagbuf++ = bd->bd_promisc ? 'p' : '-'; 836b463eedSChristian S.J. Peron *flagbuf++ = bd->bd_immediate ? 'i' : '-'; 846b463eedSChristian S.J. Peron *flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f'; 85560a54e1SJung-uk Kim *flagbuf++ = (bd->bd_direction == BPF_D_IN) ? '-' : 86560a54e1SJung-uk Kim ((bd->bd_direction == BPF_D_OUT) ? 'o' : 's'); 87560a54e1SJung-uk Kim *flagbuf++ = bd->bd_feedback ? 'b' : '-'; 886b463eedSChristian S.J. Peron *flagbuf++ = bd->bd_async ? 'a' : '-'; 896b463eedSChristian S.J. Peron *flagbuf++ = bd->bd_locked ? 'l' : '-'; 906b463eedSChristian S.J. Peron *flagbuf++ = '\0'; 91*ade9ccfeSMarcel Moolenaar 92*ade9ccfeSMarcel Moolenaar if (bd->bd_promisc) 93*ade9ccfeSMarcel Moolenaar xo_emit("{e:promiscuous/}"); 94*ade9ccfeSMarcel Moolenaar if (bd->bd_immediate) 95*ade9ccfeSMarcel Moolenaar xo_emit("{e:immediate/}"); 96*ade9ccfeSMarcel Moolenaar if (bd->bd_hdrcmplt) 97*ade9ccfeSMarcel Moolenaar xo_emit("{e:header-complete/}"); 98*ade9ccfeSMarcel Moolenaar xo_emit("{e:direction}", (bd->bd_direction == BPF_D_IN) ? "input" : 99*ade9ccfeSMarcel Moolenaar (bd->bd_direction == BPF_D_OUT) ? "output" : "bidirectional"); 100*ade9ccfeSMarcel Moolenaar if (bd->bd_feedback) 101*ade9ccfeSMarcel Moolenaar xo_emit("{e:feedback/}"); 102*ade9ccfeSMarcel Moolenaar if (bd->bd_async) 103*ade9ccfeSMarcel Moolenaar xo_emit("{e:async/}"); 104*ade9ccfeSMarcel Moolenaar if (bd->bd_locked) 105*ade9ccfeSMarcel Moolenaar xo_emit("{e:locked/}"); 1066b463eedSChristian S.J. Peron } 1076b463eedSChristian S.J. Peron 1086b463eedSChristian S.J. Peron void 10904f7f23bSYaroslav Tykhiy bpf_stats(char *ifname) 1106b463eedSChristian S.J. Peron { 1110e37f3e1SChristian S.J. Peron struct xbpf_d *d, *bd, zerostat; 1126b463eedSChristian S.J. Peron char *pname, flagbuf[12]; 1136b463eedSChristian S.J. Peron size_t size; 1146b463eedSChristian S.J. Peron 1150e37f3e1SChristian S.J. Peron if (zflag) { 1160e37f3e1SChristian S.J. Peron bzero(&zerostat, sizeof(zerostat)); 1170e37f3e1SChristian S.J. Peron if (sysctlbyname("net.bpf.stats", NULL, NULL, 1180e37f3e1SChristian S.J. Peron &zerostat, sizeof(zerostat)) < 0) 119*ade9ccfeSMarcel Moolenaar xo_warn("failed to zero bpf counters"); 1200e37f3e1SChristian S.J. Peron return; 1210e37f3e1SChristian S.J. Peron } 1226b463eedSChristian S.J. Peron if (sysctlbyname("net.bpf.stats", NULL, &size, 1236b463eedSChristian S.J. Peron NULL, 0) < 0) { 124*ade9ccfeSMarcel Moolenaar xo_warn("net.bpf.stats"); 1256b463eedSChristian S.J. Peron return; 1266b463eedSChristian S.J. Peron } 12715f3d81fSChristian S.J. Peron if (size == 0) 12815f3d81fSChristian S.J. Peron return; 1296b463eedSChristian S.J. Peron bd = malloc(size); 1306b463eedSChristian S.J. Peron if (bd == NULL) { 131*ade9ccfeSMarcel Moolenaar xo_warn("malloc failed"); 1326b463eedSChristian S.J. Peron return; 1336b463eedSChristian S.J. Peron } 1346b463eedSChristian S.J. Peron if (sysctlbyname("net.bpf.stats", bd, &size, 1356b463eedSChristian S.J. Peron NULL, 0) < 0) { 136*ade9ccfeSMarcel Moolenaar xo_warn("net.bpf.stats"); 1376b463eedSChristian S.J. Peron free(bd); 1386b463eedSChristian S.J. Peron return; 1396b463eedSChristian S.J. Peron } 140*ade9ccfeSMarcel Moolenaar xo_emit("{T:/%5s} {T:/%6s} {T:/%7s} {T:/%9s} {T:/%9s} {T:/%9s} " 141*ade9ccfeSMarcel Moolenaar "{T:/%5s} {T:/%5s} {T:/%s}\n", 142*ade9ccfeSMarcel Moolenaar "Pid", "Netif", "Flags", "Recv", "Drop", "Match", 143*ade9ccfeSMarcel Moolenaar "Sblen", "Hblen", "Command"); 144*ade9ccfeSMarcel Moolenaar xo_open_container("bpf-statistics"); 145*ade9ccfeSMarcel Moolenaar xo_open_list("bpf-entry"); 1466b463eedSChristian S.J. Peron for (d = &bd[0]; d < &bd[size / sizeof(*d)]; d++) { 147582908b3SChristian S.J. Peron if (d->bd_structsize != sizeof(*d)) { 148*ade9ccfeSMarcel Moolenaar xo_warnx("bpf_stats_extended: version mismatch"); 149582908b3SChristian S.J. Peron return; 150582908b3SChristian S.J. Peron } 15104f7f23bSYaroslav Tykhiy if (ifname && strcmp(ifname, d->bd_ifname) != 0) 1526b463eedSChristian S.J. Peron continue; 153*ade9ccfeSMarcel Moolenaar xo_open_instance("bpf-entry"); 1546b463eedSChristian S.J. Peron pname = bpf_pidname(d->bd_pid); 155*ade9ccfeSMarcel Moolenaar xo_emit("{k:pid/%5d} {k:interface-name/%6s} ", 156*ade9ccfeSMarcel Moolenaar d->bd_pid, d->bd_ifname); 157*ade9ccfeSMarcel Moolenaar bpf_flags(d, flagbuf); 158*ade9ccfeSMarcel Moolenaar xo_emit("{d:flags/%7s} {:received-packets/%9ju} " 159*ade9ccfeSMarcel Moolenaar "{:dropped-packets/%9ju} {:filter-packets/%9ju} " 160*ade9ccfeSMarcel Moolenaar "{:store-buffer-length/%5d} {:hold-buffer-length/%5d} " 161*ade9ccfeSMarcel Moolenaar "{:process/%s}\n", 162*ade9ccfeSMarcel Moolenaar flagbuf, (uintmax_t)d->bd_rcount, (uintmax_t)d->bd_dcount, 163*ade9ccfeSMarcel Moolenaar (uintmax_t)d->bd_fcount, d->bd_slen, d->bd_hlen, pname); 1646b463eedSChristian S.J. Peron free(pname); 165*ade9ccfeSMarcel Moolenaar xo_close_instance("bpf-entry"); 1666b463eedSChristian S.J. Peron } 167*ade9ccfeSMarcel Moolenaar xo_close_list("bpf-entry"); 168*ade9ccfeSMarcel Moolenaar xo_close_container("bpf-statistics"); 16948d91509SChristian S.J. Peron free(bd); 1706b463eedSChristian S.J. Peron } 171