1/* 2 * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22#include <sys/cdefs.h> 23#ifndef lint 24#if 0 25static const char rcsid[] _U_ = 26 "@(#) Header: /tcpdump/master/tcpdump/print-sl.c,v 1.65 2005-04-06 21:32:42 mcr Exp (LBL)"; 27#else 28__RCSID("$NetBSD$"); 29#endif 30#endif 31 32#ifdef HAVE_CONFIG_H 33#include "config.h" 34#endif 35 36#include <tcpdump-stdinc.h> 37 38#include <pcap.h> 39#include <stdio.h> 40 41#include "interface.h" 42#include "addrtoname.h" 43#include "extract.h" /* must come after interface.h */ 44 45#include "ip.h" 46#include "tcp.h" 47#include "slip.h" 48#include "slcompress.h" 49 50static u_int lastlen[2][256]; 51static u_int lastconn = 255; 52 53static void sliplink_print(const u_char *, const struct ip *, u_int); 54static void compressed_sl_print(const u_char *, const struct ip *, u_int, int); 55 56u_int 57sl_if_print(const struct pcap_pkthdr *h, const u_char *p) 58{ 59 register u_int caplen = h->caplen; 60 register u_int length = h->len; 61 register const struct ip *ip; 62 63 if (caplen < SLIP_HDRLEN) { 64 printf("[|slip]"); 65 return (caplen); 66 } 67 68 length -= SLIP_HDRLEN; 69 70 ip = (struct ip *)(p + SLIP_HDRLEN); 71 72 if (eflag) 73 sliplink_print(p, ip, length); 74 75 switch (IP_V(ip)) { 76 case 4: 77 ip_print(gndo, (u_char *)ip, length); 78 break; 79#ifdef INET6 80 case 6: 81 ip6_print((u_char *)ip, length); 82 break; 83#endif 84 default: 85 printf ("ip v%d", IP_V(ip)); 86 } 87 88 return (SLIP_HDRLEN); 89} 90 91u_int 92sl_bsdos_if_print(const struct pcap_pkthdr *h, const u_char *p) 93{ 94 register u_int caplen = h->caplen; 95 register u_int length = h->len; 96 register const struct ip *ip; 97 98 if (caplen < SLIP_HDRLEN) { 99 printf("[|slip]"); 100 return (caplen); 101 } 102 103 length -= SLIP_HDRLEN; 104 105 ip = (struct ip *)(p + SLIP_HDRLEN); 106 107#ifdef notdef 108 if (eflag) 109 sliplink_print(p, ip, length); 110#endif 111 112 ip_print(gndo, (u_char *)ip, length); 113 114 return (SLIP_HDRLEN); 115} 116 117static void 118sliplink_print(register const u_char *p, register const struct ip *ip, 119 register u_int length) 120{ 121 int dir; 122 u_int hlen; 123 124 dir = p[SLX_DIR]; 125 putchar(dir == SLIPDIR_IN ? 'I' : 'O'); 126 putchar(' '); 127 128 if (nflag) { 129 /* XXX just dump the header */ 130 register int i; 131 132 for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) 133 printf("%02x.", p[i]); 134 printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]); 135 return; 136 } 137 switch (p[SLX_CHDR] & 0xf0) { 138 139 case TYPE_IP: 140 printf("ip %d: ", length + SLIP_HDRLEN); 141 break; 142 143 case TYPE_UNCOMPRESSED_TCP: 144 /* 145 * The connection id is stored in the IP protocol field. 146 * Get it from the link layer since sl_uncompress_tcp() 147 * has restored the IP header copy to IPPROTO_TCP. 148 */ 149 lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p; 150 hlen = IP_HL(ip); 151 hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]); 152 lastlen[dir][lastconn] = length - (hlen << 2); 153 printf("utcp %d: ", lastconn); 154 break; 155 156 default: 157 if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { 158 compressed_sl_print(&p[SLX_CHDR], ip, 159 length, dir); 160 printf(": "); 161 } else 162 printf("slip-%d!: ", p[SLX_CHDR]); 163 } 164} 165 166static const u_char * 167print_sl_change(const char *str, register const u_char *cp) 168{ 169 register u_int i; 170 171 if ((i = *cp++) == 0) { 172 i = EXTRACT_16BITS(cp); 173 cp += 2; 174 } 175 printf(" %s%d", str, i); 176 return (cp); 177} 178 179static const u_char * 180print_sl_winchange(register const u_char *cp) 181{ 182 register short i; 183 184 if ((i = *cp++) == 0) { 185 i = EXTRACT_16BITS(cp); 186 cp += 2; 187 } 188 if (i >= 0) 189 printf(" W+%d", i); 190 else 191 printf(" W%d", i); 192 return (cp); 193} 194 195static void 196compressed_sl_print(const u_char *chdr, const struct ip *ip, 197 u_int length, int dir) 198{ 199 register const u_char *cp = chdr; 200 register u_int flags, hlen; 201 202 flags = *cp++; 203 if (flags & NEW_C) { 204 lastconn = *cp++; 205 printf("ctcp %d", lastconn); 206 } else 207 printf("ctcp *"); 208 209 /* skip tcp checksum */ 210 cp += 2; 211 212 switch (flags & SPECIALS_MASK) { 213 case SPECIAL_I: 214 printf(" *SA+%d", lastlen[dir][lastconn]); 215 break; 216 217 case SPECIAL_D: 218 printf(" *S+%d", lastlen[dir][lastconn]); 219 break; 220 221 default: 222 if (flags & NEW_U) 223 cp = print_sl_change("U=", cp); 224 if (flags & NEW_W) 225 cp = print_sl_winchange(cp); 226 if (flags & NEW_A) 227 cp = print_sl_change("A+", cp); 228 if (flags & NEW_S) 229 cp = print_sl_change("S+", cp); 230 break; 231 } 232 if (flags & NEW_I) 233 cp = print_sl_change("I+", cp); 234 235 /* 236 * 'hlen' is the length of the uncompressed TCP/IP header (in words). 237 * 'cp - chdr' is the length of the compressed header. 238 * 'length - hlen' is the amount of data in the packet. 239 */ 240 hlen = IP_HL(ip); 241 hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]); 242 lastlen[dir][lastconn] = length - (hlen << 2); 243 printf(" %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr)); 244} 245