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