156893Sfenner/* 256893Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 356893Sfenner * The Regents of the University of California. All rights reserved. 456893Sfenner * 556893Sfenner * Redistribution and use in source and binary forms, with or without 656893Sfenner * modification, are permitted provided that: (1) source code distributions 756893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 856893Sfenner * distributions including binary code include the above copyright notice and 956893Sfenner * this paragraph in its entirety in the documentation or other materials 1056893Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1156893Sfenner * features or use of this software display the following acknowledgement: 1256893Sfenner * ``This product includes software developed by the University of California, 1356893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1456893Sfenner * the University nor the names of its contributors may be used to endorse 1556893Sfenner * or promote products derived from this software without specific prior 1656893Sfenner * written permission. 1756893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1856893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1956893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20127668Sbms * 21127668Sbms * Original code by Greg Stark <gsstark@mit.edu> 2256893Sfenner */ 2356893Sfenner 2456893Sfenner#ifndef lint 25127668Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo"@(#) $Header: /tcpdump/master/tcpdump/print-pppoe.c,v 1.31 2005-04-26 19:48:38 guy Exp $ (LBL)"; 2756893Sfenner#endif 2856893Sfenner 2956893Sfenner#ifdef HAVE_CONFIG_H 3056893Sfenner#include "config.h" 3156893Sfenner#endif 3256893Sfenner 33127668Sbms#include <tcpdump-stdinc.h> 3456893Sfenner 3556893Sfenner#include <stdio.h> 3656893Sfenner#include <string.h> 3756893Sfenner 3856893Sfenner#include "interface.h" 3956893Sfenner#include "addrtoname.h" 4056893Sfenner#include "ppp.h" 4156893Sfenner#include "ethertype.h" 4275115Sfenner#include "ether.h" 4356893Sfenner#include "extract.h" /* must come after interface.h */ 4456893Sfenner 4556893Sfenner/* Codes */ 4698524Sfennerenum { 4798524Sfenner PPPOE_PADI = 0x09, 4898524Sfenner PPPOE_PADO = 0x07, 4998524Sfenner PPPOE_PADR = 0x19, 5098524Sfenner PPPOE_PADS = 0x65, 5198524Sfenner PPPOE_PADT = 0xa7 5256893Sfenner}; 5356893Sfenner 5456893Sfennerstatic struct tok pppoecode2str[] = { 5598524Sfenner { PPPOE_PADI, "PADI" }, 5698524Sfenner { PPPOE_PADO, "PADO" }, 5798524Sfenner { PPPOE_PADR, "PADR" }, 5898524Sfenner { PPPOE_PADS, "PADS" }, 5998524Sfenner { PPPOE_PADT, "PADT" }, 6098524Sfenner { 0, "" }, /* PPP Data */ 6198524Sfenner { 0, NULL } 6256893Sfenner}; 6356893Sfenner 6456893Sfenner/* Tags */ 6556893Sfennerenum { 6698524Sfenner PPPOE_EOL = 0, 6798524Sfenner PPPOE_SERVICE_NAME = 0x0101, 6898524Sfenner PPPOE_AC_NAME = 0x0102, 6998524Sfenner PPPOE_HOST_UNIQ = 0x0103, 7098524Sfenner PPPOE_AC_COOKIE = 0x0104, 7198524Sfenner PPPOE_VENDOR = 0x0105, 7298524Sfenner PPPOE_RELAY_SID = 0x0110, 73241235Sdelphij PPPOE_MAX_PAYLOAD = 0x0120, 7498524Sfenner PPPOE_SERVICE_NAME_ERROR = 0x0201, 7598524Sfenner PPPOE_AC_SYSTEM_ERROR = 0x0202, 7698524Sfenner PPPOE_GENERIC_ERROR = 0x0203 7756893Sfenner}; 7856893Sfenner 7956893Sfennerstatic struct tok pppoetag2str[] = { 8098524Sfenner { PPPOE_EOL, "EOL" }, 8198524Sfenner { PPPOE_SERVICE_NAME, "Service-Name" }, 8298524Sfenner { PPPOE_AC_NAME, "AC-Name" }, 8398524Sfenner { PPPOE_HOST_UNIQ, "Host-Uniq" }, 8498524Sfenner { PPPOE_AC_COOKIE, "AC-Cookie" }, 8598524Sfenner { PPPOE_VENDOR, "Vendor-Specific" }, 8698524Sfenner { PPPOE_RELAY_SID, "Relay-Session-ID" }, 87241235Sdelphij { PPPOE_MAX_PAYLOAD, "PPP-Max-Payload" }, 8898524Sfenner { PPPOE_SERVICE_NAME_ERROR, "Service-Name-Error" }, 8998524Sfenner { PPPOE_AC_SYSTEM_ERROR, "AC-System-Error" }, 9098524Sfenner { PPPOE_GENERIC_ERROR, "Generic-Error" }, 9198524Sfenner { 0, NULL } 9256893Sfenner}; 9356893Sfenner 9456893Sfenner#define PPPOE_HDRLEN 6 95127668Sbms#define MAXTAGPRINT 80 9656893Sfenner 97127668Sbmsu_int 98127668Sbmspppoe_if_print(const struct pcap_pkthdr *h, register const u_char *p) 9998524Sfenner{ 100127668Sbms return (pppoe_print(p, h->len)); 10198524Sfenner} 10298524Sfenner 103127668Sbmsu_int 10456893Sfennerpppoe_print(register const u_char *bp, u_int length) 10556893Sfenner{ 106146773Ssam u_int16_t pppoe_ver, pppoe_type, pppoe_code, pppoe_sessionid; 107146773Ssam u_int pppoe_length; 10898524Sfenner const u_char *pppoe_packet, *pppoe_payload; 10956893Sfenner 110146773Ssam if (length < PPPOE_HDRLEN) { 111146773Ssam (void)printf("truncated-pppoe %u", length); 112146773Ssam return (length); 113146773Ssam } 114146773Ssam length -= PPPOE_HDRLEN; 11598524Sfenner pppoe_packet = bp; 116127668Sbms TCHECK2(*pppoe_packet, PPPOE_HDRLEN); 11798524Sfenner pppoe_ver = (pppoe_packet[0] & 0xF0) >> 4; 11898524Sfenner pppoe_type = (pppoe_packet[0] & 0x0F); 11998524Sfenner pppoe_code = pppoe_packet[1]; 12098524Sfenner pppoe_sessionid = EXTRACT_16BITS(pppoe_packet + 2); 12198524Sfenner pppoe_length = EXTRACT_16BITS(pppoe_packet + 4); 12298524Sfenner pppoe_payload = pppoe_packet + PPPOE_HDRLEN; 12356893Sfenner 12498524Sfenner if (pppoe_ver != 1) { 12598524Sfenner printf(" [ver %d]",pppoe_ver); 12698524Sfenner } 12798524Sfenner if (pppoe_type != 1) { 12898524Sfenner printf(" [type %d]",pppoe_type); 12998524Sfenner } 13056893Sfenner 13198524Sfenner printf("PPPoE %s", tok2str(pppoecode2str, "PAD-%x", pppoe_code)); 13298524Sfenner if (pppoe_code == PPPOE_PADI && pppoe_length > 1484 - PPPOE_HDRLEN) { 133146773Ssam printf(" [len %u!]",pppoe_length); 13498524Sfenner } 135146773Ssam if (pppoe_length > length) { 136146773Ssam printf(" [len %u > %u!]", pppoe_length, length); 137146773Ssam pppoe_length = length; 138146773Ssam } 13998524Sfenner if (pppoe_sessionid) { 14098524Sfenner printf(" [ses 0x%x]", pppoe_sessionid); 14198524Sfenner } 14256893Sfenner 14398524Sfenner if (pppoe_code) { 14498524Sfenner /* PPP session packets don't contain tags */ 14598524Sfenner u_short tag_type = 0xffff, tag_len; 14698524Sfenner const u_char *p = pppoe_payload; 14798524Sfenner 14898524Sfenner /* 14998524Sfenner * loop invariant: 150146773Ssam * p points to current tag, 15198524Sfenner * tag_type is previous tag or 0xffff for first iteration 15298524Sfenner */ 153146773Ssam while (tag_type && p < pppoe_payload + pppoe_length) { 154146773Ssam TCHECK2(*p, 4); 15598524Sfenner tag_type = EXTRACT_16BITS(p); 15698524Sfenner tag_len = EXTRACT_16BITS(p + 2); 15798524Sfenner p += 4; 15898524Sfenner /* p points to tag_value */ 15998524Sfenner 16098524Sfenner if (tag_len) { 161127668Sbms unsigned isascii = 0, isgarbage = 0; 162251158Sdelphij const u_char *v; 163127668Sbms char tag_str[MAXTAGPRINT]; 164127668Sbms unsigned tag_str_len = 0; 16598524Sfenner 166127668Sbms /* TODO print UTF-8 decoded text */ 167146773Ssam TCHECK2(*p, tag_len); 168127668Sbms for (v = p; v < p + tag_len && tag_str_len < MAXTAGPRINT-1; v++) 169127668Sbms if (*v >= 32 && *v < 127) { 170127668Sbms tag_str[tag_str_len++] = *v; 171127668Sbms isascii++; 172127668Sbms } else { 173127668Sbms tag_str[tag_str_len++] = '.'; 174127668Sbms isgarbage++; 17598524Sfenner } 176127668Sbms tag_str[tag_str_len] = 0; 17798524Sfenner 178127668Sbms if (isascii > isgarbage) { 17998524Sfenner printf(" [%s \"%*.*s\"]", 180127668Sbms tok2str(pppoetag2str, "TAG-0x%x", tag_type), 181127668Sbms (int)tag_str_len, 182127668Sbms (int)tag_str_len, 183127668Sbms tag_str); 184127668Sbms } else { 185127668Sbms /* Print hex, not fast to abuse printf but this doesn't get used much */ 186127668Sbms printf(" [%s 0x", tok2str(pppoetag2str, "TAG-0x%x", tag_type)); 187127668Sbms for (v=p; v<p+tag_len; v++) { 188127668Sbms printf("%02X", *v); 189127668Sbms } 190127668Sbms printf("]"); 191127668Sbms } 192127668Sbms 193127668Sbms 19498524Sfenner } else 19598524Sfenner printf(" [%s]", tok2str(pppoetag2str, 19698524Sfenner "TAG-0x%x", tag_type)); 19798524Sfenner 19898524Sfenner p += tag_len; 19998524Sfenner /* p points to next tag */ 20098524Sfenner } 201127668Sbms return (0); 20298524Sfenner } else { 203127668Sbms /* PPPoE data */ 20498524Sfenner printf(" "); 205127668Sbms return (PPPOE_HDRLEN + ppp_print(pppoe_payload, pppoe_length)); 20698524Sfenner } 207127668Sbms 208127668Sbmstrunc: 209127668Sbms printf("[|pppoe]"); 210127668Sbms return (PPPOE_HDRLEN); 21156893Sfenner} 212