/****************************************************************************
** File: ccp.c
**
** Author: Mike Borella
**
** Comments: CCP module.
**
** $Id: ccp.c,v 1.1 2001/10/02 21:36: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 "ccp.h"
#define CCP_OPTION_LEN 64
/*
* CCP codes
*/
#define CCP_CODE_CONFREQ 1
#define CCP_CODE_CONFACK 2
#define CCP_CODE_CONFNAK 3
#define CCP_CODE_CONFREJ 4
#define CCP_CODE_TERMREQ 5
#define CCP_CODE_TERMACK 6
#define CCP_CODE_CODEREJ 7
#define CCP_CODE_RESETREQ 14
#define CCP_CODE_RESETREP 15
/*
* CCP code map
*/
strmap_t ccp_code_map[] =
{
{ CCP_CODE_CONFREQ, "Configure-Request" },
{ CCP_CODE_CONFACK, "Configure-Ack" },
{ CCP_CODE_CONFNAK, "Configure-Nak" },
{ CCP_CODE_CONFREJ, "Configure-Reject" },
{ CCP_CODE_TERMREQ, "Terminate-Request" },
{ CCP_CODE_TERMACK, "Terminate-Ack" },
{ CCP_CODE_CODEREJ, "Code-Rej" },
{ CCP_CODE_RESETREQ, "Reset-Request" },
{ CCP_CODE_RESETREP, "Reset-Replay" },
{ 0, ""}
};
/*
* CCP options
*/
#define CCP_OPTION_OUI 0
#define CCP_OPTION_PREDICTORTYPE1 1
#define CCP_OPTION_PREDICTORTYPE2 2
#define CCP_OPTION_PUDDLEJUMPER 3
#define CCP_OPTION_HPPPC 16
#define CCP_OPTION_STACLZS 17
#define CCP_OPTION_MSPPC 18
#define CCP_OPTION_GANDALFFZA 19
#define CCP_OPTION_V42BIS 20
#define CCP_OPTION_BSDCOMPRESS 21
#define CCP_OPTION_LZSDCP 23
#define CCP_OPTION_MVRCAMAGNALINK 24
#define CCP_OPTION_DEFLATE 26
/*
* CCP option map
*/
strmap_t ccp_option_map[] =
{
{ CCP_OPTION_OUI, "OUI" },
{ CCP_OPTION_PREDICTORTYPE1, "predictor type 1" },
{ CCP_OPTION_PREDICTORTYPE2, "predictor type 2" },
{ CCP_OPTION_PUDDLEJUMPER, "puddlejumper" },
{ CCP_OPTION_HPPPC, "Hewlett-Packard PPC" },
{ CCP_OPTION_STACLZS, "STAC LZS" },
{ CCP_OPTION_MSPPC, "Microsoft PPC" },
{ CCP_OPTION_GANDALFFZA, "Gandalf FZA" },
{ CCP_OPTION_V42BIS, "V42BIS" },
{ CCP_OPTION_BSDCOMPRESS, "BSD compress" },
{ CCP_OPTION_LZSDCP, "LZS DCP" },
{ CCP_OPTION_MVRCAMAGNALINK, "MVRCA/Magnalink" },
{ CCP_OPTION_DEFLATE, "deflate" },
{ 0, "" }
};
/*
* CCP frame format
*/
typedef struct ccp
{
u_int8_t code;
u_int8_t identifier;
u_int16_t length;
} ccp_t;
extern struct arg_t * my_args;
/*----------------------------------------------------------------------------
**
** dump_ccp()
**
** Displays CCP packets.
**
**----------------------------------------------------------------------------
*/
void dump_ccp(packet_t *pkt)
{
ccp_t ccp;
/* Set the layer */
set_layer(LAYER_DATALINK);
/*
* Get the header
*/
if (get_packet_bytes((u_int8_t *) &ccp, pkt, sizeof(ccp_t)) == 0)
return;
/*
* Conversion
*/
ccp.length = ntohs(ccp.length);
/*
* Dump the header
*/
if (my_args->m)
{
display_minimal_string("| CCP ");
display_minimal_string(map2str(ccp_code_map, ccp.code));
display_minimal_string(" ");
}
else
{
display_header_banner("CCP Header");
display_strmap("Code", ccp.code, ccp_code_map);
display("Identifier", &ccp.identifier, 1, DISP_DEC);
display("Length", (u_int8_t *) &ccp.length, 2, DISP_DEC);
}
/*
* Grab the payload data
*/
if (ccp.length > sizeof(ccp_t))
{
switch(ccp.code)
{
case CCP_CODE_CONFREQ:
case CCP_CODE_CONFACK:
case CCP_CODE_CONFNAK:
case CCP_CODE_CONFREJ:
{
u_int8_t bytes_read = 0;
u_int8_t type;
u_int8_t length;
u_int8_t value [CCP_OPTION_LEN];
int comma = 0;
/*
* CCP options appear in Type-Length-Value format
*/
while (bytes_read < ccp.length - sizeof(ccp_t))
{
/*
* Get type
*/
if (get_packet_bytes((u_int8_t *) &type, pkt, 1) == 0)
break;
bytes_read ++;
/*
* Get length
*/
if (get_packet_bytes((u_int8_t *) &length, pkt, 1) == 0)
break;
bytes_read ++;
/*
* In minimal mode we start all CCP options with an open paren
* and put a comma before all but the first
*/
if (my_args->m)
{
if (comma)
display_minimal_string(", ");
else
display_minimal_string("(");
}
comma = 1;
/*
* Display the type and length
*/
if (my_args->m)
{
display_minimal_string(map2str(ccp_option_map, type));
}
else
{
display_strmap("Option", type, ccp_option_map);
display(" Length", &length, 1, DISP_DEC);
}
/*
* Figure out if we need to get a value
*/
if (length > 2)
{
if (get_packet_bytes((u_int8_t *) value, pkt, length-2)
== 0)
break;
bytes_read = bytes_read + length - 2;
/*
* Display the value
*/
if (my_args->m)
{
display_minimal_string(" ");
display_minimal(value, length-2, DISP_HEX);
}
else
{
display(" Value", (u_int8_t *) value, length-2,
DISP_HEX);
}
} /* if */
} /* while */
/*
* Insert end paren in minimal mode
*/
if (my_args->m)
display_minimal_string(")");
}
break;
case CCP_CODE_TERMREQ:
case CCP_CODE_TERMACK:
{
u_int8_t * data;
u_int8_t data_len;
/*
* Read the data, if any
*/
data_len = ccp.length - sizeof(ccp_t);
if (data_len > 0)
{
/* allocate memory for the data */
data = (u_int8_t *) my_malloc(data_len);
/* grab the data field */
if (get_packet_bytes(data, pkt, data_len) == 0)
{
my_free(data);
return;
}
/* dump it out as hex, but don't dump in minimal mode */
if (!my_args->m)
{
display("Data", data, data_len, DISP_HEX);
}
/* free that darn mem! */
my_free(data);
}
}
break;
case CCP_CODE_CODEREJ:
dump_ccp(pkt);
break;
case CCP_CODE_RESETREQ:
case CCP_CODE_RESETREP:
break;
default:
break;
}
}
/* dump the hex buffer */
if (!my_args->l)
hexbuffer_flush();
}
syntax highlighted by Code2HTML, v. 0.9.1