/**************************************************************************** ** 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(); }