/**************************************************************************** ** File: pppoe.c ** ** Author: Andy Juniper ** ** Comments: PPP module. ** ** $Id: pppoe.c,v 1.5 2001/05/28 19:24:04 mborella Exp $ ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU Library General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** *****************************************************************************/ #include "pppoe.h" #include "ppp.h" /* * PPPOE code types */ #define PPPOE_CODE_PADI 0x09 #define PPPOE_CODE_PADO 0x07 #define PPPOE_CODE_PADR 0x19 #define PPPOE_CODE_PADS 0x65 #define PPPOE_CODE_PADT 0xa7 #define PPPOE_CODE_SESS 0x00 /* * PPPOE tag types */ #define PPPOE_TAG_ENDOFLIST 0x0000 #define PPPOE_TAG_SERVICENAME 0x0101 #define PPPOE_TAG_ACNAME 0x0102 #define PPPOE_TAG_HOSTUNIQ 0x0103 #define PPPOE_TAG_ACCOOKIE 0x0104 #define PPPOE_TAG_VENDORSPEC 0x0105 #define PPPOE_TAG_RELAYSESSID 0x0110 #define PPPOE_TAG_SERVNAMEERR 0x0201 #define PPPOE_TAG_ACSYSERR 0x0202 #define PPPOE_TAG_GENERICERR 0x0203 /* * PPPOE code map */ strmap_t pppoe_code_map[] = { { PPPOE_CODE_PADI ,"PADI" }, { PPPOE_CODE_PADO ,"PADO" }, { PPPOE_CODE_PADR ,"PADR" }, { PPPOE_CODE_PADS ,"PADS" }, { PPPOE_CODE_PADT ,"PADT" }, { PPPOE_CODE_SESS ,"SESSION" }, { 0, "" } }; /* * PPPOE TLV map */ strmap_t pppoe_tlv_map[] = { { PPPOE_TAG_ENDOFLIST ,"End of List" }, { PPPOE_TAG_SERVICENAME ,"Service Name" }, { PPPOE_TAG_ACNAME ,"AC Name" }, { PPPOE_TAG_HOSTUNIQ ,"Host Uniq" }, { PPPOE_TAG_ACCOOKIE ,"AC Cookie" }, { PPPOE_TAG_VENDORSPEC ,"Vendor Specific" }, { PPPOE_TAG_RELAYSESSID ,"Relay Session ID" }, { PPPOE_TAG_SERVNAMEERR ,"Service Name Error" }, { PPPOE_TAG_ACSYSERR ,"AC System Error" }, { PPPOE_TAG_GENERICERR ,"Generic Error" }, { 0, "" } }; /* * PPPOE frame format */ typedef struct pppoe { u_int8_t vertype; u_int8_t code; u_int16_t session; u_int16_t length; } pppoe_t; typedef struct pppoe_tlv { u_int16_t tagtype; u_int16_t taglen; } pppoe_tlv_t; extern struct arg_t * my_args; /*---------------------------------------------------------------------------- ** ** dump_pppoe_hdr() ** ** Displays PPPOE headers ** **---------------------------------------------------------------------------- */ int dump_pppoe_hdr(packet_t *pkt) { pppoe_t pppoe; int len; /* Set the layer */ set_layer(LAYER_DATALINK); /* * Get the header */ if (get_packet_bytes((u_int8_t *) &pppoe, pkt, sizeof(pppoe_t)) == 0) return 0; len = ntohs(pppoe.length); /* * Dump the header */ if (my_args->m) { display_minimal_string("| PPPOE "); } else { display_header_banner("PPPOE Header"); display("Version/Type", &pppoe.vertype, 1, DISP_HEX); display("Session ID", (u_int8_t *) &pppoe.session, 2, DISP_HEX); display("Length", (u_int8_t *) &len, 2, DISP_DEC); display_strmap_hex("Message code", pppoe.code, pppoe_code_map); } /* dump the hex buffer */ hexbuffer_flush(); return len; } /*---------------------------------------------------------------------------- ** ** dump_pppoed() ** ** Displays PPPOE discovery packets ** **---------------------------------------------------------------------------- */ void dump_pppoed(packet_t *pkt) { pppoe_tlv_t tlv; int len; int offset; int totlen; u_int8_t data[1000]; /* should be enough */ totlen = dump_pppoe_hdr(pkt); /* do no more if we don't need to */ if (my_args->m) return; /* dump the TLVs */ while ((totlen > 0) && (get_packet_bytes((u_int8_t*)&tlv, pkt, sizeof(pppoe_tlv_t)))) { /* do the header */ len = ntohs(tlv.taglen); totlen -= (sizeof(pppoe_tlv_t)+len); display_strmap_hex(" TLV type", ntohs(tlv.tagtype), pppoe_tlv_map); display(" TLV len", (u_int8_t*)&len, 2, DISP_DEC); /* copy the data out */ len = (len>sizeof(data))?sizeof(data)-1:len; if (len == 0) continue; if (get_packet_bytes(data, pkt, len) == 0) return; offset=0; if (tlv.tagtype == PPPOE_TAG_ENDOFLIST) break; /* and the data */ switch (ntohs(tlv.tagtype)) { case PPPOE_TAG_SERVICENAME: case PPPOE_TAG_ACNAME: case PPPOE_TAG_SERVNAMEERR: case PPPOE_TAG_ACSYSERR: case PPPOE_TAG_GENERICERR: /* all string values, if present, not necessarily null terminated */ data[len]=0; display(" TLV value", data, len, DISP_STRING); break; case PPPOE_TAG_VENDORSPEC: /* * 4 bytes vendor id followed by whatever - we dump as hex by * falling through */ display(" TLV vendor", data, 4, DISP_HEX); offset+=4; case PPPOE_TAG_HOSTUNIQ: case PPPOE_TAG_ACCOOKIE: case PPPOE_TAG_RELAYSESSID: default: /* all hex values, if present, and not necessarily null terminated */ display(" TLV value", data+offset, len-offset, DISP_HEX); break; } } /* dump the hex buffer */ hexbuffer_flush(); } /*---------------------------------------------------------------------------- ** ** dump_pppoes() ** ** Displays PPPOE data session packets ** **---------------------------------------------------------------------------- */ void dump_pppoes(packet_t *pkt) { dump_pppoe_hdr(pkt); dump_ppp(pkt); }