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