/* * Copyright (c) 2002 Pedro Bastos * 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. * 3. Neither the name of the author nor the name of his contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY PEDRO BASTOS AND HIS 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. * */ #include #include #include #include #include #include #ifdef OPENBSD #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #endif #ifdef FREEBSD #include #include #include #include #include #include #include #include #include #endif #include "extern.h" #include "global.h" #include "kernel.h" #include "lncurses.h" #include "machmon.h" kvm_t *kd; #ifdef _E_DEBUG void debug_inf_w(char *, ...); #endif /* static float *kern_ifs_cr(unsigned short int, u_long, u_long); */ #ifdef OPENBSD struct nlist mm_nl[] = { { "_ifnet" }, { "_mbpool" }, { "_mclpool" }, { "_fscale" }, { "__ccpu" }, { "_physmem" }, { "_maxslp"}, { NULL } }; static struct _l_pkt l_pkt[5]; static struct pool mbpool, mclpool; static int kernel_read(u_long, char *, size_t); #endif /* * kernel_read() uses the kernel descriptor kd to transfer size bytes of data * beginning at the address addr to the buffer pointed by buff. */ #ifdef OPENBSD static int kernel_read(u_long addr, char *buff, size_t size) { if (kvm_read(kd, addr, buff, size) != size) return (0); return (1); } #endif /* * kernel_start() attempts to open a kernel descriptor which will be used for * further conversations between we and the kernel, and a meta-symbol table * for referencing objects common to both sides of the communication channel. */ int kernel_start(void) { char buff[_POSIX2_LINE_MAX]; if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buff)) == NULL) return (0); if (kvm_nlist(kd, mm_nl) < 0 || mm_nl[0].n_type == 0) return (0); return (1); } #ifdef OPENBSD int d_ifs(void) { int ifs_n = 0; struct ifnet_head ifhead; struct ifnet ifnet; u_long *ifnetaddr = NULL; if (!kernel_read(mm_nl[N_IFNET].n_value, (char *) &ifhead, sizeof(ifhead))) return (1); ifnetaddr = (u_long *) ifhead.tqh_first; output("~WInterfaces:\n"); while (ifnetaddr) { if (!kernel_read((u_long) ifnetaddr, (char *) &ifnet, sizeof(ifnet))) { free(ifnetaddr); return (1); } output("~G%d: ~w%s\t", ifs_n, ifnet.if_xname); if ((ifnet.if_flags & IFF_UP) == 0) { output("~RDOWN\n"); } else { output("~GUP "); output("~C%.2f~w pkt/s in, ", (float) (((float) ifnet.if_data.ifi_ipackets - (float) l_pkt[ifs_n].packs_in) / (float) synctime)); output("~R%.2f~w pkt/s out\n", (float) (((float) ifnet.if_data.ifi_opackets - (float) l_pkt[ifs_n].packs_out) / (float) synctime)); l_pkt[ifs_n].packs_in = ifnet.if_data.ifi_ipackets; l_pkt[ifs_n].packs_out = ifnet.if_data.ifi_opackets; } ifs_n++; ifnetaddr = (u_long *) ifnet.if_list.tqe_next; } free(ifnetaddr); return (0); } #endif #ifdef FREEBSD int d_ifs(void) { return (1); } #endif int d_mbufs(void) { int mib[4], totmem; int totpct, totused; size_t size; #ifdef OPENBSD char poolname[32]; int c, pools, state; int psize; struct pool pool; size = sizeof(pools); psize = (size_t) sysconf(_SC_PAGESIZE); #endif #ifdef FREEBSD int nmbs, nmfs; struct mbstat mbstat; size = sizeof(mbstat); mib[0] = CTL_KERN; mib[1] = KERN_IPC; mib[2] = KIPC_MBSTAT; if (sysctl(mib, 3, &mbstat, &size, NULL, 0) < 0) { warn("sysctl: getting mbstat"); return (0); } size = sizeof(nmbs); mib[2] = KIPC_NMBCLUSTERS; if (sysctl(mib, 3, &nmbs, &size, NULL, 0) < 0) { warn("sysctl: getting nmbs"); return (0); } size = sizeof(nmfs); if (sysctlbyname("kern.ipc.nmbufs", &nmfs, &size, NULL, 0) < 0) { warn("sysctl: getting nmfs"); return (0); } totmem = (mbstat.m_mbufs * mbstat.m_msize) + (mbstat.m_clusters * mbstat.m_mclbytes); totused = ((nmbs * mbstat.m_mclbytes) + (nmfs * mbstat.m_msize)); totpct = (totmem * 100) / totused; totused = totused / 1024; #endif #ifdef OPENBSD /* * First we get the number of kernel pools. */ mib[0] = CTL_KERN; mib[1] = KERN_POOL; mib[2] = KERN_POOL_NPOOLS; if (sysctl(mib, 3, &pools, &size, NULL, 0) < 0) return (0); /* * Then we individually check each of them, looking for mbpl and mclpl. */ totpct = 0; state = 0; for (c = 1; pools; c++) { (void) memset(&poolname, 0x0, sizeof poolname); size = sizeof(struct pool); mib[0] = CTL_KERN; mib[1] = KERN_POOL; mib[2] = KERN_POOL_POOL; mib[3] = c; if (sysctl(mib, 4, &pool, &size, NULL, 0) < 0) return (0); pools--; size = sizeof poolname; mib[2] = KERN_POOL_NAME; if (sysctl(mib, 4, &poolname, &size, NULL, 0) < 0) return (0); if (!strncmp(poolname, "mbpl", strlen("mbpl"))) { bcopy(&pool, &mbpool, sizeof(struct pool)); state++; /* got mbpl */ } else { if (!strncmp(poolname, "mclpl", strlen("mclpl"))) { bcopy(&pool, &mclpool, sizeof(struct pool)); state++; /* got mclpl */ } } if (state == 2) break; /* found */ } totmem = (mbpool.pr_npages * psize) + (mclpool.pr_npages * psize); totused = (mbpool.pr_nget - mbpool.pr_nput) * mbpool.pr_size + (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size; totpct = (totmem == 0)? 0 : ((totused * 100)/totmem); #endif output("~R%u~w kbytes allocated to network, ~R%u~w in use (~R%d%~w%%)\n", totmem / 1024, totused / 1024, totpct); return (1); } /* * display_procs makes two calls to kvm_getprocs: the first asking for the * total number of processes running and the second asking for the processes * which are running as u_uid, which is given to display_procs as an argument. */ int d_procs(void) { int proc_total = 0; /* total number of processes */ int proc_user = 0; /* processes matching u_uid */ struct kinfo_proc *p_inf; /* ptr to get kvm_getprocs return value */ if ((p_inf = (struct kinfo_proc *) kvm_getprocs(kd, KERN_PROC_ALL, 0, &proc_total)) == NULL || (p_inf = (struct kinfo_proc *) kvm_getprocs(kd, KERN_PROC_UID, 0, &proc_user)) == NULL) return (0); output("~WProcesses: ~R%d~w effectively running with uid ~G%d~w, ~G%d~w total\n", proc_user, 0, proc_total); return (1); }