1 /* $OpenBSD: print-sl.c,v 1.13 2007/10/07 16:41:05 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24 #ifndef lint 25 static const char rcsid[] = 26 "@(#) $Id: print-sl.c,v 1.13 2007/10/07 16:41:05 deraadt Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_NET_SLIP_H 30 #include <sys/param.h> 31 #include <sys/time.h> 32 #include <sys/timeb.h> 33 #include <sys/file.h> 34 #include <sys/ioctl.h> 35 #include <sys/mbuf.h> 36 #include <sys/socket.h> 37 38 struct rtentry; 39 #include <net/if.h> 40 41 #include <netinet/in.h> 42 #include <netinet/in_systm.h> 43 #include <netinet/ip.h> 44 #include <netinet/if_ether.h> 45 #include <netinet/udp.h> 46 #include <netinet/tcp.h> 47 48 #include <net/slcompress.h> 49 #include <net/slip.h> 50 51 #include <ctype.h> 52 #include <netdb.h> 53 #include <pcap.h> 54 #include <stdio.h> 55 56 #include "interface.h" 57 #include "addrtoname.h" 58 #include "extract.h" /* must come after interface.h */ 59 60 static u_int lastlen[2][256]; 61 static u_int lastconn = 255; 62 63 static void sliplink_print(const u_char *, const struct ip *, u_int); 64 static void compressed_sl_print(const u_char *, const struct ip *, u_int, int); 65 66 /* XXX BSD/OS 2.1 compatibility */ 67 #if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR) 68 #define SLIP_HDRLEN SLC_BPFHDR 69 #define SLX_DIR 0 70 #define SLX_CHDR (SLC_BPFHDRLEN - 1) 71 #define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN) 72 #endif 73 74 /* XXX needs more hacking to work right */ 75 76 void 77 sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 78 { 79 register u_int caplen = h->caplen; 80 register u_int length = h->len; 81 register const struct ip *ip; 82 83 ts_print(&h->ts); 84 85 if (caplen < SLIP_HDRLEN) { 86 printf("[|slip]"); 87 goto out; 88 } 89 /* 90 * Some printers want to get back at the link level addresses, 91 * and/or check that they're not walking off the end of the packet. 92 * Rather than pass them all the way down, we set these globals. 93 */ 94 packetp = p; 95 snapend = p + caplen; 96 97 length -= SLIP_HDRLEN; 98 99 ip = (struct ip *)(p + SLIP_HDRLEN); 100 101 if (eflag) 102 sliplink_print(p, ip, length); 103 104 switch (ip->ip_v) { 105 case 4: 106 ip_print((u_char *)ip, length); 107 break; 108 #ifdef INET6 109 case 6: 110 ip6_print((u_char *)ip, length); 111 break; 112 #endif 113 default: 114 printf ("ip v%d", ip->ip_v); 115 } 116 117 if (xflag) 118 default_print((u_char *)ip, caplen - SLIP_HDRLEN); 119 out: 120 putchar('\n'); 121 } 122 123 124 void 125 sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 126 { 127 register u_int caplen = h->caplen; 128 register u_int length = h->len; 129 register const struct ip *ip; 130 131 ts_print(&h->ts); 132 133 if (caplen < SLIP_HDRLEN) { 134 printf("[|slip]"); 135 goto out; 136 } 137 /* 138 * Some printers want to get back at the link level addresses, 139 * and/or check that they're not walking off the end of the packet. 140 * Rather than pass them all the way down, we set these globals. 141 */ 142 packetp = p; 143 snapend = p + caplen; 144 145 length -= SLIP_HDRLEN; 146 147 ip = (struct ip *)(p + SLIP_HDRLEN); 148 149 #ifdef notdef 150 if (eflag) 151 sliplink_print(p, ip, length); 152 #endif 153 154 ip_print((u_char *)ip, length); 155 156 if (xflag) 157 default_print((u_char *)ip, caplen - SLIP_HDRLEN); 158 out: 159 putchar('\n'); 160 } 161 162 static void 163 sliplink_print(register const u_char *p, register const struct ip *ip, 164 register u_int length) 165 { 166 int dir; 167 u_int hlen; 168 169 dir = p[SLX_DIR]; 170 putchar(dir == SLIPDIR_IN ? 'I' : 'O'); 171 putchar(' '); 172 173 if (nflag) { 174 /* XXX just dump the header */ 175 register int i; 176 177 for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) 178 printf("%02x.", p[i]); 179 printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]); 180 return; 181 } 182 switch (p[SLX_CHDR] & 0xf0) { 183 184 case TYPE_IP: 185 printf("ip %d: ", length + SLIP_HDRLEN); 186 break; 187 188 case TYPE_UNCOMPRESSED_TCP: 189 /* 190 * The connection id is stored in the IP protocol field. 191 * Get it from the link layer since sl_uncompress_tcp() 192 * has restored the IP header copy to IPPROTO_TCP. 193 */ 194 lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p; 195 hlen = ip->ip_hl; 196 hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off; 197 lastlen[dir][lastconn] = length - (hlen << 2); 198 printf("utcp %d: ", lastconn); 199 break; 200 201 default: 202 if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { 203 compressed_sl_print(&p[SLX_CHDR], ip, 204 length, dir); 205 printf(": "); 206 } else 207 printf("slip-%d!: ", p[SLX_CHDR]); 208 } 209 } 210 211 static const u_char * 212 print_sl_change(const char *str, register const u_char *cp) 213 { 214 register u_int i; 215 216 if ((i = *cp++) == 0) { 217 i = EXTRACT_16BITS(cp); 218 cp += 2; 219 } 220 printf(" %s%d", str, i); 221 return (cp); 222 } 223 224 static const u_char * 225 print_sl_winchange(register const u_char *cp) 226 { 227 register short i; 228 229 if ((i = *cp++) == 0) { 230 i = EXTRACT_16BITS(cp); 231 cp += 2; 232 } 233 if (i >= 0) 234 printf(" W+%d", i); 235 else 236 printf(" W%d", i); 237 return (cp); 238 } 239 240 static void 241 compressed_sl_print(const u_char *chdr, const struct ip *ip, 242 u_int length, int dir) 243 { 244 register const u_char *cp = chdr; 245 register u_int flags, hlen; 246 247 flags = *cp++; 248 if (flags & NEW_C) { 249 lastconn = *cp++; 250 printf("ctcp %d", lastconn); 251 } else 252 printf("ctcp *"); 253 254 /* skip tcp checksum */ 255 cp += 2; 256 257 switch (flags & SPECIALS_MASK) { 258 case SPECIAL_I: 259 printf(" *SA+%d", lastlen[dir][lastconn]); 260 break; 261 262 case SPECIAL_D: 263 printf(" *S+%d", lastlen[dir][lastconn]); 264 break; 265 266 default: 267 if (flags & NEW_U) 268 cp = print_sl_change("U=", cp); 269 if (flags & NEW_W) 270 cp = print_sl_winchange(cp); 271 if (flags & NEW_A) 272 cp = print_sl_change("A+", cp); 273 if (flags & NEW_S) 274 cp = print_sl_change("S+", cp); 275 break; 276 } 277 if (flags & NEW_I) 278 cp = print_sl_change("I+", cp); 279 280 /* 281 * 'hlen' is the length of the uncompressed TCP/IP header (in words). 282 * 'cp - chdr' is the length of the compressed header. 283 * 'length - hlen' is the amount of data in the packet. 284 */ 285 hlen = ip->ip_hl; 286 hlen += ((struct tcphdr *)&((int32_t *)ip)[hlen])->th_off; 287 lastlen[dir][lastconn] = length - (hlen << 2); 288 printf(" %d (%d)", lastlen[dir][lastconn], (int)(cp - chdr)); 289 } 290 #else 291 #include <sys/types.h> 292 #include <sys/time.h> 293 294 #include <pcap.h> 295 #include <stdio.h> 296 297 #include "interface.h" 298 299 void 300 sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 301 { 302 303 error("not configured for slip"); 304 /* NOTREACHED */ 305 } 306 307 void 308 sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) 309 { 310 311 error("not configured for slip"); 312 /* NOTREACHED */ 313 } 314 #endif 315