1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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 #ifndef lint 23 static const char rcsid[] = 24 "@(#) $Header: /tcpdump/master/tcpdump/print-pppoe.c,v 1.12 2000/10/09 02:59:40 guy Exp $ (LBL)"; 25 #endif 26 27 #ifdef HAVE_CONFIG_H 28 #include "config.h" 29 #endif 30 31 #include <sys/param.h> 32 #include <sys/time.h> 33 #include <sys/socket.h> 34 35 #include <netinet/in.h> 36 37 #include <stdio.h> 38 #include <string.h> 39 40 #include "interface.h" 41 #include "addrtoname.h" 42 #include "ppp.h" 43 #include "ethertype.h" 44 #include "ether.h" 45 #include "extract.h" /* must come after interface.h */ 46 47 /* Codes */ 48 enum { 49 PPPOE_PADI = 0x09, 50 PPPOE_PADO = 0x07, 51 PPPOE_PADR = 0x19, 52 PPPOE_PADS = 0x65, 53 PPPOE_PADT = 0xa7 54 }; 55 56 static struct tok pppoecode2str[] = { 57 { PPPOE_PADI, "PADI"}, 58 { PPPOE_PADO, "PADO"}, 59 { PPPOE_PADR, "PADR"}, 60 { PPPOE_PADS, "PADS"}, 61 { PPPOE_PADT, "PADT"}, 62 { 0, ""}, /* PPP Data */ 63 { 0, NULL } 64 }; 65 66 /* Tags */ 67 enum { 68 PPPOE_EOL = 0, 69 PPPOE_SERVICE_NAME = 0x0101, 70 PPPOE_AC_NAME = 0x0102, 71 PPPOE_HOST_UNIQ = 0x0103, 72 PPPOE_AC_COOKIE = 0x0104, 73 PPPOE_VENDOR = 0x0105, 74 PPPOE_RELAY_SID = 0x0110, 75 PPPOE_SERVICE_NAME_ERROR = 0x0201, 76 PPPOE_AC_SYSTEM_ERROR = 0x0202, 77 PPPOE_GENERIC_ERROR = 0x0203 78 }; 79 80 static struct tok pppoetag2str[] = { 81 { PPPOE_EOL, "EOL"}, 82 { PPPOE_SERVICE_NAME, "Service-Name" }, 83 { PPPOE_AC_NAME, "AC-Name" }, 84 { PPPOE_HOST_UNIQ, "Host-Uniq" }, 85 { PPPOE_AC_COOKIE, "AC-Cookie" }, 86 { PPPOE_VENDOR, "Vendor-Specific" }, 87 { PPPOE_RELAY_SID, "Relay-Session-ID" }, 88 { PPPOE_SERVICE_NAME_ERROR, "Service-Name-Error" }, 89 { PPPOE_AC_SYSTEM_ERROR, "AC-System-Error" }, 90 { PPPOE_GENERIC_ERROR, "Generic-Error" }, 91 { 0, NULL} 92 }; 93 94 #define PPPOE_HDRLEN 6 95 96 void 97 pppoe_print(register const u_char *bp, u_int length) 98 { 99 register const struct ether_header *eh; 100 register u_short pppoe_ver, pppoe_type, pppoe_code, pppoe_sessionid, pppoe_length; 101 const u_char *pppoe_packet, *pppoe_payload; 102 103 eh = (struct ether_header *)packetp; 104 pppoe_packet = packetp+ETHER_HDRLEN; 105 if (pppoe_packet > snapend) { 106 printf("[|pppoe]"); 107 return; 108 } 109 110 pppoe_ver = (pppoe_packet[0]&0xF0)>>4; 111 pppoe_type = (pppoe_packet[0]&0x0F); 112 pppoe_code = (pppoe_packet[1]); 113 pppoe_sessionid = (EXTRACT_16BITS(pppoe_packet+2)); 114 pppoe_length = (EXTRACT_16BITS(pppoe_packet+4)); 115 pppoe_payload = pppoe_packet+6; 116 117 if (snapend < pppoe_payload) { 118 printf(" truncated PPPoE"); 119 return; 120 } 121 122 if (pppoe_ver != 1) { 123 printf(" [ver %d]",pppoe_ver); 124 } 125 if (pppoe_type != 1) { 126 printf(" [type %d]",pppoe_type); 127 } 128 129 printf("PPPoE %s", tok2str(pppoecode2str, "PAD-%x", pppoe_code)); 130 if (pppoe_code == PPPOE_PADI && pppoe_length > 1484-PPPOE_HDRLEN) { 131 printf(" [len %d!]",pppoe_length); 132 } 133 if (pppoe_sessionid) { 134 printf(" [ses 0x%x]",pppoe_sessionid); 135 } 136 137 if (pppoe_payload + pppoe_length < snapend) { 138 /* 139 printf(" [length %d (%d extra bytes)]", pppoe_length, snapend-pppoe_payload-pppoe_length); 140 { 141 const u_char *x = pppoe_payload+pppoe_length; 142 default_print(x, snapend - x); 143 } 144 */ 145 snapend = pppoe_payload+pppoe_length; 146 } 147 148 149 if (pppoe_code) { 150 /* PPP session packets don't contain tags */ 151 u_short tag_type = 0xffff, tag_len; 152 const u_char *p = pppoe_payload; 153 154 /* loop invariant: 155 p points to next tag, 156 tag_type is previous tag or 0xffff for first iteration 157 */ 158 while (tag_type && 159 p+4 < pppoe_payload + length && 160 p+4 < snapend) { 161 tag_type = EXTRACT_16BITS(p); 162 tag_len = EXTRACT_16BITS(p+2); 163 p += 4; 164 /* p points to tag_value */ 165 166 if (tag_len) { 167 int isascii = 1; 168 const u_char *v = p; 169 170 for (v=p; v<p+tag_len; v++) 171 if (*v >= 127 || *v < 32) { 172 isascii = 0; 173 break; 174 } 175 176 /* TODO print UTF8 decoded text */ 177 if (isascii) 178 printf(" [%s \"%*.*s\"]", 179 tok2str(pppoetag2str, "TAG-0x%x", tag_type), 180 tag_len < 80 ? tag_len : 80, 181 tag_len < 80 ? tag_len : 80, 182 p 183 ); 184 else 185 printf(" [%s UTF8]", tok2str(pppoetag2str, "TAG-0x%x", tag_type)); 186 } else 187 printf(" [%s]", tok2str(pppoetag2str, "TAG-0x%x", tag_type)); 188 189 p += tag_len; 190 /* p points to next tag */ 191 } 192 } else { 193 #if 0 194 /* We now make use of ppp_print() instead, because it has more 195 comprehensive support for PPP. It also gives us a consistent 196 output with other protocols like L2TP. */ 197 u_short ptype; 198 if (pppoe_payload[0] & 0x1) { 199 ptype = pppoe_payload[0]; 200 pppoe_payload +=1; 201 pppoe_length -=1; 202 } else if (pppoe_payload[1] & 0x1) { 203 ptype = ntohs(*(u_short *)pppoe_payload); 204 pppoe_payload +=2; 205 pppoe_length -=2; 206 } else { 207 printf(" Invalid PPP protocol ID: %x %x", pppoe_payload[0],pppoe_payload[1]); 208 return; 209 } 210 printf(" "); 211 if (ptype == PPP_IP) 212 ip_print(pppoe_payload, pppoe_length); 213 else if (ptype == PPP_LCP) 214 lcp_print(pppoe_payload, pppoe_length); 215 else 216 printf("%s ", tok2str(ppptype2str, "proto-0x%x", ptype)); 217 #endif 218 printf(" "); 219 ppp_print(pppoe_payload, pppoe_length); 220 } 221 return; 222 } 223