Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ipcp.c Source File

ipcp.c

Go to the documentation of this file.
00001 /**
00002  * @file ipcp.c
00003  * @brief IPCP (PPP Internet Protocol Control Protocol)
00004  *
00005  * @section License
00006  *
00007  * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
00008  *
00009  * This file is part of CycloneTCP Open.
00010  *
00011  * This program is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU General Public License
00013  * as published by the Free Software Foundation; either version 2
00014  * of the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software Foundation,
00023  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00024  *
00025  * @author Oryx Embedded SARL (www.oryx-embedded.com)
00026  * @version 1.7.6
00027  **/
00028 
00029 //Switch to the appropriate trace level
00030 #define TRACE_LEVEL PPP_TRACE_LEVEL
00031 
00032 //Dependencies
00033 #include "core/net.h"
00034 #include "ipv4/ipv4.h"
00035 #include "ppp/ppp_fsm.h"
00036 #include "ppp/ppp_misc.h"
00037 #include "ppp/ppp_debug.h"
00038 #include "ppp/ipcp.h"
00039 #include "debug.h"
00040 
00041 //Check TCP/IP stack configuration
00042 #if (PPP_SUPPORT == ENABLED && IPV4_SUPPORT == ENABLED)
00043 
00044 
00045 /**
00046  * @brief IPCP FSM callbacks
00047  **/
00048 
00049 const PppCallbacks ipcpCallbacks =
00050 {
00051    ipcpThisLayerUp,
00052    ipcpThisLayerDown,
00053    ipcpThisLayerStarted,
00054    ipcpThisLayerFinished,
00055    ipcpInitRestartCount,
00056    ipcpZeroRestartCount,
00057    ipcpSendConfigureReq,
00058    ipcpSendConfigureAck,
00059    ipcpSendConfigureNak,
00060    ipcpSendConfigureRej,
00061    ipcpSendTerminateReq,
00062    ipcpSendTerminateAck,
00063    ipcpSendCodeRej,
00064    NULL
00065 };
00066 
00067 
00068 /**
00069  * @brief IPCP Open event
00070  * @param[in] context PPP context
00071  * @return Error code
00072  **/
00073 
00074 error_t ipcpOpen(PppContext *context)
00075 {
00076    //Debug message
00077    TRACE_INFO("\r\nIPCP Open event\r\n");
00078 
00079    //The link is administratively available for traffic
00080    pppOpenEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00081    //The lower layer is ready to carry packets
00082    pppUpEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00083 
00084    //Successful processing
00085    return NO_ERROR;
00086 }
00087 
00088 
00089 /**
00090  * @brief IPCP Close event
00091  * @param[in] context PPP context
00092  * @return Error code
00093  **/
00094 
00095 error_t ipcpClose(PppContext *context)
00096 {
00097    //Debug message
00098    TRACE_INFO("\r\nIPCP Close event\r\n");
00099 
00100    //The lower layer is no longer ready to carry packets
00101    pppDownEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00102    //The link is no longer available for traffic
00103    pppCloseEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00104 
00105    //Successful processing
00106    return NO_ERROR;
00107 }
00108 
00109 
00110 /**
00111  * @brief IPCP timer handler
00112  *
00113  * This routine must be periodically called by the TCP/IP stack to
00114  * manage retransmissions
00115  *
00116  * @param[in] context PPP context
00117  **/
00118 
00119 void ipcpTick(PppContext *context)
00120 {
00121    //Check whether the restart timer is running
00122    if(context->ipcpFsm.state >= PPP_STATE_4_CLOSING &&
00123       context->ipcpFsm.state <= PPP_STATE_8_ACK_SENT)
00124    {
00125       //Get current time
00126       systime_t time = osGetSystemTime();
00127 
00128       //Check restart timer
00129       if((time - context->ipcpFsm.timestamp) >= PPP_RESTART_TIMER)
00130       {
00131          //Debug message
00132          TRACE_INFO("\r\nIPCP Timeout event\r\n");
00133 
00134          //The restart timer is used to retransmit Configure-Request
00135          //and Terminate-Request packets
00136          pppTimeoutEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00137       }
00138    }
00139 }
00140 
00141 
00142 /**
00143  * @brief Process an incoming IPCP packet
00144  * @param[in] context PPP context
00145  * @param[in]  packet IPCP packet received from the peer
00146  * @param[in] length Length of the packet, in bytes
00147  **/
00148 
00149 void ipcpProcessPacket(PppContext *context, const PppPacket *packet, size_t length)
00150 {
00151    //Ensure the length of the incoming IPCP packet is valid
00152    if(length < sizeof(PppPacket))
00153       return;
00154 
00155    //Check the length field
00156    if(ntohs(packet->length) > length)
00157       return;
00158    if(ntohs(packet->length) < sizeof(PppPacket))
00159       return;
00160 
00161    //Save the length of the IPCP packet
00162    length = ntohs(packet->length);
00163 
00164    //Debug message
00165    TRACE_INFO("IPCP packet received (%" PRIuSIZE " bytes)...\r\n", length);
00166    //Dump IPCP packet contents for debugging purpose
00167    pppDumpPacket(packet, length, PPP_PROTOCOL_IPCP);
00168 
00169    //Check IPCP code field
00170    switch(packet->code)
00171    {
00172    //Configure-Request packet?
00173    case PPP_CODE_CONFIGURE_REQ:
00174       //Process Configure-Request packet
00175       ipcpProcessConfigureReq(context, (PppConfigurePacket *) packet);
00176       break;
00177    //Configure-Ack packet?
00178    case PPP_CODE_CONFIGURE_ACK:
00179       //Process Configure-Ack packet
00180       ipcpProcessConfigureAck(context, (PppConfigurePacket *) packet);
00181       break;
00182    //Configure-Nak packet?
00183    case PPP_CODE_CONFIGURE_NAK:
00184       //Process Configure-Nak packet
00185       ipcpProcessConfigureNak(context, (PppConfigurePacket *) packet);
00186       break;
00187    //Configure-Reject packet?
00188    case PPP_CODE_CONFIGURE_REJ:
00189       //Process Configure-Reject packet
00190       ipcpProcessConfigureReject(context, (PppConfigurePacket *) packet);
00191       break;
00192    //Terminate-Request packet?
00193    case PPP_CODE_TERMINATE_REQ:
00194       //Process Terminate-Request packet
00195       ipcpProcessTerminateReq(context, (PppTerminatePacket *) packet);
00196       break;
00197    //Terminate-Ack packet?
00198    case PPP_CODE_TERMINATE_ACK:
00199       //Process Terminate-Ack packet
00200       ipcpProcessTerminateAck(context, (PppTerminatePacket *) packet);
00201       break;
00202    //Code-Reject packet?
00203    case PPP_CODE_CODE_REJ:
00204       //Process Code-Reject packet
00205       ipcpProcessCodeRej(context, (PppCodeRejPacket *) packet);
00206       break;
00207    //Unknown code field
00208    default:
00209       //The packet is un-interpretable
00210       ipcpProcessUnknownCode(context, packet);
00211       break;
00212    }
00213 }
00214 
00215 
00216 /**
00217  * @brief Process Configure-Request packet
00218  * @param[in] context PPP context
00219  * @param[in] configureReqPacket Packet received from the peer
00220  * @return Error code
00221  **/
00222 
00223 error_t ipcpProcessConfigureReq(PppContext *context,
00224    const PppConfigurePacket *configureReqPacket)
00225 {
00226    error_t error;
00227    size_t length;
00228    bool_t notRecognizable;
00229    bool_t notAcceptable;
00230    PppOption *option;
00231 
00232    //Debug message
00233    TRACE_INFO("\r\nIPCP Receive-Configure-Request event\r\n");
00234 
00235    //Initialize variables
00236    error = NO_ERROR;
00237    notRecognizable = FALSE;
00238    notAcceptable = FALSE;
00239 
00240    //Retrieve the length of the option list
00241    length = ntohs(configureReqPacket->length) - sizeof(PppConfigurePacket);
00242    //Point to the first option
00243    option = (PppOption *) configureReqPacket->options;
00244 
00245    //Parse configuration options
00246    while(length > 0)
00247    {
00248       //Parse current option
00249       error = ipcpParseOption(context, option, length, NULL);
00250 
00251       //Any error to report?
00252       if(error == ERROR_INVALID_TYPE)
00253       {
00254          //Option not recognizable
00255          notRecognizable = TRUE;
00256          //Catch error
00257          error = NO_ERROR;
00258       }
00259       else if(error == ERROR_INVALID_VALUE)
00260       {
00261          //Option not acceptable for configuration
00262          notAcceptable = TRUE;
00263          //Catch error
00264          error = NO_ERROR;
00265       }
00266       else if(error)
00267       {
00268          //Malformed Configure-Request packet
00269          break;
00270       }
00271 
00272       //Remaining bytes to process
00273       length -= option->length;
00274       //Jump to the next option
00275       option = (PppOption *) ((uint8_t *) option + option->length);
00276    }
00277 
00278    //Valid Configure-Request packet received from the peer?
00279    if(!error)
00280    {
00281       //Check flags
00282       if(notRecognizable)
00283       {
00284          //If some configuration options received in the Configure-Request are not
00285          //recognizable or not acceptable for negotiation, then the implementation
00286          //must transmit a Configure-Reject
00287          pppRcvConfigureReqEvent(context, &context->ipcpFsm, &ipcpCallbacks,
00288             configureReqPacket, PPP_CODE_CONFIGURE_REJ);
00289       }
00290       else if(notAcceptable)
00291       {
00292          //If all configuration options are recognizable, but some values are not
00293          //acceptable, then the implementation must transmit a Configure-Nak
00294          pppRcvConfigureReqEvent(context, &context->ipcpFsm, &ipcpCallbacks,
00295             configureReqPacket, PPP_CODE_CONFIGURE_NAK);
00296       }
00297       else
00298       {
00299          //If every configuration option received in the Configure-Request is
00300          //recognizable and all values are acceptable, then the implementation
00301          //must transmit a Configure-Ack
00302          pppRcvConfigureReqEvent(context, &context->ipcpFsm, &ipcpCallbacks,
00303             configureReqPacket, PPP_CODE_CONFIGURE_ACK);
00304       }
00305    }
00306 
00307    //Return status code
00308    return error;
00309 }
00310 
00311 
00312 /**
00313  * @brief Process Configure-Ack packet
00314  * @param[in] context PPP context
00315  * @param[in] configureAckPacket Packet received from the peer
00316  * @return Error code
00317  **/
00318 
00319 error_t ipcpProcessConfigureAck(PppContext *context,
00320    const PppConfigurePacket *configureAckPacket)
00321 {
00322    //Debug message
00323    TRACE_INFO("\r\nIPCP Receive-Configure-Ack event\r\n");
00324 
00325    //When a packet is received with an invalid Identifier field, the
00326    //packet is silently discarded without affecting the automaton
00327    if(configureAckPacket->identifier != context->ipcpFsm.identifier)
00328       return ERROR_WRONG_IDENTIFIER;
00329 
00330    //A valid Configure-Ack packet has been received from the peer
00331    pppRcvConfigureAckEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00332 
00333    //Successful processing
00334    return NO_ERROR;
00335 }
00336 
00337 
00338 /**
00339  * @brief Process Configure-Nak packet
00340  * @param[in] context PPP context
00341  * @param[in] configureNakPacket Packet received from the peer
00342  * @return Error code
00343  **/
00344 
00345 error_t ipcpProcessConfigureNak(PppContext *context,
00346    const PppConfigurePacket *configureNakPacket)
00347 {
00348    size_t length;
00349    PppOption *option;
00350 
00351    //Debug message
00352    TRACE_INFO("IPCP Receive-Configure-Nak event\r\n");
00353 
00354    //When a packet is received with an invalid Identifier field, the
00355    //packet is silently discarded without affecting the automaton
00356    if(configureNakPacket->identifier != context->ipcpFsm.identifier)
00357       return ERROR_WRONG_IDENTIFIER;
00358 
00359    //Retrieve the length of the option list
00360    length = ntohs(configureNakPacket->length) - sizeof(PppConfigurePacket);
00361    //Point to the first option
00362    option = (PppOption *) configureNakPacket->options;
00363 
00364    //Parse configuration options
00365    while(length > 0)
00366    {
00367       //Check option length
00368       if(option->length < sizeof(PppOption))
00369          return ERROR_INVALID_LENGTH;
00370       if(option->length > length)
00371          return ERROR_INVALID_LENGTH;
00372 
00373       //IP-Address option?
00374       if(option->type == IPCP_OPTION_IP_ADDRESS)
00375       {
00376          //Cast option
00377          IpcpIpAddressOption *ipAddressOption = (IpcpIpAddressOption *) option;
00378 
00379          //Check option length
00380          if(ipAddressOption->length != sizeof(IpcpIpAddressOption))
00381             return ERROR_INVALID_LENGTH;
00382 
00383          //Save IP address
00384          context->localConfig.ipAddr = ipAddressOption->ipAddr;
00385       }
00386       //Primary-DNS-Server-Address option?
00387       else if(option->type == IPCP_OPTION_PRIMARY_DNS)
00388       {
00389          //Cast option
00390          IpcpPrimaryDnsOption *primaryDns = (IpcpPrimaryDnsOption *) option;
00391 
00392          //Check option length
00393          if(primaryDns->length != sizeof(IpcpPrimaryDnsOption))
00394             return ERROR_INVALID_LENGTH;
00395 
00396          //Save primary DNS server address
00397          context->localConfig.primaryDns = primaryDns->ipAddr;
00398       }
00399       //Secondary-DNS-Server-Address option?
00400       else if(option->type == IPCP_OPTION_SECONDARY_DNS)
00401       {
00402          //Cast option
00403          IpcpSecondaryDnsOption *secondaryDns = (IpcpSecondaryDnsOption *) option;
00404 
00405          //Check option length
00406          if(secondaryDns->length != sizeof(IpcpSecondaryDnsOption))
00407             return ERROR_INVALID_LENGTH;
00408 
00409          //Save secondary DNS server address
00410          context->localConfig.secondaryDns = secondaryDns->ipAddr;
00411       }
00412 
00413       //Remaining bytes to process
00414       length -= option->length;
00415       //Jump to the next option
00416       option = (PppOption *) ((uint8_t *) option + option->length);
00417    }
00418 
00419    //A valid Configure-Nak or Configure-Reject packet has been received from the peer
00420    pppRcvConfigureNakEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00421 
00422    //Successful processing
00423    return NO_ERROR;
00424 }
00425 
00426 
00427 /**
00428  * @brief Process Configure-Reject packet
00429  * @param[in] context PPP context
00430  * @param[in] configureRejPacket Packet received from the peer
00431  * @return Error code
00432  **/
00433 
00434 error_t ipcpProcessConfigureReject(PppContext *context,
00435    const PppConfigurePacket *configureRejPacket)
00436 {
00437    size_t length;
00438    PppOption *option;
00439 
00440    //Debug message
00441    TRACE_INFO("\r\nIPCP Receive-Configure-Reject event\r\n");
00442 
00443    //When a packet is received with an invalid Identifier field, the
00444    //packet is silently discarded without affecting the automaton
00445    if(configureRejPacket->identifier != context->ipcpFsm.identifier)
00446       return ERROR_WRONG_IDENTIFIER;
00447 
00448    //Retrieve the length of the option list
00449    length = ntohs(configureRejPacket->length) - sizeof(PppConfigurePacket);
00450    //Point to the first option
00451    option = (PppOption *) configureRejPacket->options;
00452 
00453    //Parse configuration options
00454    while(length > 0)
00455    {
00456       //Check option length
00457       if(option->length < sizeof(PppOption))
00458          return ERROR_INVALID_LENGTH;
00459       if(option->length > length)
00460          return ERROR_INVALID_LENGTH;
00461 
00462       //IP-Address option?
00463       if(option->type == IPCP_OPTION_IP_ADDRESS)
00464       {
00465          //The option is not recognized by the peer
00466          context->localConfig.ipAddrRejected = TRUE;
00467       }
00468       //Primary-DNS-Server-Address option?
00469       else if(option->type == IPCP_OPTION_PRIMARY_DNS)
00470       {
00471          //The option is not recognized by the peer
00472          context->localConfig.primaryDnsRejected = TRUE;
00473       }
00474       //Secondary-DNS-Server-Address option?
00475       else if(option->type == IPCP_OPTION_SECONDARY_DNS)
00476       {
00477          //The option is not recognized by the peer
00478          context->localConfig.secondaryDnsRejected = TRUE;
00479       }
00480 
00481       //Remaining bytes to process
00482       length -= option->length;
00483       //Jump to the next option
00484       option = (PppOption *) ((uint8_t *) option + option->length);
00485    }
00486 
00487    //A valid Configure-Nak or Configure-Reject packet has been received from the peer
00488    pppRcvConfigureNakEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00489 
00490    //Successful processing
00491    return NO_ERROR;
00492 }
00493 
00494 
00495 /**
00496  * @brief Process Terminate-Request packet
00497  * @param[in] context PPP context
00498  * @param[in] terminateReqPacket Packet received from the peer
00499  * @return Error code
00500  **/
00501 
00502 error_t ipcpProcessTerminateReq(PppContext *context,
00503    const PppTerminatePacket *terminateReqPacket)
00504 {
00505    //Debug message
00506    TRACE_INFO("\r\nIPCP Receive-Terminate-Request event\r\n");
00507 
00508    //The Terminate-Request indicates the desire of the peer to close the connection
00509    pppRcvTerminateReqEvent(context, &context->ipcpFsm,
00510       &ipcpCallbacks, terminateReqPacket);
00511 
00512    //Successful processing
00513    return NO_ERROR;
00514 }
00515 
00516 
00517 /**
00518  * @brief Process Terminate-Ack packet
00519  * @param[in] context PPP context
00520  * @param[in] terminateAckPacket Packet received from the peer
00521  * @return Error code
00522  **/
00523 
00524 error_t ipcpProcessTerminateAck(PppContext *context,
00525    const PppTerminatePacket *terminateAckPacket)
00526 {
00527    //Debug message
00528    TRACE_INFO("\r\nIPCP Receive-Terminate-Ack event\r\n");
00529 
00530    //The Terminate-Ack packet is usually a response to a Terminate-Request
00531    //packet. This packet may also indicate that the peer is in Closed or
00532    //Stopped states, and serves to re-synchronize the link configuration
00533    pppRcvTerminateAckEvent(context, &context->ipcpFsm, &ipcpCallbacks);
00534 
00535    //Successful processing
00536    return NO_ERROR;
00537 }
00538 
00539 
00540 /**
00541  * @brief Process Code-Reject packet
00542  * @param[in] context PPP context
00543  * @param[in] codeRejPacket Packet received from the peer
00544  * @return Error code
00545  **/
00546 
00547 error_t ipcpProcessCodeRej(PppContext *context,
00548    const PppCodeRejPacket *codeRejPacket)
00549 {
00550    size_t length;
00551    PppPacket *packet;
00552 
00553    //Debug message
00554    TRACE_INFO("\r\nIPCP Receive-Code-Reject event\r\n");
00555 
00556    //Point to the rejected packet
00557    packet = (PppPacket *) codeRejPacket->rejectedPacket;
00558    //Retrieve the length of the rejected packet
00559    length = ntohs(codeRejPacket->length) - sizeof(PppCodeRejPacket);
00560 
00561    //Make sure the length of the rejected packet is valid
00562    if(length < sizeof(PppPacket))
00563       return ERROR_INVALID_LENGTH;
00564 
00565    //Check whether the rejected value is acceptable or catastrophic
00566    if(packet->code < PPP_CODE_CONFIGURE_REQ ||
00567       packet->code > PPP_CODE_CODE_REJ)
00568    {
00569       //The RXJ+ event arises when the rejected value is acceptable, such
00570       //as a Code-Reject of an extended code, or a Protocol-Reject of a
00571       //NCP. These are within the scope of normal operation
00572       pppRcvCodeRejEvent(context, &context->ipcpFsm, &ipcpCallbacks, TRUE);
00573    }
00574    else
00575    {
00576       //The RXJ- event arises when the rejected value is catastrophic, such
00577       //as a Code-Reject of Configure-Request! This event communicates an
00578       //unrecoverable error that terminates the connection
00579       pppRcvCodeRejEvent(context, &context->ipcpFsm, &ipcpCallbacks, FALSE);
00580    }
00581 
00582    //Successful processing
00583    return NO_ERROR;
00584 }
00585 
00586 
00587 /**
00588  * @brief Process packet with unknown code
00589  * @param[in] context PPP context
00590  * @param[in] packet Un-interpretable packet received from the peer
00591  * @return Error code
00592  **/
00593 
00594 error_t ipcpProcessUnknownCode(PppContext *context,
00595    const PppPacket *packet)
00596 {
00597    //Debug message
00598    TRACE_INFO("\r\nIPCP Receive-Unknown-Code event\r\n");
00599 
00600    //This event occurs when an un-interpretable packet is received from
00601    //the peer. A Code-Reject packet is sent in response
00602    pppRcvUnknownCodeEvent(context, &context->ipcpFsm, &ipcpCallbacks, packet);
00603 
00604    //Successful processing
00605    return NO_ERROR;
00606 }
00607 
00608 
00609 /**
00610  * @brief This-Layer-Up callback function
00611  * @param[in] context PPP context
00612  **/
00613 
00614 void ipcpThisLayerUp(PppContext *context)
00615 {
00616    NetInterface *interface;
00617 
00618    //Debug message
00619    TRACE_INFO("IPCP This-Layer-Up callback\r\n");
00620 
00621    //Debug message
00622    TRACE_INFO("  Local IP Addr = %s\r\n", ipv4AddrToString(context->localConfig.ipAddr, NULL));
00623    TRACE_INFO("  Peer IP Addr = %s\r\n", ipv4AddrToString(context->peerConfig.ipAddr, NULL));
00624    TRACE_INFO("  Primary DNS = %s\r\n", ipv4AddrToString(context->localConfig.primaryDns, NULL));
00625    TRACE_INFO("  Secondary DNS = %s\r\n", ipv4AddrToString(context->localConfig.secondaryDns, NULL));
00626 
00627    //Point to the underlying interface
00628    interface = context->interface;
00629 
00630    //Update IPv4 configuration
00631    interface->ipv4Context.addr = context->localConfig.ipAddr;
00632    interface->ipv4Context.addrState = IPV4_ADDR_STATE_VALID;
00633    interface->ipv4Context.defaultGateway = context->peerConfig.ipAddr;
00634 
00635    //Update the list of DNS servers
00636    interface->ipv4Context.dnsServerList[0] = context->localConfig.primaryDns;
00637 #if (IPV4_DNS_SERVER_LIST_SIZE >= 2)
00638    interface->ipv4Context.dnsServerList[1] = context->localConfig.secondaryDns;
00639 #endif
00640 
00641    //All the outgoing traffic will be routed to the other end of the link
00642    interface->ipv4Context.subnetMask = IPCP_DEFAULT_SUBNET_MASK;
00643 
00644    //Link is up
00645    interface->linkState = TRUE;
00646 
00647    //Disable interrupts
00648    interface->nicDriver->disableIrq(interface);
00649    //Process link state change event
00650    nicNotifyLinkChange(interface);
00651    //Re-enable interrupts
00652    interface->nicDriver->enableIrq(interface);
00653 }
00654 
00655 
00656 /**
00657  * @brief This-Layer-Down callback function
00658  * @param[in] context PPP context
00659  **/
00660 
00661 void ipcpThisLayerDown(PppContext *context)
00662 {
00663    NetInterface *interface;
00664 
00665    //Debug message
00666    TRACE_INFO("IPCP This-Layer-Down callback\r\n");
00667 
00668    //Point to the underlying interface
00669    interface = context->interface;
00670 
00671    //Link is up
00672    interface->linkState = FALSE;
00673 
00674    //Disable interrupts
00675    interface->nicDriver->disableIrq(interface);
00676    //Process link state change event
00677    nicNotifyLinkChange(interface);
00678    //Re-enable interrupts
00679    interface->nicDriver->enableIrq(interface);
00680 }
00681 
00682 
00683 /**
00684  * @brief This-Layer-Started callback function
00685  * @param[in] context PPP context
00686  **/
00687 
00688 void ipcpThisLayerStarted(PppContext *context)
00689 {
00690    //Debug message
00691    TRACE_INFO("IPCP This-Layer-Started callback\r\n");
00692 }
00693 
00694 
00695 /**
00696  * @brief This-Layer-Finished callback function
00697  * @param[in] context PPP context
00698  **/
00699 
00700 void ipcpThisLayerFinished(PppContext *context)
00701 {
00702    //Debug message
00703    TRACE_INFO("IPCP This-Layer-Finished callback\r\n");
00704 }
00705 
00706 
00707 /**
00708  * @brief Initialize-Restart-Count callback function
00709  * @param[in] context PPP context
00710  * @param[in] value Restart counter value
00711  **/
00712 
00713 void ipcpInitRestartCount(PppContext *context, uint_t value)
00714 {
00715    //Debug message
00716    TRACE_INFO("IPCP Initialize-Restart-Count callback\r\n");
00717 
00718    //Initialize restart counter
00719    context->ipcpFsm.restartCounter = value;
00720 }
00721 
00722 
00723 /**
00724  * @brief Zero-Restart-Count callback function
00725  * @param[in] context PPP context
00726  **/
00727 
00728 void ipcpZeroRestartCount(PppContext *context)
00729 {
00730    //Debug message
00731    TRACE_INFO("IPCP Zero-Restart-Count callback\r\n");
00732 
00733    //Zero restart counter
00734    context->ipcpFsm.restartCounter = 0;
00735 
00736    //The receiver of a Terminate-Request should wait for the peer to
00737    //disconnect, and must not disconnect until at least one Restart
00738    //time has passed after sending a Terminate-Ack
00739    context->ipcpFsm.timestamp = osGetSystemTime();
00740 }
00741 
00742 
00743 /**
00744  * @brief Send-Configure-Request callback function
00745  * @param[in] context PPP context
00746  * @return Error code
00747  **/
00748 
00749 error_t ipcpSendConfigureReq(PppContext *context)
00750 {
00751    error_t error;
00752    size_t length;
00753    size_t offset;
00754    NetBuffer *buffer;
00755    PppConfigurePacket *configureReqPacket;
00756 
00757    //Debug message
00758    TRACE_INFO("IPCP Send-Configure-Request callback\r\n");
00759 
00760    //Allocate a buffer memory to hold the Configure-Request packet
00761    buffer = pppAllocBuffer(PPP_MAX_CONF_REQ_SIZE, &offset);
00762    //Failed to allocate memory?
00763    if(buffer == NULL)
00764       return ERROR_OUT_OF_MEMORY;
00765 
00766    //Point to the Configure-Request packet
00767    configureReqPacket = netBufferAt(buffer, offset);
00768 
00769    //Format packet header
00770    configureReqPacket->code = PPP_CODE_CONFIGURE_REQ;
00771    configureReqPacket->identifier = ++context->ipcpFsm.identifier;
00772    configureReqPacket->length = sizeof(PppConfigurePacket);
00773 
00774    //Make sure the IP-Address option has not been previously rejected
00775    if(!context->localConfig.ipAddrRejected)
00776    {
00777       //Add option
00778       pppAddOption(configureReqPacket, IPCP_OPTION_IP_ADDRESS,
00779          &context->localConfig.ipAddr, sizeof(Ipv4Addr));
00780    }
00781 
00782    //Make sure the Primary-DNS-Server-Address option has not been
00783    //previously rejected
00784    if(!context->localConfig.primaryDnsRejected)
00785    {
00786       //Add option
00787       pppAddOption(configureReqPacket, IPCP_OPTION_PRIMARY_DNS,
00788          &context->localConfig.primaryDns, sizeof(Ipv4Addr));
00789    }
00790 
00791    //Make sure the Secondary-DNS-Server-Address option has not been
00792    //previously rejected
00793    if(!context->localConfig.secondaryDnsRejected)
00794    {
00795       //Add option
00796       pppAddOption(configureReqPacket, IPCP_OPTION_SECONDARY_DNS,
00797          &context->localConfig.secondaryDns, sizeof(Ipv4Addr));
00798    }
00799 
00800    //Save packet length
00801    length = configureReqPacket->length;
00802    //Convert length field to network byte order
00803    configureReqPacket->length = htons(length);
00804 
00805    //Adjust the length of the multi-part buffer
00806    netBufferSetLength(buffer, offset + length);
00807 
00808    //Debug message
00809    TRACE_INFO("Sending Configure-Request packet (%" PRIuSIZE " bytes)...\r\n", length);
00810    //Dump packet contents for debugging purpose
00811    pppDumpPacket((PppPacket *) configureReqPacket, length, PPP_PROTOCOL_IPCP);
00812 
00813    //Send PPP frame
00814    error = pppSendFrame(context->interface, buffer, offset, PPP_PROTOCOL_IPCP);
00815 
00816    //The restart counter is decremented each time a Configure-Request is sent
00817    if(context->ipcpFsm.restartCounter > 0)
00818       context->ipcpFsm.restartCounter--;
00819 
00820    //Save the time at which the packet was sent
00821    context->ipcpFsm.timestamp = osGetSystemTime();
00822 
00823    //Free previously allocated memory block
00824    netBufferFree(buffer);
00825    //Return status code
00826    return error;
00827 }
00828 
00829 
00830 /**
00831  * @brief Send-Configure-Ack callback function
00832  * @param[in] context PPP context
00833  * @param[in] configureReqPacket Configure-Request packet received from the peer
00834  * @return Error code
00835  **/
00836 
00837 error_t ipcpSendConfigureAck(PppContext *context,
00838    const PppConfigurePacket *configureReqPacket)
00839 {
00840    //Debug message
00841    TRACE_INFO("IPCP Send-Configure-Ack callback\r\n");
00842 
00843    //Send Configure-Ack packet
00844    return pppSendConfigureAckNak(context, configureReqPacket,
00845       PPP_PROTOCOL_IPCP, PPP_CODE_CONFIGURE_ACK);
00846 }
00847 
00848 
00849 /**
00850  * @brief Send-Configure-Nak callback function
00851  * @param[in] context PPP context
00852  * @param[in] configureReqPacket Configure-Request packet received from the peer
00853  * @return Error code
00854  **/
00855 
00856 error_t ipcpSendConfigureNak(PppContext *context,
00857    const PppConfigurePacket *configureReqPacket)
00858 {
00859    //Debug message
00860    TRACE_INFO("IPCP Send-Configure-Nak callback\r\n");
00861 
00862    //Send Configure-Nak packet
00863    return pppSendConfigureAckNak(context, configureReqPacket,
00864       PPP_PROTOCOL_IPCP, PPP_CODE_CONFIGURE_NAK);
00865 }
00866 
00867 
00868 /**
00869  * @brief Send-Configure-Reject callback function
00870  * @param[in] context PPP context
00871  * @param[in] configureReqPacket Configure-Request packet received from the peer
00872  * @return Error code
00873  **/
00874 
00875 error_t ipcpSendConfigureRej(PppContext *context,
00876    const PppConfigurePacket *configureReqPacket)
00877 {
00878    //Debug message
00879    TRACE_INFO("IPCP Send-Configure-Reject callback\r\n");
00880 
00881    //Send Configure-Reject packet
00882    return pppSendConfigureAckNak(context, configureReqPacket,
00883       PPP_PROTOCOL_IPCP, PPP_CODE_CONFIGURE_REJ);
00884 }
00885 
00886 
00887 /**
00888  * @brief Send-Terminate-Request callback function
00889  * @param[in] context PPP context
00890  * @return Error code
00891  **/
00892 
00893 error_t ipcpSendTerminateReq(PppContext *context)
00894 {
00895    error_t error;
00896 
00897    //Debug message
00898    TRACE_INFO("IPCP Send-Terminate-Request callback\r\n");
00899 
00900    //On transmission, the Identifier field must be changed
00901    context->ipcpFsm.identifier++;
00902 
00903    //Send Terminate-Request packet
00904    error = pppSendTerminateReq(context, context->ipcpFsm.identifier, PPP_PROTOCOL_IPCP);
00905 
00906    //The restart counter is decremented each time a Terminate-Request is sent
00907    if(context->ipcpFsm.restartCounter > 0)
00908       context->ipcpFsm.restartCounter--;
00909 
00910    //Save the time at which the packet was sent
00911    context->ipcpFsm.timestamp = osGetSystemTime();
00912 
00913    //Return status code
00914    return error;
00915 }
00916 
00917 
00918 /**
00919  * @brief Send-Terminate-Ack callback function
00920  * @param[in] context PPP context
00921  * @param[in] terminateReqPacket Terminate-Request packet received from the peer
00922  * @return Error code
00923  **/
00924 
00925 error_t ipcpSendTerminateAck(PppContext *context,
00926    const PppTerminatePacket *terminateReqPacket)
00927 {
00928    uint8_t identifier;
00929 
00930    //Debug message
00931    TRACE_INFO("IPCP Send-Terminate-Ack callback\r\n");
00932 
00933    //Check whether this Terminate-Ack acknowledges the reception of a
00934    //Terminate-Request packet
00935    if(terminateReqPacket != NULL)
00936    {
00937       //The Identifier field of the Terminate-Request is copied into the
00938       //Identifier field of the Terminate-Ack packet
00939       identifier = terminateReqPacket->identifier;
00940    }
00941    else
00942    {
00943       //This Terminate-Ack packet serves to synchronize the automatons
00944       identifier = ++context->ipcpFsm.identifier;
00945    }
00946 
00947    //Send Terminate-Ack packet
00948    return pppSendTerminateAck(context, identifier, PPP_PROTOCOL_IPCP);
00949 }
00950 
00951 
00952 /**
00953  * @brief Send-Code-Reject callback function
00954  * @param[in] context PPP context
00955  * @param[in] packet Un-interpretable packet received from the peer
00956  * @return Error code
00957  **/
00958 
00959 error_t ipcpSendCodeRej(PppContext *context, const PppPacket *packet)
00960 {
00961    //Debug message
00962    TRACE_INFO("IPCP Send-Code-Reject callback\r\n");
00963 
00964    //The Identifier field must be changed for each Code-Reject sent
00965    context->ipcpFsm.identifier++;
00966 
00967    //Send Code-Reject packet
00968    return pppSendCodeRej(context, packet, context->ipcpFsm.identifier, PPP_PROTOCOL_IPCP);
00969 }
00970 
00971 
00972 /**
00973  * @brief Parse IPCP configuration option
00974  * @param[in] context PPP context
00975  * @param[in] option Option to be checked
00976  * @param[in] inPacketLen Remaining bytes to process in the incoming packet
00977  * @param[out] outPacket Pointer to the Configure-Ack, Nak or Reject packet
00978  * @return Error code
00979  **/
00980 
00981 error_t ipcpParseOption(PppContext *context, PppOption *option,
00982    size_t inPacketLen, PppConfigurePacket *outPacket)
00983 {
00984    error_t error;
00985 
00986    //Malformed IPCP packet?
00987    if(inPacketLen < sizeof(PppOption))
00988       return ERROR_INVALID_LENGTH;
00989 
00990    //Check option length
00991    if(option->length < sizeof(PppOption))
00992       return ERROR_INVALID_LENGTH;
00993    if(option->length > inPacketLen)
00994       return ERROR_INVALID_LENGTH;
00995 
00996    //Check option type
00997    switch(option->type)
00998    {
00999    case IPCP_OPTION_IP_ADDRESS:
01000       //Check IP-Address option
01001       error = ipcpParseIpAddressOption(context, (IpcpIpAddressOption *) option, outPacket);
01002       break;
01003    default:
01004       //If some configuration options received in the Configure-Request are not
01005       //recognizable or not acceptable for negotiation, then the implementation
01006       //must transmit a Configure-Reject
01007       if(outPacket->code == PPP_CODE_CONFIGURE_REJ)
01008       {
01009          //The options field of the Configure-Reject packet is filled
01010          //with the unrecognized options from the Configure-Request
01011          pppAddOption(outPacket, option->type, option->data,
01012             option->length - sizeof(PppOption));
01013       }
01014 
01015       //The option is not acceptable for negotiation
01016       error = ERROR_INVALID_TYPE;
01017       break;
01018    }
01019 
01020    //Return status code
01021    return error;
01022 }
01023 
01024 
01025 /**
01026  * @brief Parse IP-Address option
01027  * @param[in] context PPP context
01028  * @param[in] option Option to be checked
01029  * @param[out] outPacket Pointer to the Configure-Nak or Configure-Reject packet
01030  * @return Error code
01031  **/
01032 
01033 error_t ipcpParseIpAddressOption(PppContext *context,
01034    IpcpIpAddressOption *option, PppConfigurePacket *outPacket)
01035 {
01036    error_t error;
01037 
01038    //Check length field
01039    if(option->length == sizeof(IpcpIpAddressOption))
01040    {
01041       //Check whether the option value is acceptable
01042       if(option->ipAddr != IPV4_UNSPECIFIED_ADDR)
01043       {
01044          //If every configuration option received in the Configure-Request is
01045          //recognizable and all values are acceptable, then the implementation
01046          //must transmit a Configure-Ack
01047          if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_ACK)
01048          {
01049             //Save IP address
01050             context->peerConfig.ipAddr = option->ipAddr;
01051 
01052             //The options field of the Configure-Ack packet contains the
01053             //configuration options that the sender is acknowledging
01054             pppAddOption(outPacket, IPCP_OPTION_IP_ADDRESS,
01055                (void *) &option->ipAddr, option->length - sizeof(PppOption));
01056          }
01057 
01058          //The value is acceptable
01059          error = NO_ERROR;
01060       }
01061       else
01062       {
01063          //If all configuration options are recognizable, but some values are not
01064          //acceptable, then the implementation must transmit a Configure-Nak
01065          if(outPacket != NULL && outPacket->code == PPP_CODE_CONFIGURE_NAK)
01066          {
01067             //The option must be modified to a value acceptable to the
01068             //Configure-Nak sender
01069             pppAddOption(outPacket, IPCP_OPTION_IP_ADDRESS,
01070                &context->peerConfig.ipAddr, sizeof(Ipv4Addr));
01071          }
01072 
01073          //The value is not acceptable
01074          error = ERROR_INVALID_VALUE;
01075       }
01076    }
01077    else
01078    {
01079       //Invalid length field
01080       error = ERROR_INVALID_LENGTH;
01081    }
01082 
01083    //Return status code
01084    return error;
01085 }
01086 
01087 #endif
01088