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