1 /* 2 * Copyright (c) 1983, 1988, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)if.c 8.2 (Berkeley) 02/21/94"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 #include <sys/protosw.h> 14 #include <sys/socket.h> 15 16 #include <net/if.h> 17 #include <net/if_dl.h> 18 #include <netinet/in.h> 19 #include <netinet/in_var.h> 20 #include <netns/ns.h> 21 #include <netns/ns_if.h> 22 #include <netiso/iso.h> 23 #include <netiso/iso_var.h> 24 #include <arpa/inet.h> 25 26 #include <signal.h> 27 #include <stdio.h> 28 #include <string.h> 29 #include <unistd.h> 30 31 #include "netstat.h" 32 33 #define YES 1 34 #define NO 0 35 36 static void sidewaysintpr __P((u_int, u_long)); 37 static void catchalarm __P((int)); 38 39 /* 40 * Print a description of the network interfaces. 41 */ 42 void 43 intpr(interval, ifnetaddr) 44 int interval; 45 u_long ifnetaddr; 46 { 47 struct ifnet ifnet; 48 union { 49 struct ifaddr ifa; 50 struct in_ifaddr in; 51 struct ns_ifaddr ns; 52 struct iso_ifaddr iso; 53 } ifaddr; 54 u_long ifaddraddr; 55 struct sockaddr *sa; 56 char name[16]; 57 58 if (ifnetaddr == 0) { 59 printf("ifnet: symbol not defined\n"); 60 return; 61 } 62 if (interval) { 63 sidewaysintpr((unsigned)interval, ifnetaddr); 64 return; 65 } 66 if (kread(ifnetaddr, (char *)&ifnetaddr, sizeof ifnetaddr)) 67 return; 68 printf("%-5.5s %-5.5s %-11.11s %-15.15s %8.8s %5.5s %8.8s %5.5s", 69 "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs", 70 "Opkts", "Oerrs"); 71 printf(" %5s", "Coll"); 72 if (tflag) 73 printf(" %s", "Time"); 74 if (dflag) 75 printf(" %s", "Drop"); 76 putchar('\n'); 77 ifaddraddr = 0; 78 while (ifnetaddr || ifaddraddr) { 79 struct sockaddr_in *sin; 80 register char *cp; 81 int n, m; 82 83 if (ifaddraddr == 0) { 84 if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) || 85 kread((u_long)ifnet.if_name, name, 16)) 86 return; 87 name[15] = '\0'; 88 ifnetaddr = (u_long)ifnet.if_next; 89 if (interface != 0 && (strcmp(name, interface) != 0 || 90 unit != ifnet.if_unit)) 91 continue; 92 cp = index(name, '\0'); 93 cp += sprintf(cp, "%d", ifnet.if_unit); 94 if ((ifnet.if_flags&IFF_UP) == 0) 95 *cp++ = '*'; 96 *cp = '\0'; 97 ifaddraddr = (u_long)ifnet.if_addrlist; 98 } 99 printf("%-5.5s %-5d ", name, ifnet.if_mtu); 100 if (ifaddraddr == 0) { 101 printf("%-11.11s ", "none"); 102 printf("%-15.15s ", "none"); 103 } else { 104 if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { 105 ifaddraddr = 0; 106 continue; 107 } 108 #define CP(x) ((char *)(x)) 109 cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + 110 CP(&ifaddr); sa = (struct sockaddr *)cp; 111 switch (sa->sa_family) { 112 case AF_UNSPEC: 113 printf("%-11.11s ", "none"); 114 printf("%-15.15s ", "none"); 115 break; 116 case AF_INET: 117 sin = (struct sockaddr_in *)sa; 118 #ifdef notdef 119 /* can't use inet_makeaddr because kernel 120 * keeps nets unshifted. 121 */ 122 in = inet_makeaddr(ifaddr.in.ia_subnet, 123 INADDR_ANY); 124 printf("%-11.11s ", netname(in.s_addr, 125 ifaddr.in.ia_subnetmask)); 126 #else 127 printf("%-11.11s ", 128 netname(htonl(ifaddr.in.ia_subnet), 129 ifaddr.in.ia_subnetmask)); 130 #endif 131 printf("%-15.15s ", 132 routename(sin->sin_addr.s_addr)); 133 break; 134 case AF_NS: 135 { 136 struct sockaddr_ns *sns = 137 (struct sockaddr_ns *)sa; 138 u_long net; 139 char netnum[8]; 140 141 *(union ns_net *) &net = sns->sns_addr.x_net; 142 sprintf(netnum, "%lxH", ntohl(net)); 143 upHex(netnum); 144 printf("ns:%-8s ", netnum); 145 printf("%-15s ", 146 ns_phost((struct sockaddr *)sns)); 147 } 148 break; 149 case AF_LINK: 150 { 151 struct sockaddr_dl *sdl = 152 (struct sockaddr_dl *)sa; 153 cp = (char *)LLADDR(sdl); 154 n = sdl->sdl_alen; 155 } 156 m = printf("<Link>"); 157 goto hexprint; 158 default: 159 m = printf("(%d)", sa->sa_family); 160 for (cp = sa->sa_len + (char *)sa; 161 --cp > sa->sa_data && (*cp == 0);) {} 162 n = cp - sa->sa_data + 1; 163 cp = sa->sa_data; 164 hexprint: 165 while (--n >= 0) 166 m += printf("%x%c", *cp++ & 0xff, 167 n > 0 ? '.' : ' '); 168 m = 28 - m; 169 while (m-- > 0) 170 putchar(' '); 171 break; 172 } 173 ifaddraddr = (u_long)ifaddr.ifa.ifa_next; 174 } 175 printf("%8d %5d %8d %5d %5d", 176 ifnet.if_ipackets, ifnet.if_ierrors, 177 ifnet.if_opackets, ifnet.if_oerrors, 178 ifnet.if_collisions); 179 if (tflag) 180 printf(" %3d", ifnet.if_timer); 181 if (dflag) 182 printf(" %3d", ifnet.if_snd.ifq_drops); 183 putchar('\n'); 184 } 185 } 186 187 #define MAXIF 10 188 struct iftot { 189 char ift_name[16]; /* interface name */ 190 int ift_ip; /* input packets */ 191 int ift_ie; /* input errors */ 192 int ift_op; /* output packets */ 193 int ift_oe; /* output errors */ 194 int ift_co; /* collisions */ 195 int ift_dr; /* drops */ 196 } iftot[MAXIF]; 197 198 u_char signalled; /* set if alarm goes off "early" */ 199 200 /* 201 * Print a running summary of interface statistics. 202 * Repeat display every interval seconds, showing statistics 203 * collected over that interval. Assumes that interval is non-zero. 204 * First line printed at top of screen is always cumulative. 205 */ 206 static void 207 sidewaysintpr(interval, off) 208 unsigned interval; 209 u_long off; 210 { 211 struct ifnet ifnet; 212 u_long firstifnet; 213 register struct iftot *ip, *total; 214 register int line; 215 struct iftot *lastif, *sum, *interesting; 216 int oldmask; 217 218 if (kread(off, (char *)&firstifnet, sizeof (u_long))) 219 return; 220 lastif = iftot; 221 sum = iftot + MAXIF - 1; 222 total = sum - 1; 223 interesting = iftot; 224 for (off = firstifnet, ip = iftot; off;) { 225 char *cp; 226 227 if (kread(off, (char *)&ifnet, sizeof ifnet)) 228 break; 229 ip->ift_name[0] = '('; 230 if (kread((u_long)ifnet.if_name, ip->ift_name + 1, 15)) 231 break; 232 if (interface && strcmp(ip->ift_name + 1, interface) == 0 && 233 unit == ifnet.if_unit) 234 interesting = ip; 235 ip->ift_name[15] = '\0'; 236 cp = index(ip->ift_name, '\0'); 237 sprintf(cp, "%d)", ifnet.if_unit); 238 ip++; 239 if (ip >= iftot + MAXIF - 2) 240 break; 241 off = (u_long) ifnet.if_next; 242 } 243 lastif = ip; 244 245 (void)signal(SIGALRM, catchalarm); 246 signalled = NO; 247 (void)alarm(interval); 248 banner: 249 printf(" input %-6.6s output ", interesting->ift_name); 250 if (lastif - iftot > 0) { 251 if (dflag) 252 printf(" "); 253 printf(" input (Total) output"); 254 } 255 for (ip = iftot; ip < iftot + MAXIF; ip++) { 256 ip->ift_ip = 0; 257 ip->ift_ie = 0; 258 ip->ift_op = 0; 259 ip->ift_oe = 0; 260 ip->ift_co = 0; 261 ip->ift_dr = 0; 262 } 263 putchar('\n'); 264 printf("%8.8s %5.5s %8.8s %5.5s %5.5s ", 265 "packets", "errs", "packets", "errs", "colls"); 266 if (dflag) 267 printf("%5.5s ", "drops"); 268 if (lastif - iftot > 0) 269 printf(" %8.8s %5.5s %8.8s %5.5s %5.5s", 270 "packets", "errs", "packets", "errs", "colls"); 271 if (dflag) 272 printf(" %5.5s", "drops"); 273 putchar('\n'); 274 fflush(stdout); 275 line = 0; 276 loop: 277 sum->ift_ip = 0; 278 sum->ift_ie = 0; 279 sum->ift_op = 0; 280 sum->ift_oe = 0; 281 sum->ift_co = 0; 282 sum->ift_dr = 0; 283 for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) { 284 if (kread(off, (char *)&ifnet, sizeof ifnet)) { 285 off = 0; 286 continue; 287 } 288 if (ip == interesting) { 289 printf("%8d %5d %8d %5d %5d", 290 ifnet.if_ipackets - ip->ift_ip, 291 ifnet.if_ierrors - ip->ift_ie, 292 ifnet.if_opackets - ip->ift_op, 293 ifnet.if_oerrors - ip->ift_oe, 294 ifnet.if_collisions - ip->ift_co); 295 if (dflag) 296 printf(" %5d", 297 ifnet.if_snd.ifq_drops - ip->ift_dr); 298 } 299 ip->ift_ip = ifnet.if_ipackets; 300 ip->ift_ie = ifnet.if_ierrors; 301 ip->ift_op = ifnet.if_opackets; 302 ip->ift_oe = ifnet.if_oerrors; 303 ip->ift_co = ifnet.if_collisions; 304 ip->ift_dr = ifnet.if_snd.ifq_drops; 305 sum->ift_ip += ip->ift_ip; 306 sum->ift_ie += ip->ift_ie; 307 sum->ift_op += ip->ift_op; 308 sum->ift_oe += ip->ift_oe; 309 sum->ift_co += ip->ift_co; 310 sum->ift_dr += ip->ift_dr; 311 off = (u_long) ifnet.if_next; 312 } 313 if (lastif - iftot > 0) { 314 printf(" %8d %5d %8d %5d %5d", 315 sum->ift_ip - total->ift_ip, 316 sum->ift_ie - total->ift_ie, 317 sum->ift_op - total->ift_op, 318 sum->ift_oe - total->ift_oe, 319 sum->ift_co - total->ift_co); 320 if (dflag) 321 printf(" %5d", sum->ift_dr - total->ift_dr); 322 } 323 *total = *sum; 324 putchar('\n'); 325 fflush(stdout); 326 line++; 327 oldmask = sigblock(sigmask(SIGALRM)); 328 if (! signalled) { 329 sigpause(0); 330 } 331 sigsetmask(oldmask); 332 signalled = NO; 333 (void)alarm(interval); 334 if (line == 21) 335 goto banner; 336 goto loop; 337 /*NOTREACHED*/ 338 } 339 340 /* 341 * Called if an interval expires before sidewaysintpr has completed a loop. 342 * Sets a flag to not wait for the alarm. 343 */ 344 static void 345 catchalarm(signo) 346 int signo; 347 { 348 signalled = YES; 349 } 350