/* *--------------------------------------------------------------------------- * ppp.c - PPP Processor/Handler - * - *--------------------------------------------------------------------------- * * Version - * 0.1 Original Version Jun 3, 2000 - * - *--------------------------------------------------------------------------- */ /* * Copyright (c) 2003, Mike Johnson, Mycal Labs, www.mycal.net * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Mike Johnson/Mycal Labs * www.mycal.net. * 4. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the Mycal Modified uIP TCP/IP stack. * * $Id: ppp.c,v 1.1 2006/06/17 22:48:09 adamdunkels Exp $ * */ /* */ /* include files */ /* */ #include "lcp.h" #include "pap.h" #include "ipcp.h" /*#include "time.h"*/ /*#include "mip.h"*/ #if 0 #define DEBUG1(x) #else #include #define DEBUG1(x) debug_printf x #endif /* Set the debug message level */ #define PACKET_RX_DEBUG 1 /* Include stuff */ /*#include "mTypes.h"*/ #include "ppp.h" #include "ahdlc.h" #include "ipcp.h" #include "lcp.h" extern int ppp_arch_getchar(u8_t *p); /* Buffers that this layer needs (this can be optimized out) */ u8_t ppp_rx_buffer[PPP_RX_BUFFER_SIZE]; /*u8_t ppp_tx_buffer[PPP_TX_BUFFER_SIZE];*/ /* * Other state storage (this can be placed in a struct and this could could * support multiple PPP connections, would have to embedded the other ppp * module state also) */ u8_t ppp_flags; u8_t ppp_id; u8_t ppp_retry; #if PACKET_RX_DEBUG u16_t ppp_rx_frame_count=0; u16_t ppp_rx_tobig_error; u8_t done; /* temporary variable */ #endif /*---------------------------------------------------------------------------*/ static u8_t check_ppp_errors(void) { u8_t ret = 0; /* Check Errors */ if(lcp_state & LCP_TX_TIMEOUT) { ret = 1; } if(lcp_state & LCP_RX_TIMEOUT) { ret = 2; } if(pap_state & PAP_TX_AUTH_FAIL) { ret = 3; } if(pap_state & PAP_RX_AUTH_FAIL) { ret = 4; } if(pap_state & PAP_TX_TIMEOUT) { ret = 5; } if(pap_state & PAP_RX_TIMEOUT) { ret = 6; } if(ipcp_state & IPCP_TX_TIMEOUT) { ret = 7; } return ret; } /*---------------------------------------------------------------------------*/ /* * Unknown Protocol Handler, sends reject */ static void ppp_reject_protocol(u16_t protocol, u8_t *buffer, u16_t count) { u16_t i; u8_t *dptr, *sptr; LCPPKT *pkt; /* first copy rejected packet back, start from end and work forward, +++ Pay attention to buffer managment when updated. Assumes fixed PPP blocks. */ DEBUG1(("Rejecting Protocol\n")); if((count + 6) > PPP_RX_BUFFER_SIZE) { /* This is a fatal error +++ do somthing about it. */ DEBUG1(("Cannot Reject Protocol, PKT to big\n")); return; } dptr = buffer + count + 6; sptr = buffer + count; for(i = 0; i < count; ++i) { *dptr-- = *sptr--; } pkt = (LCPPKT *)buffer; pkt->code = PROT_REJ; /* Write Conf_rej */ /*pkt->id = tid++;*/ /* write tid */ pkt->len = htons(count + 6); *((u16_t *)(&pkt->data[0])) = htons(protocol); ahdlc_tx(LCP, buffer, 0, (u16_t)(count + 6), 0); } /*---------------------------------------------------------------------------*/ #if PACKET_RX_DEBUG void dump_ppp_packet(u8_t *buffer, u16_t len) { int i; DEBUG1(("\n")); for(i = 0;i < len; ++i) { if((i & 0x1f) == 0x10) { DEBUG1(("\n")); } DEBUG1(("0x%02x ",buffer[i])); } DEBUG1(("\n\n")); } #endif /*---------------------------------------------------------------------------*/ /* Initialize and start PPP engine. This just sets things up to * starting values. This can stay a private method. */ /*---------------------------------------------------------------------------*/ void ppp_init() { #if PACKET_RX_DEBUG ppp_rx_frame_count = 0; done = 0; #endif ppp_flags = 0; pap_init(); ipcp_init(); lcp_init(); ppp_flags = 0; ahdlc_init(ppp_rx_buffer, PPP_RX_BUFFER_SIZE); ahdlc_rx_ready(); } /*---------------------------------------------------------------------------*/ /* raise_ppp() - This routine will try to bring up a PPP connection, * It is blocking. In the future we probably want to pass a * structure with all the options on bringing up a PPP link, like * server/client, DSN server, username password for PAP... +++ for * now just use config and bit defines */ /*---------------------------------------------------------------------------*/ #if 0 u16_t ppp_raise(u8_t config, u8_t *username, u8_t *password) { u16_t status = 0; /* Initialize PPP engine */ /* init_ppp(); */ pap_init(); ipcp_init(); lcp_init(); /* Enable PPP */ ppp_flags = PPP_RX_READY; /* Try to bring up the layers */ while(status == 0) { #ifdef SYSTEM_POLLER /* If the the serial interrupt is not hooked to ahdlc_rx, or the system needs to handle other stuff while were blocking, call the system poller.*/ system_poller(); #endif /* call the lcp task to bring up the LCP layer */ lcp_task(ppp_tx_buffer); /* If LCP is up, neg next layer */ if(lcp_state & LCP_TX_UP) { /* If LCP wants PAP, try to authenticate, else bring up IPCP */ if((lcp_state & LCP_RX_AUTH) && (!(pap_state & PAP_TX_UP))) { pap_task(ppp_tx_buffer,username,password); } else { ipcp_task(ppp_tx_buffer); } } /* If IPCP came up then our link should be up. */ if((ipcp_state & IPCP_TX_UP) && (ipcp_state & IPCP_RX_UP)) { break; } status = check_ppp_errors(); } return status; } #endif /*---------------------------------------------------------------------------*/ void ppp_connect(void) { /* Initialize PPP engine */ /* init_ppp(); */ pap_init(); ipcp_init(); lcp_init(); /* Enable PPP */ ppp_flags = PPP_RX_READY; } /*---------------------------------------------------------------------------*/ void ppp_send(void) { /* If IPCP came up then our link should be up. */ if((ipcp_state & IPCP_TX_UP) && (ipcp_state & IPCP_RX_UP)) { ahdlc_tx(IPV4, &uip_buf[ UIP_LLH_LEN ], uip_appdata, UIP_TCPIP_HLEN, uip_len - UIP_TCPIP_HLEN); } } /*---------------------------------------------------------------------------*/ void ppp_poll(void) { u8_t c; uip_len = 0; if(!(ppp_flags & PPP_RX_READY)) { return; } while(uip_len == 0 && ppp_arch_getchar(&c)) { ahdlc_rx(c); } /* If IPCP came up then our link should be up. */ if((ipcp_state & IPCP_TX_UP) && (ipcp_state & IPCP_RX_UP)) { return; } /* call the lcp task to bring up the LCP layer */ lcp_task( &uip_buf[ UIP_LLH_LEN ]); /* If LCP is up, neg next layer */ if((lcp_state & LCP_TX_UP) && (lcp_state & LCP_RX_UP)) { /* If LCP wants PAP, try to authenticate, else bring up IPCP */ if((lcp_state & LCP_RX_AUTH) && (!(pap_state & PAP_TX_UP))) { pap_task( &uip_buf[ UIP_LLH_LEN ]); } else { ipcp_task( &uip_buf[ UIP_LLH_LEN ]); } } } /*---------------------------------------------------------------------------*/ /* ppp_upcall() - this is where valid PPP frames from the ahdlc layer are * sent to be processed and demuxed. */ /*---------------------------------------------------------------------------*/ void ppp_upcall(u16_t protocol, u8_t *buffer, u16_t len) { #if PACKET_RX_DEBUG ++ppp_rx_frame_count; dump_ppp_packet(buffer, len); if(ppp_rx_frame_count > 18) { done = 1; } #endif /* check to see if we have a packet waiting to be processed */ if(ppp_flags & PPP_RX_READY) { /* demux on protocol field */ switch(protocol) { case LCP: /* We must support some level of LCP */ DEBUG1(("LCP Packet - ")); lcp_rx(buffer, len); DEBUG1(("\n")); break; case PAP: /* PAP should be compile in optional */ DEBUG1(("PAP Packet - ")); pap_rx(buffer, len); DEBUG1(("\n")); break; case IPCP: /* IPCP should be compile in optional. */ DEBUG1(("IPCP Packet - ")); ipcp_rx(buffer, len); DEBUG1(("\n")); break; case IPV4: /* We must support IPV4 */ DEBUG1(("IPV4 Packet---\n")); memcpy( &uip_buf[ UIP_LLH_LEN ], buffer, len); uip_len = len; DEBUG1(("\n")); break; default: DEBUG1(("Unknown PPP Packet Type 0x%04x - ",protocol)); ppp_reject_protocol(protocol, buffer, len); DEBUG1(("\n")); break; } } } /*---------------------------------------------------------------------------*/ /* scan_packet(list,buffer,len) * * list = list of supported ID's * *buffer pointer to the first code in the packet * length of the codespace */ u16_t scan_packet(u16_t protocol, u8_t *list, u8_t *buffer, u8_t *options, u16_t len) { u8_t *tlist, *bptr; u8_t *tptr; u8_t bad = 0; u8_t i, j, good; bptr = tptr = options; /* scan through the packet and see if it has any unsupported codes */ while(bptr < options + len) { /* get code and see if it matches somwhere in the list, if not we don't support it */ i = *bptr++; /* DEBUG2("%x - ",i);*/ tlist = list; good = 0; while(*tlist) { /* DEBUG2("%x ",*tlist);*/ if(i == *tlist++) { good = 1; break; } } if(!good) { /* we don't understand it, write it back */ DEBUG1(("We don't understand option 0x%02x\n",i)); bad = 1; *tptr++ = i; j = *tptr++ = *bptr++; for(i = 0; i < j - 2; ++i) { *tptr++ = *bptr++; } } else { /* advance over to next option */ bptr += *bptr - 1; } } /* Bad? if we we need to send a config Reject */ if(bad) { /* write the config Rej packet we've built above, take on the header */ bptr = buffer; *bptr++ = CONF_REJ; /* Write Conf_rej */ bptr++; /* skip over ID */ *bptr++ = 0; *bptr = tptr - buffer; /* length right here? */ /* write the reject frame */ DEBUG1(("Writing Reject frame --\n")); ahdlc_tx(protocol, buffer, 0, (u16_t)(tptr - buffer), 0); DEBUG1(("\nEnd writing reject \n")); } return bad; } /*---------------------------------------------------------------------------*/