1 /* 2 * Copyright (c) 1995 Danny Gasparovski. 3 * Portions copyright (c) 2000 Kelly Price. 4 * 5 * Please read the file COPYRIGHT for the 6 * terms and conditions of the copyright. 7 */ 8 9 #include <slirp.h> 10 11 FILE *dfd = NULL; 12 #ifdef DEBUG 13 int dostats = 1; 14 #else 15 int dostats = 0; 16 #endif 17 int slirp_debug = 0; 18 19 extern char *strerror _P((int)); 20 21 /* Carry over one item from main.c so that the tty's restored. 22 * Only done when the tty being used is /dev/tty --RedWolf */ 23 extern struct termios slirp_tty_settings; 24 extern int slirp_tty_restore; 25 26 27 void 28 debug_init(file, dbg) 29 char *file; 30 int dbg; 31 { 32 /* Close the old debugging file */ 33 if (dfd) 34 fclose(dfd); 35 36 dfd = fopen(file,"w"); 37 if (dfd != NULL) { 38 #if 0 39 fprintf(dfd,"Slirp %s - Debugging Started.\n", SLIRP_VERSION); 40 #endif 41 fprintf(dfd,"Debugging Started level %i.\r\n",dbg); 42 fflush(dfd); 43 slirp_debug = dbg; 44 } else { 45 fprintf(stderr, "Error: Debugging file \"%s\" could not be opened: %s\r\n", 46 file, strerror(errno)); 47 } 48 } 49 50 /* 51 * Dump a packet in the same format as tcpdump -x 52 */ 53 #ifdef DEBUG 54 void 55 dump_packet(dat, n) 56 void *dat; 57 int n; 58 { 59 u_char *pptr = (u_char *)dat; 60 int j,k; 61 62 n /= 16; 63 n++; 64 DEBUG_MISC((dfd, "PACKET DUMPED: \n")); 65 for(j = 0; j < n; j++) { 66 for(k = 0; k < 6; k++) 67 DEBUG_MISC((dfd, "%02x ", *pptr++)); 68 DEBUG_MISC((dfd, "\n")); 69 fflush(dfd); 70 } 71 } 72 #endif 73 74 #if 0 75 /* 76 * Statistic routines 77 * 78 * These will print statistics to the screen, the debug file (dfd), or 79 * a buffer, depending on "type", so that the stats can be sent over 80 * the link as well. 81 */ 82 83 static void 84 ttystats(ttyp) 85 struct ttys *ttyp; 86 { 87 struct slirp_ifstats *is = &ttyp->ifstats; 88 char buff[512]; 89 90 lprint(" \r\n"); 91 92 if (IF_COMP & IF_COMPRESS) 93 strcpy(buff, "on"); 94 else if (IF_COMP & IF_NOCOMPRESS) 95 strcpy(buff, "off"); 96 else 97 strcpy(buff, "off (for now)"); 98 lprint("Unit %d:\r\n", ttyp->unit); 99 lprint(" using %s encapsulation (VJ compression is %s)\r\n", ( 100 #ifdef USE_PPP 101 ttyp->proto==PROTO_PPP?"PPP": 102 #endif 103 "SLIP"), buff); 104 lprint(" %d baudrate\r\n", ttyp->baud); 105 lprint(" interface is %s\r\n", ttyp->up?"up":"down"); 106 lprint(" using fd %d, guardian pid is %d\r\n", ttyp->fd, ttyp->pid); 107 #ifndef FULL_BOLT 108 lprint(" towrite is %d bytes\r\n", ttyp->towrite); 109 #endif 110 if (ttyp->zeros) 111 lprint(" %d zeros have been typed\r\n", ttyp->zeros); 112 else if (ttyp->ones) 113 lprint(" %d ones have been typed\r\n", ttyp->ones); 114 lprint("Interface stats:\r\n"); 115 lprint(" %6d output packets sent (%d bytes)\r\n", is->out_pkts, is->out_bytes); 116 lprint(" %6d output packets dropped (%d bytes)\r\n", is->out_errpkts, is->out_errbytes); 117 lprint(" %6d input packets received (%d bytes)\r\n", is->in_pkts, is->in_bytes); 118 lprint(" %6d input packets dropped (%d bytes)\r\n", is->in_errpkts, is->in_errbytes); 119 lprint(" %6d bad input packets\r\n", is->in_mbad); 120 } 121 122 static void 123 allttystats(void) 124 { 125 struct ttys *ttyp; 126 127 for (ttyp = ttys; ttyp; ttyp = ttyp->next) 128 ttystats(ttyp); 129 } 130 131 static void 132 ipstats(void) 133 { 134 lprint(" \r\n"); 135 136 lprint("IP stats:\r\n"); 137 lprint(" %6d total packets received (%d were unaligned)\r\n", 138 ipstat.ips_total, ipstat.ips_unaligned); 139 lprint(" %6d with incorrect version\r\n", ipstat.ips_badvers); 140 lprint(" %6d with bad header checksum\r\n", ipstat.ips_badsum); 141 lprint(" %6d with length too short (len < sizeof(iphdr))\r\n", ipstat.ips_tooshort); 142 lprint(" %6d with length too small (len < ip->len)\r\n", ipstat.ips_toosmall); 143 lprint(" %6d with bad header length\r\n", ipstat.ips_badhlen); 144 lprint(" %6d with bad packet length\r\n", ipstat.ips_badlen); 145 lprint(" %6d fragments received\r\n", ipstat.ips_fragments); 146 lprint(" %6d fragments dropped\r\n", ipstat.ips_fragdropped); 147 lprint(" %6d fragments timed out\r\n", ipstat.ips_fragtimeout); 148 lprint(" %6d packets reassembled ok\r\n", ipstat.ips_reassembled); 149 lprint(" %6d outgoing packets fragmented\r\n", ipstat.ips_fragmented); 150 lprint(" %6d total outgoing fragments\r\n", ipstat.ips_ofragments); 151 lprint(" %6d with bad protocol field\r\n", ipstat.ips_noproto); 152 lprint(" %6d total packets delivered\r\n", ipstat.ips_delivered); 153 } 154 155 static void 156 vjstats(void) 157 { 158 lprint(" \r\n"); 159 160 lprint("VJ compression stats:\r\n"); 161 162 lprint(" %6d outbound packets (%d compressed)\r\n", 163 comp_s.sls_packets, comp_s.sls_compressed); 164 lprint(" %6d searches for connection stats (%d misses)\r\n", 165 comp_s.sls_searches, comp_s.sls_misses); 166 lprint(" %6d inbound uncompressed packets\r\n", comp_s.sls_uncompressedin); 167 lprint(" %6d inbound compressed packets\r\n", comp_s.sls_compressedin); 168 lprint(" %6d inbound unknown type packets\r\n", comp_s.sls_errorin); 169 lprint(" %6d inbound packets tossed due to error\r\n", comp_s.sls_tossed); 170 } 171 172 static void 173 tcpstats(void) 174 { 175 lprint(" \r\n"); 176 177 lprint("TCP stats:\r\n"); 178 179 lprint(" %6d packets sent\r\n", tcpstat.tcps_sndtotal); 180 lprint(" %6d data packets (%d bytes)\r\n", 181 tcpstat.tcps_sndpack, tcpstat.tcps_sndbyte); 182 lprint(" %6d data packets retransmitted (%d bytes)\r\n", 183 tcpstat.tcps_sndrexmitpack, tcpstat.tcps_sndrexmitbyte); 184 lprint(" %6d ack-only packets (%d delayed)\r\n", 185 tcpstat.tcps_sndacks, tcpstat.tcps_delack); 186 lprint(" %6d URG only packets\r\n", tcpstat.tcps_sndurg); 187 lprint(" %6d window probe packets\r\n", tcpstat.tcps_sndprobe); 188 lprint(" %6d window update packets\r\n", tcpstat.tcps_sndwinup); 189 lprint(" %6d control (SYN/FIN/RST) packets\r\n", tcpstat.tcps_sndctrl); 190 lprint(" %6d times tcp_output did nothing\r\n", tcpstat.tcps_didnuttin); 191 192 lprint(" %6d packets received\r\n", tcpstat.tcps_rcvtotal); 193 lprint(" %6d acks (for %d bytes)\r\n", 194 tcpstat.tcps_rcvackpack, tcpstat.tcps_rcvackbyte); 195 lprint(" %6d duplicate acks\r\n", tcpstat.tcps_rcvdupack); 196 lprint(" %6d acks for unsent data\r\n", tcpstat.tcps_rcvacktoomuch); 197 lprint(" %6d packets received in sequence (%d bytes)\r\n", 198 tcpstat.tcps_rcvpack, tcpstat.tcps_rcvbyte); 199 lprint(" %6d completely duplicate packets (%d bytes)\r\n", 200 tcpstat.tcps_rcvduppack, tcpstat.tcps_rcvdupbyte); 201 202 lprint(" %6d packets with some duplicate data (%d bytes duped)\r\n", 203 tcpstat.tcps_rcvpartduppack, tcpstat.tcps_rcvpartdupbyte); 204 lprint(" %6d out-of-order packets (%d bytes)\r\n", 205 tcpstat.tcps_rcvoopack, tcpstat.tcps_rcvoobyte); 206 lprint(" %6d packets of data after window (%d bytes)\r\n", 207 tcpstat.tcps_rcvpackafterwin, tcpstat.tcps_rcvbyteafterwin); 208 lprint(" %6d window probes\r\n", tcpstat.tcps_rcvwinprobe); 209 lprint(" %6d window update packets\r\n", tcpstat.tcps_rcvwinupd); 210 lprint(" %6d packets received after close\r\n", tcpstat.tcps_rcvafterclose); 211 lprint(" %6d discarded for bad checksums\r\n", tcpstat.tcps_rcvbadsum); 212 lprint(" %6d discarded for bad header offset fields\r\n", 213 tcpstat.tcps_rcvbadoff); 214 215 lprint(" %6d connection requests\r\n", tcpstat.tcps_connattempt); 216 lprint(" %6d connection accepts\r\n", tcpstat.tcps_accepts); 217 lprint(" %6d connections established (including accepts)\r\n", tcpstat.tcps_connects); 218 lprint(" %6d connections closed (including %d drop)\r\n", 219 tcpstat.tcps_closed, tcpstat.tcps_drops); 220 lprint(" %6d embryonic connections dropped\r\n", tcpstat.tcps_conndrops); 221 lprint(" %6d segments we tried to get rtt (%d succeeded)\r\n", 222 tcpstat.tcps_segstimed, tcpstat.tcps_rttupdated); 223 lprint(" %6d retransmit timeouts\r\n", tcpstat.tcps_rexmttimeo); 224 lprint(" %6d connections dropped by rxmt timeout\r\n", 225 tcpstat.tcps_timeoutdrop); 226 lprint(" %6d persist timeouts\r\n", tcpstat.tcps_persisttimeo); 227 lprint(" %6d keepalive timeouts\r\n", tcpstat.tcps_keeptimeo); 228 lprint(" %6d keepalive probes sent\r\n", tcpstat.tcps_keepprobe); 229 lprint(" %6d connections dropped by keepalive\r\n", tcpstat.tcps_keepdrops); 230 lprint(" %6d correct ACK header predictions\r\n", tcpstat.tcps_predack); 231 lprint(" %6d correct data packet header predictions\n", tcpstat.tcps_preddat); 232 lprint(" %6d TCP cache misses\r\n", tcpstat.tcps_socachemiss); 233 234 235 /* lprint(" Packets received too short: %d\r\n", tcpstat.tcps_rcvshort); */ 236 /* lprint(" Segments dropped due to PAWS: %d\r\n", tcpstat.tcps_pawsdrop); */ 237 238 } 239 240 static void 241 udpstats(void) 242 { 243 lprint(" \r\n"); 244 245 lprint("UDP stats:\r\n"); 246 lprint(" %6d datagrams received\r\n", udpstat.udps_ipackets); 247 lprint(" %6d with packets shorter than header\r\n", udpstat.udps_hdrops); 248 lprint(" %6d with bad checksums\r\n", udpstat.udps_badsum); 249 lprint(" %6d with data length larger than packet\r\n", udpstat.udps_badlen); 250 lprint(" %6d UDP socket cache misses\r\n", udpstat.udpps_pcbcachemiss); 251 lprint(" %6d datagrams sent\r\n", udpstat.udps_opackets); 252 } 253 254 static void 255 icmpstats(void) 256 { 257 lprint(" \r\n"); 258 lprint("ICMP stats:\r\n"); 259 lprint(" %6d ICMP packets received\r\n", icmpstat.icps_received); 260 lprint(" %6d were too short\r\n", icmpstat.icps_tooshort); 261 lprint(" %6d with bad checksums\r\n", icmpstat.icps_checksum); 262 lprint(" %6d with type not supported\r\n", icmpstat.icps_notsupp); 263 lprint(" %6d with bad type feilds\r\n", icmpstat.icps_badtype); 264 lprint(" %6d ICMP packets sent in reply\r\n", icmpstat.icps_reflect); 265 } 266 267 static void 268 sockstats(void) 269 { 270 char buff[256]; 271 int n; 272 struct socket *so; 273 274 lprint(" \r\n"); 275 276 lprint( 277 "Proto[state] Sock Local Address, Port Remote Address, Port RecvQ SendQ\r\n"); 278 279 for (so = tcb.so_next; so != &tcb; so = so->so_next) { 280 281 n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE"); 282 while (n < 17) 283 buff[n++] = ' '; 284 buff[17] = 0; 285 lprint("%s %3d %15s %5d ", 286 buff, so->s, 287 inet_iptostr(so->so_laddr_ip), so->so_laddr_port); 288 lprint("%15s %5d %5d %5d\r\n", 289 inet_iptostr(so->so_faddr_ip), so->so_faddr_port, 290 so->so_rcv.sb_cc, so->so_snd.sb_cc); 291 } 292 293 for (so = udb.so_next; so != &udb; so = so->so_next) { 294 295 n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000); 296 while (n < 17) 297 buff[n++] = ' '; 298 buff[17] = 0; 299 lprint("%s %3d %15s %5d ", 300 buff, so->s, 301 inet_iptostr(so->so_laddr_ip), so->so_laddr_port); 302 lprint("%15s %5d %5d %5d\r\n", 303 inet_iptostr(so->so_faddr_ip), so->so_faddr_port, 304 so->so_rcv.sb_cc, so->so_snd.sb_cc); 305 } 306 } 307 #endif 308 309 #if 0 310 void 311 slirp_exit(exit_status) 312 int exit_status; 313 { 314 struct ttys *ttyp; 315 316 DEBUG_CALL("slirp_exit"); 317 DEBUG_ARG("exit_status = %d", exit_status); 318 319 if (dostats) { 320 lprint_print = (int (*) _P((void *, const char *, va_list)))vfprintf; 321 if (!dfd) 322 debug_init("slirp_stats", 0xf); 323 lprint_arg = (char **)&dfd; 324 325 ipstats(); 326 tcpstats(); 327 udpstats(); 328 icmpstats(); 329 mbufstats(); 330 sockstats(); 331 allttystats(); 332 vjstats(); 333 } 334 335 for (ttyp = ttys; ttyp; ttyp = ttyp->next) 336 tty_detached(ttyp, 1); 337 338 if (slirp_forked) { 339 /* Menendez time */ 340 if (kill(getppid(), SIGQUIT) < 0) 341 lprint("Couldn't kill parent process %ld!\n", 342 (long) getppid()); 343 } 344 345 /* Restore the terminal if we gotta */ 346 if(slirp_tty_restore) 347 tcsetattr(0,TCSANOW, &slirp_tty_settings); /* NOW DAMMIT! */ 348 exit(exit_status); 349 } 350 #endif 351