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