/****************************************************************************
** File: ppp.c
**
** Author: Mike Borella
**
** Comments: PPP module.
**
** $Id: ppp.c,v 1.14 2001/11/15 00:22:36 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 "ppp.h"
#include "payload.h"
/*
* PPP protocol types
*/
#define PPP_PROTOCOL_IP 0x0021
#define PPP_PROTOCOL_IPCP 0x8021
#define PPP_PROTOCOL_IPXCP 0x802b
#define PPP_PROTOCOL_LCP 0xc021
#define PPP_PROTOCOL_PAP 0xc023
#define PPP_PROTOCOL_CHAP 0xc223
#define PPP_PROTOCOL_CCP 0x80fd
#define PPP_PROTOCOL_COMPRESSED_FRAME 0x00fd
#define PPP_PROTOCOL_CBCP 0xc029
#define PPP_PROTOCOL_VJUNCOMPRESSED 0x002f
/*
* PPP protocol map
*/
strmap_t ppp_protocol_map[] =
{
{ PPP_PROTOCOL_IP, "IP" },
{ PPP_PROTOCOL_IPCP, "IPCP" },
{ PPP_PROTOCOL_IPXCP, "IPXCP" },
{ PPP_PROTOCOL_LCP, "LCP" },
{ PPP_PROTOCOL_PAP, "PAP" },
{ PPP_PROTOCOL_CHAP, "CHAP" },
{ PPP_PROTOCOL_CCP, "CCP" },
{ PPP_PROTOCOL_COMPRESSED_FRAME, "compressed frame" },
{ PPP_PROTOCOL_CBCP, "CBCP" },
{ PPP_PROTOCOL_VJUNCOMPRESSED, "VJ uncompressed" },
{ 0, "" }
};
/*
* PPP frame format
*/
typedef struct ppp
{
u_int8_t address;
u_int8_t control;
u_int16_t protocol;
} ppp_t;
extern struct arg_t * my_args;
/*----------------------------------------------------------------------------
**
** dump_ppp()
**
** Displays PPP packets.
**
**----------------------------------------------------------------------------
*/
void dump_ppp(packet_t * pkt)
{
ppp_t ppp;
u_int16_t protocol;
u_int16_t two_bytes;
/* Set the layer */
set_layer(LAYER_DATALINK);
/*
* Look at the first 2 bytes to see if address/control compression is
* set or not.
*/
if (look_packet_bytes((u_int8_t *) &two_bytes, pkt, sizeof(u_int16_t)) == 0)
return;
/*
* If the result is 0xff03, then process the packet normally. Anything else
* and we'll assume that compression is being used and that these two
* bytes are a protocol type.
*/
if (ntohs(two_bytes) == 0xff03)
{
/*
* Get the header
*/
if (get_packet_bytes((u_int8_t *) &ppp, pkt, sizeof(ppp_t)) == 0)
return;
/*
* Conversion
*/
protocol = ntohs(ppp.protocol);
/*
* Dump the header
*/
if (my_args->m)
{
display_minimal_string("| PPP ");
}
else
{
display_header_banner("PPP Header");
display("Address", &ppp.address, 1, DISP_HEX);
display("Control", &ppp.control, 1, DISP_HEX);
display_strmap_hex("Protocol type", protocol,
ppp_protocol_map);
}
}
else
{
u_int8_t temp_protocol;
/*
* Get the protocol. If the protocol is "0x21" then it is only
* one byte and compression is suppressing the "0x00" - i.e., its a
* damn IP packet. If is one byte and is "0xfd", its a compressed
* PPP frame and therefore we cannot decode it.
*
* This is a quick fix = it could be made more robust
*/
if (look_packet_bytes((u_int8_t *) &temp_protocol, pkt, 1) == 0)
return;
if (temp_protocol == PPP_PROTOCOL_IP ||
temp_protocol == PPP_PROTOCOL_COMPRESSED_FRAME ||
temp_protocol == PPP_PROTOCOL_VJUNCOMPRESSED)
{
if (get_packet_bytes((u_int8_t *) &temp_protocol, pkt, 1) == 0)
return;
protocol = temp_protocol;
}
else
{
if (get_packet_bytes((u_int8_t *) &protocol, pkt, 2) == 0)
return;
protocol = ntohs(protocol);
}
/*
* Dump the header
*/
if (my_args->m)
{
display_minimal_string("PPP ");
}
else
{
display_header_banner("PPP Header");
display_strmap_hex("Protocol type", protocol, ppp_protocol_map);
}
} /* else */
/* dump the hex buffer */
hexbuffer_flush();
/*
* Determine the next layer protocol
*/
switch(protocol)
{
case PPP_PROTOCOL_IP:
case PPP_PROTOCOL_VJUNCOMPRESSED:
dump_ip(pkt);
break;
case PPP_PROTOCOL_LCP:
dump_lcp(pkt);
break;
case PPP_PROTOCOL_CHAP:
dump_chap(pkt);
break;
case PPP_PROTOCOL_IPCP:
dump_ipcp(pkt);
break;
case PPP_PROTOCOL_CBCP:
dump_cbcp(pkt);
break;
case PPP_PROTOCOL_CCP:
dump_ccp(pkt);
break;
case PPP_PROTOCOL_COMPRESSED_FRAME:
/* If MPPC was given as the default CCP algorithm, dump it */
if (!strcmp(my_args->C, "mppc"))
dump_mppc(pkt);
break;
default:
if (!my_args->m)
dump_payload(pkt);
break;
}
/* Should be able to display the PPP trailer here.... */
}
/*----------------------------------------------------------------------------
**
** dump_ppp_hdlc()
**
** Scans over the HDLC based PPP frame and translates it into a regular
** frame that PPP can handle. Some systems however will fragment the
** HDLC-ized packets. We would need memory and state to handle these
** cases, and we're not going to implement that right now.
**
**----------------------------------------------------------------------------
*/
void dump_ppp_hdlc(packet_t * pkt)
{
packet_t hdlc_frame;
int length;
char * holder_before;
char * holder_after;
int ptr;
int i;
u_int8_t first_byte;
/* Set the layer */
set_layer(LAYER_DATALINK);
/*
* Look at the first byte. Bail out if it is not 0x7e. We may be able
* to fix this later
*/
if (look_packet_bytes(&first_byte, pkt, 1) == 0)
return;
else
{
if (first_byte != 0x7e)
{
dump_ppp(pkt);
return;
}
}
/* Determine the length of the frame */
length = get_packet_apparentbytesleft(pkt);
/* Allocate space for this */
holder_before = my_malloc(length);
holder_after = my_malloc(length);
/* Get the packet */
if (get_packet_bytes(holder_before, pkt, length) == 0)
return;
/* Run through the before array moving fixed characters to the after array */
ptr = 0;
for (i=0; i<length; i++)
{
/* Copy normal bytes */
if (holder_before[i] != 0x7e && holder_before[i] != 0x7d)
{
holder_after[ptr] = holder_before[i];
ptr++;
continue;
}
/* Unescape escaped bytes */
if (holder_before[i] == 0x7d)
{
if (i+1 >= length)
break;
i++;
holder_after[ptr] = holder_before[i] ^ 0x20;
ptr++;
}
/* Bail out when we see a 0x7e that is not at the beginning */
if (i>0 && holder_before[i] == 0x7e)
break;
}
/* Delete the before data, we no longer need it */
my_free (holder_before);
/* Create a fake packet to fake out PPP and other modules */
hdlc_frame.contents = holder_after;
hdlc_frame.current = &hdlc_frame.contents[0];
hdlc_frame.end = &hdlc_frame.contents[0] + ptr;
hdlc_frame.apparent_end = hdlc_frame.end;
hdlc_frame.media_length = ptr;
/* Kill the hex buffer here in order to eliminate duplicate processing */
hexbuffer_kill();
/* Send this packet through the processing */
dump_ppp(&hdlc_frame);
/* Free the memory for the fake packet */
my_free(hdlc_frame.contents);
}
syntax highlighted by Code2HTML, v. 0.9.1