1 /* $NetBSD: icmp.c,v 1.5 2000/07/05 11:03:21 ad Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2000 Andrew Doran <ad@NetBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 #ifndef lint 32 __RCSID("$NetBSD: icmp.c,v 1.5 2000/07/05 11:03:21 ad Exp $"); 33 #endif /* not lint */ 34 35 #include <sys/param.h> 36 #include <sys/types.h> 37 #include <sys/socket.h> 38 #include <sys/sysctl.h> 39 40 #include <netinet/in.h> 41 #include <netinet/in_systm.h> 42 #include <netinet/ip.h> 43 #include <netinet/ip_icmp.h> 44 #include <netinet/icmp_var.h> 45 46 #include <stdlib.h> 47 #include <string.h> 48 #include <paths.h> 49 #include <nlist.h> 50 #include <kvm.h> 51 52 #include "systat.h" 53 #include "extern.h" 54 55 #define LHD(row, str) mvwprintw(wnd, row, 10, str) 56 #define RHD(row, str) mvwprintw(wnd, row, 45, str); 57 #define BD(row, str) LHD(row, str); RHD(row, str) 58 #define SHOW(stat, row, col) \ 59 mvwprintw(wnd, row, col, "%9llu", (unsigned long long)curstat.stat) 60 #define SHOW2(type, row) SHOW(icps_inhist[type], row, 0); \ 61 SHOW(icps_outhist[type], row, 35) 62 63 enum update { 64 UPDATE_TIME, 65 UPDATE_BOOT, 66 UPDATE_RUN, 67 }; 68 69 static enum update update = UPDATE_TIME; 70 static struct icmpstat curstat; 71 static struct icmpstat newstat; 72 static struct icmpstat oldstat; 73 74 static struct nlist namelist[] = { 75 { "_icmpstat" }, 76 { "" } 77 }; 78 79 WINDOW * 80 openicmp(void) 81 { 82 83 return (subwin(stdscr, LINES-5-1, 0, 5, 0)); 84 } 85 86 void 87 closeicmp(WINDOW *w) 88 { 89 90 if (w != NULL) { 91 wclear(w); 92 wrefresh(w); 93 delwin(w); 94 } 95 } 96 97 void 98 labelicmp(void) 99 { 100 101 wmove(wnd, 0, 0); wclrtoeol(wnd); 102 103 mvwprintw(wnd, 1, 0, "------------ ICMP input -----------"); 104 mvwprintw(wnd, 1, 36, "------------- ICMP output ---------------"); 105 106 mvwprintw(wnd, 8, 0, "---------- Input histogram --------"); 107 mvwprintw(wnd, 8, 36, "---------- Output histogram -------------"); 108 109 LHD(3, "with bad code"); 110 LHD(4, "with bad length"); 111 LHD(5, "with bad checksum"); 112 LHD(6, "with insufficient data"); 113 114 RHD(3, "errors generated"); 115 RHD(4, "suppressed - original too short"); 116 RHD(5, "suppressed - original was ICMP"); 117 RHD(6, "responses sent"); 118 119 BD(2, "total messages"); 120 BD(9, "echo response"); 121 BD(10, "echo request"); 122 BD(11, "destination unreachable"); 123 BD(12, "redirect"); 124 BD(13, "time-to-live exceeded"); 125 BD(14, "parameter problem"); 126 LHD(15, "router advertisement"); 127 RHD(15, "router solicitation"); 128 } 129 130 void 131 showicmp(void) 132 { 133 u_long tin, tout; 134 int i; 135 136 for (i = tin = tout = 0; i <= ICMP_MAXTYPE; i++) { 137 tin += curstat.icps_inhist[i]; 138 tout += curstat.icps_outhist[i]; 139 } 140 141 tin += curstat.icps_badcode + curstat.icps_badlen + 142 curstat.icps_checksum + curstat.icps_tooshort; 143 mvwprintw(wnd, 2, 0, "%9lu", tin); 144 mvwprintw(wnd, 2, 35, "%9lu", tout); 145 146 SHOW(icps_badcode, 3, 0); 147 SHOW(icps_badlen, 4, 0); 148 SHOW(icps_checksum, 5, 0); 149 SHOW(icps_tooshort, 6, 0); 150 SHOW(icps_error, 3, 35); 151 SHOW(icps_oldshort, 4, 35); 152 SHOW(icps_oldicmp, 5, 35); 153 SHOW(icps_reflect, 6, 35); 154 155 SHOW2(ICMP_ECHOREPLY, 9); 156 SHOW2(ICMP_ECHO, 10); 157 SHOW2(ICMP_UNREACH, 11); 158 SHOW2(ICMP_REDIRECT, 12); 159 SHOW2(ICMP_TIMXCEED, 13); 160 SHOW2(ICMP_PARAMPROB, 14); 161 SHOW(icps_inhist[ICMP_ROUTERADVERT], 15, 0); 162 SHOW(icps_outhist[ICMP_ROUTERSOLICIT], 15, 35); 163 } 164 165 int 166 initicmp(void) 167 { 168 169 if (namelist[0].n_type == 0) { 170 if (kvm_nlist(kd, namelist)) { 171 nlisterr(namelist); 172 return(0); 173 } 174 if (namelist[0].n_type == 0) { 175 error("No namelist"); 176 return(0); 177 } 178 } 179 180 return (1); 181 } 182 183 void 184 fetchicmp(void) 185 { 186 int i; 187 188 KREAD((void *)namelist[0].n_value, &newstat, sizeof(newstat)); 189 190 ADJINETCTR(curstat, oldstat, newstat, icps_badcode); 191 ADJINETCTR(curstat, oldstat, newstat, icps_badlen); 192 ADJINETCTR(curstat, oldstat, newstat, icps_checksum); 193 ADJINETCTR(curstat, oldstat, newstat, icps_tooshort); 194 ADJINETCTR(curstat, oldstat, newstat, icps_error); 195 ADJINETCTR(curstat, oldstat, newstat, icps_oldshort); 196 ADJINETCTR(curstat, oldstat, newstat, icps_oldicmp); 197 ADJINETCTR(curstat, oldstat, newstat, icps_reflect); 198 199 for (i = 0; i <= ICMP_MAXTYPE; i++) { 200 ADJINETCTR(curstat, oldstat, newstat, icps_inhist[i]); 201 ADJINETCTR(curstat, oldstat, newstat, icps_outhist[i]); 202 } 203 204 if (update == UPDATE_TIME) 205 memcpy(&oldstat, &newstat, sizeof(oldstat)); 206 } 207 208 void 209 icmp_boot(char *args) 210 { 211 212 memset(&oldstat, 0, sizeof(oldstat)); 213 update = UPDATE_BOOT; 214 } 215 216 void 217 icmp_run(char *args) 218 { 219 220 if (update != UPDATE_RUN) { 221 memcpy(&oldstat, &newstat, sizeof(oldstat)); 222 update = UPDATE_RUN; 223 } 224 } 225 226 void 227 icmp_time(char *args) 228 { 229 230 if (update != UPDATE_TIME) { 231 memcpy(&oldstat, &newstat, sizeof(oldstat)); 232 update = UPDATE_TIME; 233 } 234 } 235 236 void 237 icmp_zero(char *args) 238 { 239 240 if (update == UPDATE_RUN) 241 memcpy(&oldstat, &newstat, sizeof(oldstat)); 242 } 243