/****************************************************************************
** File: ipcp.c
**
** Author: Mike Borella
**
** Comments: IPCP module.
**
** $Id: ipcp.c,v 1.6 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 "ipcp.h"
#define IPCP_OPTION_LEN 64
/*
* IPCP codes
*/
#define IPCP_CODE_CONFREQ 1
#define IPCP_CODE_CONFACK 2
#define IPCP_CODE_CONFNAK 3
#define IPCP_CODE_CONFREJ 4
#define IPCP_CODE_TERMREQ 5
#define IPCP_CODE_TERMACK 6
#define IPCP_CODE_CODEREJ 7
/*
* IPCP code map
*/
strmap_t ipcp_code_map[] =
{
{ IPCP_CODE_CONFREQ, "Configure-Request" },
{ IPCP_CODE_CONFACK, "Configure-Ack" },
{ IPCP_CODE_CONFNAK, "Configure-Nak" },
{ IPCP_CODE_CONFREJ, "Configure-Reject" },
{ IPCP_CODE_TERMREQ, "Terminate-Request" },
{ IPCP_CODE_TERMACK, "Terminate-Ack" },
{ IPCP_CODE_CODEREJ, "Code-Rej" },
{ 0, ""}
};
/*
* IPCP options
*/
#define IPCP_OPTION_IPADDRS 1
#define IPCP_OPTION_IPCOMPPROTO 2
#define IPCP_OPTION_IPADDR 3
#define IPCP_OPTION_MOBILEIPV4 4
#define IPCP_OPTION_PRIMARYDNS 129
#define IPCP_OPTION_PRIMARYNBNS 130
#define IPCP_OPTION_SECONDARYDNS 131
#define IPCP_OPTION_SECONDARYNBNS 132
/*
* IPCP option map
*/
strmap_t ipcp_option_map[] =
{
{ IPCP_OPTION_IPADDRS, "IP addresses" },
{ IPCP_OPTION_IPCOMPPROTO, "IP compression protocol" },
{ IPCP_OPTION_IPADDR, "IP address" },
{ IPCP_OPTION_MOBILEIPV4, "Mobile IPv4" },
{ IPCP_OPTION_PRIMARYDNS, "Primary DNS" },
{ IPCP_OPTION_PRIMARYNBNS, "Primary NBNS" },
{ IPCP_OPTION_SECONDARYDNS, "Secondary DNS" },
{ IPCP_OPTION_SECONDARYNBNS, "Secondary NBNS" },
{ 0, "" }
};
/*
* IPCP compression types
*/
#define IPCP_COMP_VJ 0x002d
/*
* IPCP compression type map
*/
strmap_t ipcp_comp_map[] =
{
{ IPCP_COMP_VJ, "Van Jacobson" },
{ 0, "" }
};
/*
* IPCP frame format
*/
typedef struct ipcp
{
u_int8_t code;
u_int8_t identifier;
u_int16_t length;
} ipcp_t;
extern struct arg_t * my_args;
/*----------------------------------------------------------------------------
**
** dump_ipcp()
**
** Displays IPCP packets.
**
**----------------------------------------------------------------------------
*/
void dump_ipcp(packet_t *pkt)
{
ipcp_t ipcp;
/* Set the layer */
set_layer(LAYER_DATALINK);
/*
* Get the header
*/
if (get_packet_bytes((u_int8_t *) &ipcp, pkt, sizeof(ipcp_t)) == 0)
return;
/*
* Conversion
*/
ipcp.length = ntohs(ipcp.length);
/*
* Dump the header
*/
if (my_args->m)
{
display_minimal_string("| IPCP ");
display_minimal_string(map2str(ipcp_code_map, ipcp.code));
display_minimal_string(" ");
}
else
{
display_header_banner("IPCP Header");
display_strmap("Code", ipcp.code, ipcp_code_map);
display("Identifier", &ipcp.identifier, 1, DISP_DEC);
display("Length", (u_int8_t *) &ipcp.length, 2, DISP_DEC);
}
/*
* Grab the payload data
*/
if (ipcp.length > sizeof(ipcp_t))
{
switch(ipcp.code)
{
case IPCP_CODE_CONFREQ:
case IPCP_CODE_CONFACK:
case IPCP_CODE_CONFNAK:
case IPCP_CODE_CONFREJ:
{
u_int8_t bytes_read = 0;
u_int8_t type;
u_int8_t length;
u_int8_t value [IPCP_OPTION_LEN];
int comma = 0;
/*
* IPCP options appear in Type-Length-Value format
*/
while (bytes_read < ipcp.length - sizeof(ipcp_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 IPCP 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(ipcp_option_map, type));
}
else
{
display_strmap("Option", type, ipcp_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
*/
switch(type)
{
case IPCP_OPTION_IPADDRS:
break;
case IPCP_OPTION_IPCOMPPROTO:
{
u_int16_t comp_type;
memcpy((void *) &comp_type, (void *) &value, 2);
comp_type = ntohs(comp_type);
if (my_args->m)
{
display_minimal_string(" ");
display_minimal_string(map2str
(ipcp_comp_map,
comp_type));
}
else
{
u_int8_t max_slot_id = value[2];
u_int8_t comp_slot_id = value[3];
display_strmap("IP compression", comp_type,
ipcp_comp_map);
display("Max slot ID",
(u_int8_t *) &max_slot_id, 1,
DISP_DEC);
display("Comp slot ID",
(u_int8_t *) &comp_slot_id, 1,
DISP_DEC);
}
break;
}
case IPCP_OPTION_IPADDR:
case IPCP_OPTION_PRIMARYDNS:
case IPCP_OPTION_PRIMARYNBNS:
case IPCP_OPTION_SECONDARYDNS:
case IPCP_OPTION_SECONDARYNBNS:
if (my_args->m)
{
display_minimal_string(" ");
display_minimal_ipv4((u_int8_t *) &value);
}
else
display_ipv4("IP address", (u_int8_t *) &value);
break;
}
}
} /* while */
/*
* Insert end paren in minimal mode
*/
if (my_args->m)
display_minimal_string(")");
}
break;
case IPCP_CODE_TERMREQ:
case IPCP_CODE_TERMACK:
{
u_int8_t * data;
u_int8_t data_len;
/*
* Read the data, if any
*/
data_len = ipcp.length - sizeof(ipcp_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 IPCP_CODE_CODEREJ:
dump_ipcp(pkt);
break;
default:
break;
}
}
/* dump the hex buffer */
if (!my_args->l)
hexbuffer_flush();
}
syntax highlighted by Code2HTML, v. 0.9.1