Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
lwip_ppp.c
00001 /***************************************************************************** 00002 * ppp.c - Network Point to Point Protocol program file. 00003 * 00004 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc. 00005 * portions Copyright (c) 1997 by Global Election Systems Inc. 00006 * 00007 * The authors hereby grant permission to use, copy, modify, distribute, 00008 * and license this software and its documentation for any purpose, provided 00009 * that existing copyright notices are retained in all copies and that this 00010 * notice and the following disclaimer are included verbatim in any 00011 * distributions. No written agreement, license, or royalty fee is required 00012 * for any of the authorized uses. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 * 00025 ****************************************************************************** 00026 * REVISION HISTORY 00027 * 00028 * 03-01-01 Marc Boucher <marc@mbsi.ca> 00029 * Ported to lwIP. 00030 * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc. 00031 * Original. 00032 *****************************************************************************/ 00033 00034 /* 00035 * ppp_defs.h - PPP definitions. 00036 * 00037 * if_pppvar.h - private structures and declarations for PPP. 00038 * 00039 * Copyright (c) 1994 The Australian National University. 00040 * All rights reserved. 00041 * 00042 * Permission to use, copy, modify, and distribute this software and its 00043 * documentation is hereby granted, provided that the above copyright 00044 * notice appears in all copies. This software is provided without any 00045 * warranty, express or implied. The Australian National University 00046 * makes no representations about the suitability of this software for 00047 * any purpose. 00048 * 00049 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY 00050 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 00051 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 00052 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY 00053 * OF SUCH DAMAGE. 00054 * 00055 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, 00056 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00057 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 00058 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO 00059 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 00060 * OR MODIFICATIONS. 00061 */ 00062 00063 /* 00064 * if_ppp.h - Point-to-Point Protocol definitions. 00065 * 00066 * Copyright (c) 1989 Carnegie Mellon University. 00067 * All rights reserved. 00068 * 00069 * Redistribution and use in source and binary forms are permitted 00070 * provided that the above copyright notice and this paragraph are 00071 * duplicated in all such forms and that any documentation, 00072 * advertising materials, and other materials related to such 00073 * distribution and use acknowledge that the software was developed 00074 * by Carnegie Mellon University. The name of the 00075 * University may not be used to endorse or promote products derived 00076 * from this software without specific prior written permission. 00077 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 00078 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 00079 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00080 */ 00081 00082 /** 00083 * @defgroup ppp PPP netif 00084 * @ingroup addons 00085 * @verbinclude "ppp.txt" 00086 */ 00087 00088 #include "netif/ppp/ppp_opts.h" 00089 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00090 00091 #include "lwip/pbuf.h" 00092 #include "lwip/stats.h" 00093 #include "lwip/sys.h" 00094 #include "lwip/tcpip.h" 00095 #include "lwip/api.h" 00096 #include "lwip/snmp.h" 00097 #include "lwip/ip4.h" /* for ip4_input() */ 00098 #if PPP_IPV6_SUPPORT 00099 #include "lwip/ip6.h" /* for ip6_input() */ 00100 #endif /* PPP_IPV6_SUPPORT */ 00101 #include "lwip/dns.h" 00102 00103 #include "netif/ppp/ppp_impl.h" 00104 #include "netif/ppp/pppos.h" 00105 00106 #include "netif/ppp/fsm.h" 00107 #include "netif/ppp/lcp.h" 00108 #include "netif/ppp/magic.h" 00109 00110 #if PAP_SUPPORT 00111 #include "netif/ppp/upap.h" 00112 #endif /* PAP_SUPPORT */ 00113 #if CHAP_SUPPORT 00114 #include "netif/ppp/chap-new.h" 00115 #endif /* CHAP_SUPPORT */ 00116 #if EAP_SUPPORT 00117 #include "netif/ppp/eap.h" 00118 #endif /* EAP_SUPPORT */ 00119 #if CCP_SUPPORT 00120 #include "netif/ppp/ccp.h" 00121 #endif /* CCP_SUPPORT */ 00122 #if MPPE_SUPPORT 00123 #include "netif/ppp/mppe.h" 00124 #endif /* MPPE_SUPPORT */ 00125 #if ECP_SUPPORT 00126 #include "netif/ppp/ecp.h" 00127 #endif /* EAP_SUPPORT */ 00128 #if VJ_SUPPORT 00129 #include "netif/ppp/vj.h" 00130 #endif /* VJ_SUPPORT */ 00131 #if PPP_IPV4_SUPPORT 00132 #include "netif/ppp/ipcp.h" 00133 #endif /* PPP_IPV4_SUPPORT */ 00134 #if PPP_IPV6_SUPPORT 00135 #include "netif/ppp/ipv6cp.h" 00136 #endif /* PPP_IPV6_SUPPORT */ 00137 00138 /*************************/ 00139 /*** LOCAL DEFINITIONS ***/ 00140 /*************************/ 00141 00142 /* Memory pools */ 00143 #if PPPOS_SUPPORT 00144 LWIP_MEMPOOL_PROTOTYPE(PPPOS_PCB); 00145 #endif 00146 #if PPPOE_SUPPORT 00147 LWIP_MEMPOOL_PROTOTYPE(PPPOE_IF); 00148 #endif 00149 #if PPPOL2TP_SUPPORT 00150 LWIP_MEMPOOL_PROTOTYPE(PPPOL2TP_PCB); 00151 #endif 00152 #if LWIP_PPP_API && LWIP_MPU_COMPATIBLE 00153 LWIP_MEMPOOL_PROTOTYPE(PPPAPI_MSG); 00154 #endif 00155 LWIP_MEMPOOL_DECLARE(PPP_PCB, MEMP_NUM_PPP_PCB, sizeof(ppp_pcb), "PPP_PCB") 00156 00157 /* FIXME: add stats per PPP session */ 00158 #if PPP_STATS_SUPPORT 00159 static struct timeval start_time; /* Time when link was started. */ 00160 static struct pppd_stats old_link_stats; 00161 struct pppd_stats link_stats; 00162 unsigned link_connect_time; 00163 int link_stats_valid; 00164 #endif /* PPP_STATS_SUPPORT */ 00165 00166 /* 00167 * PPP Data Link Layer "protocol" table. 00168 * One entry per supported protocol. 00169 * The last entry must be NULL. 00170 */ 00171 const struct protent* const protocols[] = { 00172 &lcp_protent, 00173 #if PAP_SUPPORT 00174 &pap_protent, 00175 #endif /* PAP_SUPPORT */ 00176 #if CHAP_SUPPORT 00177 &chap_protent, 00178 #endif /* CHAP_SUPPORT */ 00179 #if CBCP_SUPPORT 00180 &cbcp_protent, 00181 #endif /* CBCP_SUPPORT */ 00182 #if PPP_IPV4_SUPPORT 00183 &ipcp_protent, 00184 #endif /* PPP_IPV4_SUPPORT */ 00185 #if PPP_IPV6_SUPPORT 00186 &ipv6cp_protent, 00187 #endif /* PPP_IPV6_SUPPORT */ 00188 #if CCP_SUPPORT 00189 &ccp_protent, 00190 #endif /* CCP_SUPPORT */ 00191 #if ECP_SUPPORT 00192 &ecp_protent, 00193 #endif /* ECP_SUPPORT */ 00194 #ifdef AT_CHANGE 00195 &atcp_protent, 00196 #endif /* AT_CHANGE */ 00197 #if EAP_SUPPORT 00198 &eap_protent, 00199 #endif /* EAP_SUPPORT */ 00200 NULL 00201 }; 00202 00203 /* Prototypes for procedures local to this file. */ 00204 static void ppp_do_connect(void *arg); 00205 static err_t ppp_netif_init_cb(struct netif *netif); 00206 #if LWIP_IPV4 00207 static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr); 00208 #endif /* LWIP_IPV4 */ 00209 #if PPP_IPV6_SUPPORT 00210 static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr); 00211 #endif /* PPP_IPV6_SUPPORT */ 00212 static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol); 00213 00214 /***********************************/ 00215 /*** PUBLIC FUNCTION DEFINITIONS ***/ 00216 /***********************************/ 00217 #if PPP_AUTH_SUPPORT 00218 void ppp_set_auth(ppp_pcb *pcb, u8_t authtype, const char *user, const char *passwd) { 00219 #if PAP_SUPPORT 00220 pcb->settings.refuse_pap = !(authtype & PPPAUTHTYPE_PAP); 00221 #endif /* PAP_SUPPORT */ 00222 #if CHAP_SUPPORT 00223 pcb->settings.refuse_chap = !(authtype & PPPAUTHTYPE_CHAP); 00224 #if MSCHAP_SUPPORT 00225 pcb->settings.refuse_mschap = !(authtype & PPPAUTHTYPE_MSCHAP); 00226 pcb->settings.refuse_mschap_v2 = !(authtype & PPPAUTHTYPE_MSCHAP_V2); 00227 #endif /* MSCHAP_SUPPORT */ 00228 #endif /* CHAP_SUPPORT */ 00229 #if EAP_SUPPORT 00230 pcb->settings.refuse_eap = !(authtype & PPPAUTHTYPE_EAP); 00231 #endif /* EAP_SUPPORT */ 00232 pcb->settings.user = user; 00233 pcb->settings.passwd = passwd; 00234 } 00235 #endif /* PPP_AUTH_SUPPORT */ 00236 00237 #if MPPE_SUPPORT 00238 /* Set MPPE configuration */ 00239 void ppp_set_mppe(ppp_pcb *pcb, u8_t flags) { 00240 if (flags == PPP_MPPE_DISABLE) { 00241 pcb->settings.require_mppe = 0; 00242 return; 00243 } 00244 00245 pcb->settings.require_mppe = 1; 00246 pcb->settings.refuse_mppe_stateful = !(flags & PPP_MPPE_ALLOW_STATEFUL); 00247 pcb->settings.refuse_mppe_40 = !!(flags & PPP_MPPE_REFUSE_40); 00248 pcb->settings.refuse_mppe_128 = !!(flags & PPP_MPPE_REFUSE_128); 00249 } 00250 #endif /* MPPE_SUPPORT */ 00251 00252 #if PPP_NOTIFY_PHASE 00253 void ppp_set_notify_phase_callback(ppp_pcb *pcb, ppp_notify_phase_cb_fn notify_phase_cb) { 00254 pcb->notify_phase_cb = notify_phase_cb; 00255 notify_phase_cb(pcb, pcb->phase, pcb->ctx_cb); 00256 } 00257 #endif /* PPP_NOTIFY_PHASE */ 00258 00259 /* 00260 * Initiate a PPP connection. 00261 * 00262 * This can only be called if PPP is in the dead phase. 00263 * 00264 * Holdoff is the time to wait (in seconds) before initiating 00265 * the connection. 00266 * 00267 * If this port connects to a modem, the modem connection must be 00268 * established before calling this. 00269 */ 00270 err_t ppp_connect(ppp_pcb *pcb, u16_t holdoff) { 00271 if (pcb->phase != PPP_PHASE_DEAD) { 00272 return ERR_ALREADY; 00273 } 00274 00275 PPPDEBUG(LOG_DEBUG, ("ppp_connect[%d]: holdoff=%d\n", pcb->netif->num, holdoff)); 00276 00277 if (holdoff == 0) { 00278 ppp_do_connect(pcb); 00279 return ERR_OK; 00280 } 00281 00282 new_phase(pcb, PPP_PHASE_HOLDOFF); 00283 sys_timeout((u32_t)(holdoff*1000), ppp_do_connect, pcb); 00284 return ERR_OK; 00285 } 00286 00287 #if PPP_SERVER 00288 /* 00289 * Listen for an incoming PPP connection. 00290 * 00291 * This can only be called if PPP is in the dead phase. 00292 * 00293 * If this port connects to a modem, the modem connection must be 00294 * established before calling this. 00295 */ 00296 err_t ppp_listen(ppp_pcb *pcb) { 00297 if (pcb->phase != PPP_PHASE_DEAD) { 00298 return ERR_ALREADY; 00299 } 00300 00301 PPPDEBUG(LOG_DEBUG, ("ppp_listen[%d]\n", pcb->netif->num)); 00302 00303 if (pcb->link_cb->listen) { 00304 new_phase(pcb, PPP_PHASE_INITIALIZE); 00305 pcb->link_cb->listen(pcb, pcb->link_ctx_cb); 00306 return ERR_OK; 00307 } 00308 return ERR_IF; 00309 } 00310 #endif /* PPP_SERVER */ 00311 00312 /* 00313 * Initiate the end of a PPP connection. 00314 * Any outstanding packets in the queues are dropped. 00315 * 00316 * Setting nocarrier to 1 close the PPP connection without initiating the 00317 * shutdown procedure. Always using nocarrier = 0 is still recommended, 00318 * this is going to take a little longer time if your link is down, but 00319 * is a safer choice for the PPP state machine. 00320 * 00321 * Return 0 on success, an error code on failure. 00322 */ 00323 err_t 00324 ppp_close(ppp_pcb *pcb, u8_t nocarrier) 00325 { 00326 pcb->err_code = PPPERR_USER; 00327 00328 /* holdoff phase, cancel the reconnection */ 00329 if (pcb->phase == PPP_PHASE_HOLDOFF) { 00330 sys_untimeout(ppp_do_connect, pcb); 00331 new_phase(pcb, PPP_PHASE_DEAD); 00332 } 00333 00334 /* dead phase, nothing to do, call the status callback to be consistent */ 00335 if (pcb->phase == PPP_PHASE_DEAD) { 00336 pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); 00337 return ERR_OK; 00338 } 00339 00340 /* Already terminating, nothing to do */ 00341 if (pcb->phase >= PPP_PHASE_TERMINATE) { 00342 return ERR_INPROGRESS; 00343 } 00344 00345 /* LCP not open, close link protocol */ 00346 if (pcb->phase < PPP_PHASE_ESTABLISH) { 00347 new_phase(pcb, PPP_PHASE_DISCONNECT); 00348 ppp_link_terminated(pcb); 00349 return ERR_OK; 00350 } 00351 00352 /* 00353 * Only accept carrier lost signal on the stable running phase in order 00354 * to prevent changing the PPP phase FSM in transition phases. 00355 * 00356 * Always using nocarrier = 0 is still recommended, this is going to 00357 * take a little longer time, but is a safer choice from FSM point of view. 00358 */ 00359 if (nocarrier && pcb->phase == PPP_PHASE_RUNNING) { 00360 PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: carrier lost -> lcp_lowerdown\n", pcb->netif->num)); 00361 lcp_lowerdown(pcb); 00362 /* forced link termination, this will force link protocol to disconnect. */ 00363 link_terminated(pcb); 00364 return ERR_OK; 00365 } 00366 00367 /* Disconnect */ 00368 PPPDEBUG(LOG_DEBUG, ("ppp_close[%d]: kill_link -> lcp_close\n", pcb->netif->num)); 00369 /* LCP soft close request. */ 00370 lcp_close(pcb, "User request"); 00371 return ERR_OK; 00372 } 00373 00374 /* 00375 * Release the control block. 00376 * 00377 * This can only be called if PPP is in the dead phase. 00378 * 00379 * You must use ppp_close() before if you wish to terminate 00380 * an established PPP session. 00381 * 00382 * Return 0 on success, an error code on failure. 00383 */ 00384 err_t ppp_free(ppp_pcb *pcb) { 00385 err_t err; 00386 if (pcb->phase != PPP_PHASE_DEAD) { 00387 return ERR_CONN; 00388 } 00389 00390 PPPDEBUG(LOG_DEBUG, ("ppp_free[%d]\n", pcb->netif->num)); 00391 00392 netif_remove(pcb->netif); 00393 00394 err = pcb->link_cb->free(pcb, pcb->link_ctx_cb); 00395 00396 LWIP_MEMPOOL_FREE(PPP_PCB, pcb); 00397 return err; 00398 } 00399 00400 /* Get and set parameters for the given connection. 00401 * Return 0 on success, an error code on failure. */ 00402 err_t 00403 ppp_ioctl(ppp_pcb *pcb, u8_t cmd, void *arg) 00404 { 00405 if (pcb == NULL) { 00406 return ERR_VAL; 00407 } 00408 00409 switch(cmd) { 00410 case PPPCTLG_UPSTATUS: /* Get the PPP up status. */ 00411 if (!arg) { 00412 goto fail; 00413 } 00414 *(int *)arg = (int)(0 00415 #if PPP_IPV4_SUPPORT 00416 || pcb->if4_up 00417 #endif /* PPP_IPV4_SUPPORT */ 00418 #if PPP_IPV6_SUPPORT 00419 || pcb->if6_up 00420 #endif /* PPP_IPV6_SUPPORT */ 00421 ); 00422 return ERR_OK; 00423 00424 case PPPCTLG_ERRCODE: /* Get the PPP error code. */ 00425 if (!arg) { 00426 goto fail; 00427 } 00428 *(int *)arg = (int)(pcb->err_code); 00429 return ERR_OK; 00430 00431 default: 00432 goto fail; 00433 } 00434 00435 fail: 00436 return ERR_VAL; 00437 } 00438 00439 00440 /**********************************/ 00441 /*** LOCAL FUNCTION DEFINITIONS ***/ 00442 /**********************************/ 00443 00444 static void ppp_do_connect(void *arg) { 00445 ppp_pcb *pcb = (ppp_pcb*)arg; 00446 00447 LWIP_ASSERT("pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF", pcb->phase == PPP_PHASE_DEAD || pcb->phase == PPP_PHASE_HOLDOFF); 00448 00449 new_phase(pcb, PPP_PHASE_INITIALIZE); 00450 pcb->link_cb->connect(pcb, pcb->link_ctx_cb); 00451 } 00452 00453 /* 00454 * ppp_netif_init_cb - netif init callback 00455 */ 00456 static err_t ppp_netif_init_cb(struct netif *netif) { 00457 netif->name[0] = 'p'; 00458 netif->name[1] = 'p'; 00459 #if LWIP_IPV4 00460 /* FIXME: change that when netif_null_output_ip4() will materialize */ 00461 netif->output = ppp_netif_output_ip4; 00462 #endif /* LWIP_IPV4 */ 00463 #if PPP_IPV6_SUPPORT 00464 netif->output_ip6 = ppp_netif_output_ip6; 00465 #endif /* PPP_IPV6_SUPPORT */ 00466 netif->flags = NETIF_FLAG_UP; 00467 #if LWIP_NETIF_HOSTNAME 00468 /* @todo: Initialize interface hostname */ 00469 /* netif_set_hostname(netif, "lwip"); */ 00470 #endif /* LWIP_NETIF_HOSTNAME */ 00471 return ERR_OK; 00472 } 00473 00474 #if LWIP_IPV4 00475 /* 00476 * Send an IPv4 packet on the given connection. 00477 */ 00478 static err_t ppp_netif_output_ip4(struct netif *netif, struct pbuf *pb, const ip4_addr_t *ipaddr) { 00479 LWIP_UNUSED_ARG(ipaddr); 00480 #if PPP_IPV4_SUPPORT 00481 return ppp_netif_output(netif, pb, PPP_IP); 00482 #else /* PPP_IPV4_SUPPORT */ 00483 LWIP_UNUSED_ARG(netif); 00484 LWIP_UNUSED_ARG(pb); 00485 return ERR_IF; 00486 #endif /* PPP_IPV4_SUPPORT */ 00487 } 00488 #endif /* LWIP_IPV4 */ 00489 00490 #if PPP_IPV6_SUPPORT 00491 /* 00492 * Send an IPv6 packet on the given connection. 00493 */ 00494 static err_t ppp_netif_output_ip6(struct netif *netif, struct pbuf *pb, const ip6_addr_t *ipaddr) { 00495 LWIP_UNUSED_ARG(ipaddr); 00496 return ppp_netif_output(netif, pb, PPP_IPV6); 00497 } 00498 #endif /* PPP_IPV6_SUPPORT */ 00499 00500 static err_t ppp_netif_output(struct netif *netif, struct pbuf *pb, u16_t protocol) { 00501 ppp_pcb *pcb = (ppp_pcb*)netif->state; 00502 err_t err; 00503 struct pbuf *fpb = NULL; 00504 00505 /* Check that the link is up. */ 00506 if (0 00507 #if PPP_IPV4_SUPPORT 00508 || (protocol == PPP_IP && !pcb->if4_up) 00509 #endif /* PPP_IPV4_SUPPORT */ 00510 #if PPP_IPV6_SUPPORT 00511 || (protocol == PPP_IPV6 && !pcb->if6_up) 00512 #endif /* PPP_IPV6_SUPPORT */ 00513 ) { 00514 PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: link not up\n", pcb->netif->num)); 00515 goto err_rte_drop; 00516 } 00517 00518 #if MPPE_SUPPORT 00519 /* If MPPE is required, refuse any IP packet until we are able to crypt them. */ 00520 if (pcb->settings.require_mppe && pcb->ccp_transmit_method != CI_MPPE) { 00521 PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: MPPE required, not up\n", pcb->netif->num)); 00522 goto err_rte_drop; 00523 } 00524 #endif /* MPPE_SUPPORT */ 00525 00526 #if VJ_SUPPORT 00527 /* 00528 * Attempt Van Jacobson header compression if VJ is configured and 00529 * this is an IP packet. 00530 */ 00531 if (protocol == PPP_IP && pcb->vj_enabled) { 00532 switch (vj_compress_tcp(&pcb->vj_comp, &pb)) { 00533 case TYPE_IP: 00534 /* No change... 00535 protocol = PPP_IP; */ 00536 break; 00537 case TYPE_COMPRESSED_TCP: 00538 /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free 00539 * our duplicated pbuf later */ 00540 fpb = pb; 00541 protocol = PPP_VJC_COMP; 00542 break; 00543 case TYPE_UNCOMPRESSED_TCP: 00544 /* vj_compress_tcp() returns a new allocated pbuf, indicate we should free 00545 * our duplicated pbuf later */ 00546 fpb = pb; 00547 protocol = PPP_VJC_UNCOMP; 00548 break; 00549 default: 00550 PPPDEBUG(LOG_WARNING, ("ppp_netif_output[%d]: bad IP packet\n", pcb->netif->num)); 00551 LINK_STATS_INC(link.proterr); 00552 LINK_STATS_INC(link.drop); 00553 MIB2_STATS_NETIF_INC(pcb->netif, ifoutdiscards); 00554 return ERR_VAL; 00555 } 00556 } 00557 #endif /* VJ_SUPPORT */ 00558 00559 #if CCP_SUPPORT 00560 switch (pcb->ccp_transmit_method) { 00561 case 0: 00562 break; /* Don't compress */ 00563 #if MPPE_SUPPORT 00564 case CI_MPPE: 00565 if ((err = mppe_compress(pcb, &pcb->mppe_comp, &pb, protocol)) != ERR_OK) { 00566 LINK_STATS_INC(link.memerr); 00567 LINK_STATS_INC(link.drop); 00568 MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 00569 goto err; 00570 } 00571 /* if VJ compressor returned a new allocated pbuf, free it */ 00572 if (fpb) { 00573 pbuf_free(fpb); 00574 } 00575 /* mppe_compress() returns a new allocated pbuf, indicate we should free 00576 * our duplicated pbuf later */ 00577 fpb = pb; 00578 protocol = PPP_COMP; 00579 break; 00580 #endif /* MPPE_SUPPORT */ 00581 default: 00582 PPPDEBUG(LOG_ERR, ("ppp_netif_output[%d]: bad CCP transmit method\n", pcb->netif->num)); 00583 goto err_rte_drop; /* Cannot really happen, we only negotiate what we are able to do */ 00584 } 00585 #endif /* CCP_SUPPORT */ 00586 00587 err = pcb->link_cb->netif_output(pcb, pcb->link_ctx_cb, pb, protocol); 00588 goto err; 00589 00590 err_rte_drop: 00591 err = ERR_RTE; 00592 LINK_STATS_INC(link.rterr); 00593 LINK_STATS_INC(link.drop); 00594 MIB2_STATS_NETIF_INC(netif, ifoutdiscards); 00595 err: 00596 if (fpb) { 00597 pbuf_free(fpb); 00598 } 00599 return err; 00600 } 00601 00602 /************************************/ 00603 /*** PRIVATE FUNCTION DEFINITIONS ***/ 00604 /************************************/ 00605 00606 /* Initialize the PPP subsystem. */ 00607 int ppp_init(void) 00608 { 00609 #if PPPOS_SUPPORT 00610 LWIP_MEMPOOL_INIT(PPPOS_PCB); 00611 #endif 00612 #if PPPOE_SUPPORT 00613 LWIP_MEMPOOL_INIT(PPPOE_IF); 00614 #endif 00615 #if PPPOL2TP_SUPPORT 00616 LWIP_MEMPOOL_INIT(PPPOL2TP_PCB); 00617 #endif 00618 #if LWIP_PPP_API && LWIP_MPU_COMPATIBLE 00619 LWIP_MEMPOOL_INIT(PPPAPI_MSG); 00620 #endif 00621 00622 LWIP_MEMPOOL_INIT(PPP_PCB); 00623 00624 /* 00625 * Initialize magic number generator now so that protocols may 00626 * use magic numbers in initialization. 00627 */ 00628 magic_init(); 00629 00630 return 0; 00631 } 00632 00633 /* 00634 * Create a new PPP control block. 00635 * 00636 * This initializes the PPP control block but does not 00637 * attempt to negotiate the LCP session. 00638 * 00639 * Return a new PPP connection control block pointer 00640 * on success or a null pointer on failure. 00641 */ 00642 ppp_pcb *ppp_new(struct netif *pppif, const struct link_callbacks *callbacks, void *link_ctx_cb, ppp_link_status_cb_fn link_status_cb, void *ctx_cb) { 00643 ppp_pcb *pcb; 00644 const struct protent *protp; 00645 int i; 00646 00647 /* PPP is single-threaded: without a callback, 00648 * there is no way to know when the link is up. */ 00649 if (link_status_cb == NULL) { 00650 return NULL; 00651 } 00652 00653 pcb = (ppp_pcb*)LWIP_MEMPOOL_ALLOC(PPP_PCB); 00654 if (pcb == NULL) { 00655 return NULL; 00656 } 00657 00658 memset(pcb, 0, sizeof(ppp_pcb)); 00659 00660 /* default configuration */ 00661 #if PAP_SUPPORT 00662 pcb->settings.pap_timeout_time = UPAP_DEFTIMEOUT; 00663 pcb->settings.pap_max_transmits = UPAP_DEFTRANSMITS; 00664 #if PPP_SERVER 00665 pcb->settings.pap_req_timeout = UPAP_DEFREQTIME; 00666 #endif /* PPP_SERVER */ 00667 #endif /* PAP_SUPPORT */ 00668 00669 #if CHAP_SUPPORT 00670 pcb->settings.chap_timeout_time = CHAP_DEFTIMEOUT; 00671 pcb->settings.chap_max_transmits = CHAP_DEFTRANSMITS; 00672 #if PPP_SERVER 00673 pcb->settings.chap_rechallenge_time = CHAP_DEFRECHALLENGETIME; 00674 #endif /* PPP_SERVER */ 00675 #endif /* CHAP_SUPPPORT */ 00676 00677 #if EAP_SUPPORT 00678 pcb->settings.eap_req_time = EAP_DEFREQTIME; 00679 pcb->settings.eap_allow_req = EAP_DEFALLOWREQ; 00680 #if PPP_SERVER 00681 pcb->settings.eap_timeout_time = EAP_DEFTIMEOUT; 00682 pcb->settings.eap_max_transmits = EAP_DEFTRANSMITS; 00683 #endif /* PPP_SERVER */ 00684 #endif /* EAP_SUPPORT */ 00685 00686 pcb->settings.lcp_loopbackfail = LCP_DEFLOOPBACKFAIL; 00687 pcb->settings.lcp_echo_interval = LCP_ECHOINTERVAL; 00688 pcb->settings.lcp_echo_fails = LCP_MAXECHOFAILS; 00689 00690 pcb->settings.fsm_timeout_time = FSM_DEFTIMEOUT; 00691 pcb->settings.fsm_max_conf_req_transmits = FSM_DEFMAXCONFREQS; 00692 pcb->settings.fsm_max_term_transmits = FSM_DEFMAXTERMREQS; 00693 pcb->settings.fsm_max_nak_loops = FSM_DEFMAXNAKLOOPS; 00694 00695 pcb->netif = pppif; 00696 MIB2_INIT_NETIF(pppif, snmp_ifType_ppp, 0); 00697 if (!netif_add(pcb->netif, 00698 #if LWIP_IPV4 00699 IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4, 00700 #endif /* LWIP_IPV4 */ 00701 (void *)pcb, ppp_netif_init_cb, NULL)) { 00702 LWIP_MEMPOOL_FREE(PPP_PCB, pcb); 00703 PPPDEBUG(LOG_ERR, ("ppp_new: netif_add failed\n")); 00704 return NULL; 00705 } 00706 00707 pcb->link_cb = callbacks; 00708 pcb->link_ctx_cb = link_ctx_cb; 00709 pcb->link_status_cb = link_status_cb; 00710 pcb->ctx_cb = ctx_cb; 00711 00712 /* 00713 * Initialize each protocol. 00714 */ 00715 for (i = 0; (protp = protocols[i]) != NULL; ++i) { 00716 (*protp->init)(pcb); 00717 } 00718 00719 new_phase(pcb, PPP_PHASE_DEAD); 00720 return pcb; 00721 } 00722 00723 /** Initiate LCP open request */ 00724 void ppp_start(ppp_pcb *pcb) { 00725 PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]\n", pcb->netif->num)); 00726 00727 /* Clean data not taken care by anything else, mostly shared data. */ 00728 #if PPP_STATS_SUPPORT 00729 link_stats_valid = 0; 00730 #endif /* PPP_STATS_SUPPORT */ 00731 #if MPPE_SUPPORT 00732 pcb->mppe_keys_set = 0; 00733 memset(&pcb->mppe_comp, 0, sizeof(pcb->mppe_comp)); 00734 memset(&pcb->mppe_decomp, 0, sizeof(pcb->mppe_decomp)); 00735 #endif /* MPPE_SUPPORT */ 00736 #if VJ_SUPPORT 00737 vj_compress_init(&pcb->vj_comp); 00738 #endif /* VJ_SUPPORT */ 00739 00740 /* Start protocol */ 00741 new_phase(pcb, PPP_PHASE_ESTABLISH); 00742 lcp_open(pcb); 00743 lcp_lowerup(pcb); 00744 PPPDEBUG(LOG_DEBUG, ("ppp_start[%d]: finished\n", pcb->netif->num)); 00745 } 00746 00747 /** Called when link failed to setup */ 00748 void ppp_link_failed(ppp_pcb *pcb) { 00749 PPPDEBUG(LOG_DEBUG, ("ppp_link_failed[%d]\n", pcb->netif->num)); 00750 new_phase(pcb, PPP_PHASE_DEAD); 00751 pcb->err_code = PPPERR_OPEN; 00752 pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); 00753 } 00754 00755 /** Called when link is normally down (i.e. it was asked to end) */ 00756 void ppp_link_end(ppp_pcb *pcb) { 00757 PPPDEBUG(LOG_DEBUG, ("ppp_link_end[%d]\n", pcb->netif->num)); 00758 new_phase(pcb, PPP_PHASE_DEAD); 00759 if (pcb->err_code == PPPERR_NONE) { 00760 pcb->err_code = PPPERR_CONNECT; 00761 } 00762 pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); 00763 } 00764 00765 /* 00766 * Pass the processed input packet to the appropriate handler. 00767 * This function and all handlers run in the context of the tcpip_thread 00768 */ 00769 void ppp_input(ppp_pcb *pcb, struct pbuf *pb) { 00770 u16_t protocol; 00771 #if PPP_DEBUG && PPP_PROTOCOLNAME 00772 const char *pname; 00773 #endif /* PPP_DEBUG && PPP_PROTOCOLNAME */ 00774 00775 magic_randomize(); 00776 00777 if (pb->len < 2) { 00778 PPPDEBUG(LOG_ERR, ("ppp_input[%d]: packet too short\n", pcb->netif->num)); 00779 goto drop; 00780 } 00781 protocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1]; 00782 00783 #if PRINTPKT_SUPPORT 00784 ppp_dump_packet(pcb, "rcvd", (unsigned char *)pb->payload, pb->len); 00785 #endif /* PRINTPKT_SUPPORT */ 00786 00787 pbuf_header(pb, -(s16_t)sizeof(protocol)); 00788 00789 LINK_STATS_INC(link.recv); 00790 MIB2_STATS_NETIF_INC(pcb->netif, ifinucastpkts); 00791 MIB2_STATS_NETIF_ADD(pcb->netif, ifinoctets, pb->tot_len); 00792 00793 /* 00794 * Toss all non-LCP packets unless LCP is OPEN. 00795 */ 00796 if (protocol != PPP_LCP && pcb->lcp_fsm.state != PPP_FSM_OPENED) { 00797 ppp_dbglog("Discarded non-LCP packet when LCP not open"); 00798 goto drop; 00799 } 00800 00801 /* 00802 * Until we get past the authentication phase, toss all packets 00803 * except LCP, LQR and authentication packets. 00804 */ 00805 if (pcb->phase <= PPP_PHASE_AUTHENTICATE 00806 && !(protocol == PPP_LCP 00807 #if LQR_SUPPORT 00808 || protocol == PPP_LQR 00809 #endif /* LQR_SUPPORT */ 00810 #if PAP_SUPPORT 00811 || protocol == PPP_PAP 00812 #endif /* PAP_SUPPORT */ 00813 #if CHAP_SUPPORT 00814 || protocol == PPP_CHAP 00815 #endif /* CHAP_SUPPORT */ 00816 #if EAP_SUPPORT 00817 || protocol == PPP_EAP 00818 #endif /* EAP_SUPPORT */ 00819 )) { 00820 ppp_dbglog("discarding proto 0x%x in phase %d", protocol, pcb->phase); 00821 goto drop; 00822 } 00823 00824 #if CCP_SUPPORT 00825 #if MPPE_SUPPORT 00826 /* 00827 * MPPE is required and unencrypted data has arrived (this 00828 * should never happen!). We should probably drop the link if 00829 * the protocol is in the range of what should be encrypted. 00830 * At the least, we drop this packet. 00831 */ 00832 if (pcb->settings.require_mppe && protocol != PPP_COMP && protocol < 0x8000) { 00833 PPPDEBUG(LOG_ERR, ("ppp_input[%d]: MPPE required, received unencrypted data!\n", pcb->netif->num)); 00834 goto drop; 00835 } 00836 #endif /* MPPE_SUPPORT */ 00837 00838 if (protocol == PPP_COMP) { 00839 u8_t *pl; 00840 00841 switch (pcb->ccp_receive_method) { 00842 #if MPPE_SUPPORT 00843 case CI_MPPE: 00844 if (mppe_decompress(pcb, &pcb->mppe_decomp, &pb) != ERR_OK) { 00845 goto drop; 00846 } 00847 break; 00848 #endif /* MPPE_SUPPORT */ 00849 default: 00850 PPPDEBUG(LOG_ERR, ("ppp_input[%d]: bad CCP receive method\n", pcb->netif->num)); 00851 goto drop; /* Cannot really happen, we only negotiate what we are able to do */ 00852 } 00853 00854 /* Assume no PFC */ 00855 if (pb->len < 2) { 00856 goto drop; 00857 } 00858 00859 /* Extract and hide protocol (do PFC decompression if necessary) */ 00860 pl = (u8_t*)pb->payload; 00861 if (pl[0] & 0x01) { 00862 protocol = pl[0]; 00863 pbuf_header(pb, -(s16_t)1); 00864 } else { 00865 protocol = (pl[0] << 8) | pl[1]; 00866 pbuf_header(pb, -(s16_t)2); 00867 } 00868 } 00869 #endif /* CCP_SUPPORT */ 00870 00871 switch(protocol) { 00872 00873 #if PPP_IPV4_SUPPORT 00874 case PPP_IP: /* Internet Protocol */ 00875 PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); 00876 ip4_input(pb, pcb->netif); 00877 return; 00878 #endif /* PPP_IPV4_SUPPORT */ 00879 00880 #if PPP_IPV6_SUPPORT 00881 case PPP_IPV6: /* Internet Protocol Version 6 */ 00882 PPPDEBUG(LOG_INFO, ("ppp_input[%d]: ip6 in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); 00883 ip6_input(pb, pcb->netif); 00884 return; 00885 #endif /* PPP_IPV6_SUPPORT */ 00886 00887 #if VJ_SUPPORT 00888 case PPP_VJC_COMP: /* VJ compressed TCP */ 00889 /* 00890 * Clip off the VJ header and prepend the rebuilt TCP/IP header and 00891 * pass the result to IP. 00892 */ 00893 PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_comp in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); 00894 if (pcb->vj_enabled && vj_uncompress_tcp(&pb, &pcb->vj_comp) >= 0) { 00895 ip4_input(pb, pcb->netif); 00896 return; 00897 } 00898 /* Something's wrong so drop it. */ 00899 PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ compressed\n", pcb->netif->num)); 00900 break; 00901 00902 case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ 00903 /* 00904 * Process the TCP/IP header for VJ header compression and then pass 00905 * the packet to IP. 00906 */ 00907 PPPDEBUG(LOG_INFO, ("ppp_input[%d]: vj_un in pbuf len=%d\n", pcb->netif->num, pb->tot_len)); 00908 if (pcb->vj_enabled && vj_uncompress_uncomp(pb, &pcb->vj_comp) >= 0) { 00909 ip4_input(pb, pcb->netif); 00910 return; 00911 } 00912 /* Something's wrong so drop it. */ 00913 PPPDEBUG(LOG_WARNING, ("ppp_input[%d]: Dropping VJ uncompressed\n", pcb->netif->num)); 00914 break; 00915 #endif /* VJ_SUPPORT */ 00916 00917 default: { 00918 int i; 00919 const struct protent *protp; 00920 00921 /* 00922 * Upcall the proper protocol input routine. 00923 */ 00924 for (i = 0; (protp = protocols[i]) != NULL; ++i) { 00925 if (protp->protocol == protocol) { 00926 pb = ppp_singlebuf(pb); 00927 (*protp->input)(pcb, (u8_t*)pb->payload, pb->len); 00928 goto out; 00929 } 00930 #if 0 /* UNUSED 00931 * 00932 * This is actually a (hacked?) way for the Linux kernel to pass a data 00933 * packet to pppd. pppd in normal condition only do signaling 00934 * (LCP, PAP, CHAP, IPCP, ...) and does not handle any data packet at all. 00935 * 00936 * We don't even need this interface, which is only there because of PPP 00937 * interface limitation between Linux kernel and pppd. For MPPE, which uses 00938 * CCP to negotiate although it is not really a (de)compressor, we added 00939 * ccp_resetrequest() in CCP and MPPE input data flow is calling either 00940 * ccp_resetrequest() or lcp_close() if the issue is, respectively, non-fatal 00941 * or fatal, this is what ccp_datainput() really do. 00942 */ 00943 if (protocol == (protp->protocol & ~0x8000) 00944 && protp->datainput != NULL) { 00945 (*protp->datainput)(pcb, pb->payload, pb->len); 00946 goto out; 00947 } 00948 #endif /* UNUSED */ 00949 } 00950 00951 #if PPP_DEBUG 00952 #if PPP_PROTOCOLNAME 00953 pname = protocol_name(protocol); 00954 if (pname != NULL) { 00955 ppp_warn("Unsupported protocol '%s' (0x%x) received", pname, protocol); 00956 } else 00957 #endif /* PPP_PROTOCOLNAME */ 00958 ppp_warn("Unsupported protocol 0x%x received", protocol); 00959 #endif /* PPP_DEBUG */ 00960 pbuf_header(pb, (s16_t)sizeof(protocol)); 00961 lcp_sprotrej(pcb, (u8_t*)pb->payload, pb->len); 00962 } 00963 break; 00964 } 00965 00966 drop: 00967 LINK_STATS_INC(link.drop); 00968 MIB2_STATS_NETIF_INC(pcb->netif, ifindiscards); 00969 00970 out: 00971 pbuf_free(pb); 00972 } 00973 00974 /* merge a pbuf chain into one pbuf */ 00975 struct pbuf *ppp_singlebuf(struct pbuf *p) { 00976 struct pbuf *q, *b; 00977 u8_t *pl; 00978 00979 if(p->tot_len == p->len) { 00980 return p; 00981 } 00982 00983 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); 00984 if(!q) { 00985 PPPDEBUG(LOG_ERR, 00986 ("ppp_singlebuf: unable to alloc new buf (%d)\n", p->tot_len)); 00987 return p; /* live dangerously */ 00988 } 00989 00990 for(b = p, pl = (u8_t*)q->payload; b != NULL; b = b->next) { 00991 MEMCPY(pl, b->payload, b->len); 00992 pl += b->len; 00993 } 00994 00995 pbuf_free(p); 00996 00997 return q; 00998 } 00999 01000 /* 01001 * Write a pbuf to a ppp link, only used from PPP functions 01002 * to send PPP packets. 01003 * 01004 * IPv4 and IPv6 packets from lwIP are sent, respectively, 01005 * with ppp_netif_output_ip4() and ppp_netif_output_ip6() 01006 * functions (which are callbacks of the netif PPP interface). 01007 */ 01008 err_t ppp_write(ppp_pcb *pcb, struct pbuf *p) { 01009 #if PRINTPKT_SUPPORT 01010 ppp_dump_packet(pcb, "sent", (unsigned char *)p->payload+2, p->len-2); 01011 #endif /* PRINTPKT_SUPPORT */ 01012 return pcb->link_cb->write(pcb, pcb->link_ctx_cb, p); 01013 } 01014 01015 void ppp_link_terminated(ppp_pcb *pcb) { 01016 PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]\n", pcb->netif->num)); 01017 pcb->link_cb->disconnect(pcb, pcb->link_ctx_cb); 01018 PPPDEBUG(LOG_DEBUG, ("ppp_link_terminated[%d]: finished.\n", pcb->netif->num)); 01019 } 01020 01021 01022 /************************************************************************ 01023 * Functions called by various PPP subsystems to configure 01024 * the PPP interface or change the PPP phase. 01025 */ 01026 01027 /* 01028 * new_phase - signal the start of a new phase of pppd's operation. 01029 */ 01030 void new_phase(ppp_pcb *pcb, int p) { 01031 pcb->phase = p; 01032 PPPDEBUG(LOG_DEBUG, ("ppp phase changed[%d]: phase=%d\n", pcb->netif->num, pcb->phase)); 01033 #if PPP_NOTIFY_PHASE 01034 if (pcb->notify_phase_cb != NULL) { 01035 pcb->notify_phase_cb(pcb, p, pcb->ctx_cb); 01036 } 01037 #endif /* PPP_NOTIFY_PHASE */ 01038 } 01039 01040 /* 01041 * ppp_send_config - configure the transmit-side characteristics of 01042 * the ppp interface. 01043 */ 01044 int ppp_send_config(ppp_pcb *pcb, int mtu, u32_t accm, int pcomp, int accomp) { 01045 LWIP_UNUSED_ARG(mtu); 01046 /* pcb->mtu = mtu; -- set correctly with netif_set_mtu */ 01047 01048 if (pcb->link_cb->send_config) { 01049 pcb->link_cb->send_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); 01050 } 01051 01052 PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]\n", pcb->netif->num) ); 01053 return 0; 01054 } 01055 01056 /* 01057 * ppp_recv_config - configure the receive-side characteristics of 01058 * the ppp interface. 01059 */ 01060 int ppp_recv_config(ppp_pcb *pcb, int mru, u32_t accm, int pcomp, int accomp) { 01061 LWIP_UNUSED_ARG(mru); 01062 01063 if (pcb->link_cb->recv_config) { 01064 pcb->link_cb->recv_config(pcb, pcb->link_ctx_cb, accm, pcomp, accomp); 01065 } 01066 01067 PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]\n", pcb->netif->num)); 01068 return 0; 01069 } 01070 01071 #if PPP_IPV4_SUPPORT 01072 /* 01073 * sifaddr - Config the interface IP addresses and netmask. 01074 */ 01075 int sifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr, u32_t netmask) { 01076 ip4_addr_t ip, nm, gw; 01077 01078 ip4_addr_set_u32(&ip, our_adr); 01079 ip4_addr_set_u32(&nm, netmask); 01080 ip4_addr_set_u32(&gw, his_adr); 01081 netif_set_addr(pcb->netif, &ip, &nm, &gw); 01082 return 1; 01083 } 01084 01085 /******************************************************************** 01086 * 01087 * cifaddr - Clear the interface IP addresses, and delete routes 01088 * through the interface if possible. 01089 */ 01090 int cifaddr(ppp_pcb *pcb, u32_t our_adr, u32_t his_adr) { 01091 LWIP_UNUSED_ARG(our_adr); 01092 LWIP_UNUSED_ARG(his_adr); 01093 01094 netif_set_addr(pcb->netif, IP4_ADDR_ANY4, IP4_ADDR_BROADCAST, IP4_ADDR_ANY4); 01095 return 1; 01096 } 01097 01098 #if 0 /* UNUSED - PROXY ARP */ 01099 /******************************************************************** 01100 * 01101 * sifproxyarp - Make a proxy ARP entry for the peer. 01102 */ 01103 01104 int sifproxyarp(ppp_pcb *pcb, u32_t his_adr) { 01105 LWIP_UNUSED_ARG(pcb); 01106 LWIP_UNUSED_ARG(his_adr); 01107 return 0; 01108 } 01109 01110 /******************************************************************** 01111 * 01112 * cifproxyarp - Delete the proxy ARP entry for the peer. 01113 */ 01114 01115 int cifproxyarp(ppp_pcb *pcb, u32_t his_adr) { 01116 LWIP_UNUSED_ARG(pcb); 01117 LWIP_UNUSED_ARG(his_adr); 01118 return 0; 01119 } 01120 #endif /* UNUSED - PROXY ARP */ 01121 01122 #if LWIP_DNS 01123 /* 01124 * sdns - Config the DNS servers 01125 */ 01126 int sdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { 01127 ip_addr_t ns; 01128 LWIP_UNUSED_ARG(pcb); 01129 01130 ip_addr_set_ip4_u32(&ns, ns1); 01131 dns_setserver(0, &ns); 01132 ip_addr_set_ip4_u32(&ns, ns2); 01133 dns_setserver(1, &ns); 01134 return 1; 01135 } 01136 01137 /******************************************************************** 01138 * 01139 * cdns - Clear the DNS servers 01140 */ 01141 int cdns(ppp_pcb *pcb, u32_t ns1, u32_t ns2) { 01142 const ip_addr_t *nsa; 01143 ip_addr_t nsb; 01144 LWIP_UNUSED_ARG(pcb); 01145 01146 nsa = dns_getserver(0); 01147 ip_addr_set_ip4_u32(&nsb, ns1); 01148 if (ip_addr_cmp(nsa, &nsb)) { 01149 dns_setserver(0, IP_ADDR_ANY); 01150 } 01151 nsa = dns_getserver(1); 01152 ip_addr_set_ip4_u32(&nsb, ns2); 01153 if (ip_addr_cmp(nsa, &nsb)) { 01154 dns_setserver(1, IP_ADDR_ANY); 01155 } 01156 return 1; 01157 } 01158 #endif /* LWIP_DNS */ 01159 01160 #if VJ_SUPPORT 01161 /******************************************************************** 01162 * 01163 * sifvjcomp - config tcp header compression 01164 */ 01165 int sifvjcomp(ppp_pcb *pcb, int vjcomp, int cidcomp, int maxcid) { 01166 pcb->vj_enabled = vjcomp; 01167 pcb->vj_comp.compressSlot = cidcomp; 01168 pcb->vj_comp.maxSlotIndex = maxcid; 01169 PPPDEBUG(LOG_INFO, ("sifvjcomp[%d]: VJ compress enable=%d slot=%d max slot=%d\n", 01170 pcb->netif->num, vjcomp, cidcomp, maxcid)); 01171 return 0; 01172 } 01173 #endif /* VJ_SUPPORT */ 01174 01175 /* 01176 * sifup - Config the interface up and enable IP packets to pass. 01177 */ 01178 int sifup(ppp_pcb *pcb) { 01179 pcb->if4_up = 1; 01180 pcb->err_code = PPPERR_NONE; 01181 netif_set_link_up(pcb->netif); 01182 01183 PPPDEBUG(LOG_DEBUG, ("sifup[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); 01184 pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); 01185 return 1; 01186 } 01187 01188 /******************************************************************** 01189 * 01190 * sifdown - Disable the indicated protocol and config the interface 01191 * down if there are no remaining protocols. 01192 */ 01193 int sifdown(ppp_pcb *pcb) { 01194 01195 pcb->if4_up = 0; 01196 01197 if (1 01198 #if PPP_IPV6_SUPPORT 01199 /* set the interface down if IPv6 is down as well */ 01200 && !pcb->if6_up 01201 #endif /* PPP_IPV6_SUPPORT */ 01202 ) { 01203 /* make sure the netif link callback is called */ 01204 netif_set_link_down(pcb->netif); 01205 } 01206 PPPDEBUG(LOG_DEBUG, ("sifdown[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); 01207 return 1; 01208 } 01209 01210 /******************************************************************** 01211 * 01212 * Return user specified netmask, modified by any mask we might determine 01213 * for address `addr' (in network byte order). 01214 * Here we scan through the system's list of interfaces, looking for 01215 * any non-point-to-point interfaces which might appear to be on the same 01216 * network as `addr'. If we find any, we OR in their netmask to the 01217 * user-specified netmask. 01218 */ 01219 u32_t get_mask(u32_t addr) { 01220 #if 0 01221 u32_t mask, nmask; 01222 01223 addr = lwip_htonl(addr); 01224 if (IP_CLASSA(addr)) { /* determine network mask for address class */ 01225 nmask = IP_CLASSA_NET; 01226 } else if (IP_CLASSB(addr)) { 01227 nmask = IP_CLASSB_NET; 01228 } else { 01229 nmask = IP_CLASSC_NET; 01230 } 01231 01232 /* class D nets are disallowed by bad_ip_adrs */ 01233 mask = PP_HTONL(0xffffff00UL) | lwip_htonl(nmask); 01234 01235 /* XXX 01236 * Scan through the system's network interfaces. 01237 * Get each netmask and OR them into our mask. 01238 */ 01239 /* return mask; */ 01240 return mask; 01241 #endif /* 0 */ 01242 LWIP_UNUSED_ARG(addr); 01243 return IPADDR_BROADCAST; 01244 } 01245 #endif /* PPP_IPV4_SUPPORT */ 01246 01247 #if PPP_IPV6_SUPPORT 01248 #define IN6_LLADDR_FROM_EUI64(ip6, eui64) do { \ 01249 ip6.addr[0] = PP_HTONL(0xfe800000); \ 01250 ip6.addr[1] = 0; \ 01251 eui64_copy(eui64, ip6.addr[2]); \ 01252 } while (0) 01253 01254 /******************************************************************** 01255 * 01256 * sif6addr - Config the interface with an IPv6 link-local address 01257 */ 01258 int sif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { 01259 ip6_addr_t ip6; 01260 LWIP_UNUSED_ARG(his_eui64); 01261 01262 IN6_LLADDR_FROM_EUI64(ip6, our_eui64); 01263 netif_ip6_addr_set(pcb->netif, 0, &ip6); 01264 netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_PREFERRED); 01265 /* FIXME: should we add an IPv6 static neighbor using his_eui64 ? */ 01266 return 1; 01267 } 01268 01269 /******************************************************************** 01270 * 01271 * cif6addr - Remove IPv6 address from interface 01272 */ 01273 int cif6addr(ppp_pcb *pcb, eui64_t our_eui64, eui64_t his_eui64) { 01274 LWIP_UNUSED_ARG(our_eui64); 01275 LWIP_UNUSED_ARG(his_eui64); 01276 01277 netif_ip6_addr_set(pcb->netif, 0, IP6_ADDR_ANY6); 01278 netif_ip6_addr_set_state(pcb->netif, 0, IP6_ADDR_INVALID); 01279 return 1; 01280 } 01281 01282 /* 01283 * sif6up - Config the interface up and enable IPv6 packets to pass. 01284 */ 01285 int sif6up(ppp_pcb *pcb) { 01286 01287 pcb->if6_up = 1; 01288 pcb->err_code = PPPERR_NONE; 01289 netif_set_link_up(pcb->netif); 01290 01291 PPPDEBUG(LOG_DEBUG, ("sif6up[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); 01292 pcb->link_status_cb(pcb, pcb->err_code, pcb->ctx_cb); 01293 return 1; 01294 } 01295 01296 /******************************************************************** 01297 * 01298 * sif6down - Disable the indicated protocol and config the interface 01299 * down if there are no remaining protocols. 01300 */ 01301 int sif6down(ppp_pcb *pcb) { 01302 01303 pcb->if6_up = 0; 01304 01305 if (1 01306 #if PPP_IPV4_SUPPORT 01307 /* set the interface down if IPv4 is down as well */ 01308 && !pcb->if4_up 01309 #endif /* PPP_IPV4_SUPPORT */ 01310 ) { 01311 /* make sure the netif link callback is called */ 01312 netif_set_link_down(pcb->netif); 01313 } 01314 PPPDEBUG(LOG_DEBUG, ("sif6down[%d]: err_code=%d\n", pcb->netif->num, pcb->err_code)); 01315 return 1; 01316 } 01317 #endif /* PPP_IPV6_SUPPORT */ 01318 01319 #if DEMAND_SUPPORT 01320 /* 01321 * sifnpmode - Set the mode for handling packets for a given NP. 01322 */ 01323 int sifnpmode(ppp_pcb *pcb, int proto, enum NPmode mode) { 01324 LWIP_UNUSED_ARG(pcb); 01325 LWIP_UNUSED_ARG(proto); 01326 LWIP_UNUSED_ARG(mode); 01327 return 0; 01328 } 01329 #endif /* DEMAND_SUPPORT */ 01330 01331 /* 01332 * netif_set_mtu - set the MTU on the PPP network interface. 01333 */ 01334 void netif_set_mtu(ppp_pcb *pcb, int mtu) { 01335 01336 pcb->netif->mtu = mtu; 01337 PPPDEBUG(LOG_INFO, ("netif_set_mtu[%d]: mtu=%d\n", pcb->netif->num, mtu)); 01338 } 01339 01340 /* 01341 * netif_get_mtu - get PPP interface MTU 01342 */ 01343 int netif_get_mtu(ppp_pcb *pcb) { 01344 01345 return pcb->netif->mtu; 01346 } 01347 01348 #if CCP_SUPPORT 01349 #if 0 /* unused */ 01350 /* 01351 * ccp_test - whether a given compression method is acceptable for use. 01352 */ 01353 int 01354 ccp_test(ppp_pcb *pcb, u_char *opt_ptr, int opt_len, int for_transmit) 01355 { 01356 LWIP_UNUSED_ARG(pcb); 01357 LWIP_UNUSED_ARG(opt_ptr); 01358 LWIP_UNUSED_ARG(opt_len); 01359 LWIP_UNUSED_ARG(for_transmit); 01360 return -1; 01361 } 01362 #endif /* unused */ 01363 01364 /* 01365 * ccp_set - inform about the current state of CCP. 01366 */ 01367 void 01368 ccp_set(ppp_pcb *pcb, u8_t isopen, u8_t isup, u8_t receive_method, u8_t transmit_method) 01369 { 01370 LWIP_UNUSED_ARG(isopen); 01371 LWIP_UNUSED_ARG(isup); 01372 pcb->ccp_receive_method = receive_method; 01373 pcb->ccp_transmit_method = transmit_method; 01374 PPPDEBUG(LOG_DEBUG, ("ccp_set[%d]: is_open=%d, is_up=%d, receive_method=%u, transmit_method=%u\n", 01375 pcb->netif->num, isopen, isup, receive_method, transmit_method)); 01376 } 01377 01378 void 01379 ccp_reset_comp(ppp_pcb *pcb) 01380 { 01381 switch (pcb->ccp_transmit_method) { 01382 #if MPPE_SUPPORT 01383 case CI_MPPE: 01384 mppe_comp_reset(pcb, &pcb->mppe_comp); 01385 break; 01386 #endif /* MPPE_SUPPORT */ 01387 default: 01388 break; 01389 } 01390 } 01391 01392 void 01393 ccp_reset_decomp(ppp_pcb *pcb) 01394 { 01395 switch (pcb->ccp_receive_method) { 01396 #if MPPE_SUPPORT 01397 case CI_MPPE: 01398 mppe_decomp_reset(pcb, &pcb->mppe_decomp); 01399 break; 01400 #endif /* MPPE_SUPPORT */ 01401 default: 01402 break; 01403 } 01404 } 01405 01406 #if 0 /* unused */ 01407 /* 01408 * ccp_fatal_error - returns 1 if decompression was disabled as a 01409 * result of an error detected after decompression of a packet, 01410 * 0 otherwise. This is necessary because of patent nonsense. 01411 */ 01412 int 01413 ccp_fatal_error(ppp_pcb *pcb) 01414 { 01415 LWIP_UNUSED_ARG(pcb); 01416 return 1; 01417 } 01418 #endif /* unused */ 01419 #endif /* CCP_SUPPORT */ 01420 01421 #if PPP_IDLETIMELIMIT 01422 /******************************************************************** 01423 * 01424 * get_idle_time - return how long the link has been idle. 01425 */ 01426 int get_idle_time(ppp_pcb *pcb, struct ppp_idle *ip) { 01427 /* FIXME: add idle time support and make it optional */ 01428 LWIP_UNUSED_ARG(pcb); 01429 LWIP_UNUSED_ARG(ip); 01430 return 1; 01431 } 01432 #endif /* PPP_IDLETIMELIMIT */ 01433 01434 #if DEMAND_SUPPORT 01435 /******************************************************************** 01436 * 01437 * get_loop_output - get outgoing packets from the ppp device, 01438 * and detect when we want to bring the real link up. 01439 * Return value is 1 if we need to bring up the link, 0 otherwise. 01440 */ 01441 int get_loop_output(void) { 01442 return 0; 01443 } 01444 #endif /* DEMAND_SUPPORT */ 01445 01446 #if PPP_PROTOCOLNAME 01447 /* List of protocol names, to make our messages a little more informative. */ 01448 struct protocol_list { 01449 u_short proto; 01450 const char *name; 01451 } const protocol_list[] = { 01452 { 0x21, "IP" }, 01453 { 0x23, "OSI Network Layer" }, 01454 { 0x25, "Xerox NS IDP" }, 01455 { 0x27, "DECnet Phase IV" }, 01456 { 0x29, "Appletalk" }, 01457 { 0x2b, "Novell IPX" }, 01458 { 0x2d, "VJ compressed TCP/IP" }, 01459 { 0x2f, "VJ uncompressed TCP/IP" }, 01460 { 0x31, "Bridging PDU" }, 01461 { 0x33, "Stream Protocol ST-II" }, 01462 { 0x35, "Banyan Vines" }, 01463 { 0x39, "AppleTalk EDDP" }, 01464 { 0x3b, "AppleTalk SmartBuffered" }, 01465 { 0x3d, "Multi-Link" }, 01466 { 0x3f, "NETBIOS Framing" }, 01467 { 0x41, "Cisco Systems" }, 01468 { 0x43, "Ascom Timeplex" }, 01469 { 0x45, "Fujitsu Link Backup and Load Balancing (LBLB)" }, 01470 { 0x47, "DCA Remote Lan" }, 01471 { 0x49, "Serial Data Transport Protocol (PPP-SDTP)" }, 01472 { 0x4b, "SNA over 802.2" }, 01473 { 0x4d, "SNA" }, 01474 { 0x4f, "IP6 Header Compression" }, 01475 { 0x51, "KNX Bridging Data" }, 01476 { 0x53, "Encryption" }, 01477 { 0x55, "Individual Link Encryption" }, 01478 { 0x57, "IPv6" }, 01479 { 0x59, "PPP Muxing" }, 01480 { 0x5b, "Vendor-Specific Network Protocol" }, 01481 { 0x61, "RTP IPHC Full Header" }, 01482 { 0x63, "RTP IPHC Compressed TCP" }, 01483 { 0x65, "RTP IPHC Compressed non-TCP" }, 01484 { 0x67, "RTP IPHC Compressed UDP 8" }, 01485 { 0x69, "RTP IPHC Compressed RTP 8" }, 01486 { 0x6f, "Stampede Bridging" }, 01487 { 0x73, "MP+" }, 01488 { 0xc1, "NTCITS IPI" }, 01489 { 0xfb, "single-link compression" }, 01490 { 0xfd, "Compressed Datagram" }, 01491 { 0x0201, "802.1d Hello Packets" }, 01492 { 0x0203, "IBM Source Routing BPDU" }, 01493 { 0x0205, "DEC LANBridge100 Spanning Tree" }, 01494 { 0x0207, "Cisco Discovery Protocol" }, 01495 { 0x0209, "Netcs Twin Routing" }, 01496 { 0x020b, "STP - Scheduled Transfer Protocol" }, 01497 { 0x020d, "EDP - Extreme Discovery Protocol" }, 01498 { 0x0211, "Optical Supervisory Channel Protocol" }, 01499 { 0x0213, "Optical Supervisory Channel Protocol" }, 01500 { 0x0231, "Luxcom" }, 01501 { 0x0233, "Sigma Network Systems" }, 01502 { 0x0235, "Apple Client Server Protocol" }, 01503 { 0x0281, "MPLS Unicast" }, 01504 { 0x0283, "MPLS Multicast" }, 01505 { 0x0285, "IEEE p1284.4 standard - data packets" }, 01506 { 0x0287, "ETSI TETRA Network Protocol Type 1" }, 01507 { 0x0289, "Multichannel Flow Treatment Protocol" }, 01508 { 0x2063, "RTP IPHC Compressed TCP No Delta" }, 01509 { 0x2065, "RTP IPHC Context State" }, 01510 { 0x2067, "RTP IPHC Compressed UDP 16" }, 01511 { 0x2069, "RTP IPHC Compressed RTP 16" }, 01512 { 0x4001, "Cray Communications Control Protocol" }, 01513 { 0x4003, "CDPD Mobile Network Registration Protocol" }, 01514 { 0x4005, "Expand accelerator protocol" }, 01515 { 0x4007, "ODSICP NCP" }, 01516 { 0x4009, "DOCSIS DLL" }, 01517 { 0x400B, "Cetacean Network Detection Protocol" }, 01518 { 0x4021, "Stacker LZS" }, 01519 { 0x4023, "RefTek Protocol" }, 01520 { 0x4025, "Fibre Channel" }, 01521 { 0x4027, "EMIT Protocols" }, 01522 { 0x405b, "Vendor-Specific Protocol (VSP)" }, 01523 { 0x8021, "Internet Protocol Control Protocol" }, 01524 { 0x8023, "OSI Network Layer Control Protocol" }, 01525 { 0x8025, "Xerox NS IDP Control Protocol" }, 01526 { 0x8027, "DECnet Phase IV Control Protocol" }, 01527 { 0x8029, "Appletalk Control Protocol" }, 01528 { 0x802b, "Novell IPX Control Protocol" }, 01529 { 0x8031, "Bridging NCP" }, 01530 { 0x8033, "Stream Protocol Control Protocol" }, 01531 { 0x8035, "Banyan Vines Control Protocol" }, 01532 { 0x803d, "Multi-Link Control Protocol" }, 01533 { 0x803f, "NETBIOS Framing Control Protocol" }, 01534 { 0x8041, "Cisco Systems Control Protocol" }, 01535 { 0x8043, "Ascom Timeplex" }, 01536 { 0x8045, "Fujitsu LBLB Control Protocol" }, 01537 { 0x8047, "DCA Remote Lan Network Control Protocol (RLNCP)" }, 01538 { 0x8049, "Serial Data Control Protocol (PPP-SDCP)" }, 01539 { 0x804b, "SNA over 802.2 Control Protocol" }, 01540 { 0x804d, "SNA Control Protocol" }, 01541 { 0x804f, "IP6 Header Compression Control Protocol" }, 01542 { 0x8051, "KNX Bridging Control Protocol" }, 01543 { 0x8053, "Encryption Control Protocol" }, 01544 { 0x8055, "Individual Link Encryption Control Protocol" }, 01545 { 0x8057, "IPv6 Control Protocol" }, 01546 { 0x8059, "PPP Muxing Control Protocol" }, 01547 { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, 01548 { 0x806f, "Stampede Bridging Control Protocol" }, 01549 { 0x8073, "MP+ Control Protocol" }, 01550 { 0x80c1, "NTCITS IPI Control Protocol" }, 01551 { 0x80fb, "Single Link Compression Control Protocol" }, 01552 { 0x80fd, "Compression Control Protocol" }, 01553 { 0x8207, "Cisco Discovery Protocol Control" }, 01554 { 0x8209, "Netcs Twin Routing" }, 01555 { 0x820b, "STP - Control Protocol" }, 01556 { 0x820d, "EDPCP - Extreme Discovery Protocol Ctrl Prtcl" }, 01557 { 0x8235, "Apple Client Server Protocol Control" }, 01558 { 0x8281, "MPLSCP" }, 01559 { 0x8285, "IEEE p1284.4 standard - Protocol Control" }, 01560 { 0x8287, "ETSI TETRA TNP1 Control Protocol" }, 01561 { 0x8289, "Multichannel Flow Treatment Protocol" }, 01562 { 0xc021, "Link Control Protocol" }, 01563 { 0xc023, "Password Authentication Protocol" }, 01564 { 0xc025, "Link Quality Report" }, 01565 { 0xc027, "Shiva Password Authentication Protocol" }, 01566 { 0xc029, "CallBack Control Protocol (CBCP)" }, 01567 { 0xc02b, "BACP Bandwidth Allocation Control Protocol" }, 01568 { 0xc02d, "BAP" }, 01569 { 0xc05b, "Vendor-Specific Authentication Protocol (VSAP)" }, 01570 { 0xc081, "Container Control Protocol" }, 01571 { 0xc223, "Challenge Handshake Authentication Protocol" }, 01572 { 0xc225, "RSA Authentication Protocol" }, 01573 { 0xc227, "Extensible Authentication Protocol" }, 01574 { 0xc229, "Mitsubishi Security Info Exch Ptcl (SIEP)" }, 01575 { 0xc26f, "Stampede Bridging Authorization Protocol" }, 01576 { 0xc281, "Proprietary Authentication Protocol" }, 01577 { 0xc283, "Proprietary Authentication Protocol" }, 01578 { 0xc481, "Proprietary Node ID Authentication Protocol" }, 01579 { 0, NULL }, 01580 }; 01581 01582 /* 01583 * protocol_name - find a name for a PPP protocol. 01584 */ 01585 const char * protocol_name(int proto) { 01586 const struct protocol_list *lp; 01587 01588 for (lp = protocol_list; lp->proto != 0; ++lp) { 01589 if (proto == lp->proto) { 01590 return lp->name; 01591 } 01592 } 01593 return NULL; 01594 } 01595 #endif /* PPP_PROTOCOLNAME */ 01596 01597 #if PPP_STATS_SUPPORT 01598 01599 /* ---- Note on PPP Stats support ---- 01600 * 01601 * The one willing link stats support should add the get_ppp_stats() 01602 * to fetch statistics from lwIP. 01603 */ 01604 01605 /* 01606 * reset_link_stats - "reset" stats when link goes up. 01607 */ 01608 void reset_link_stats(int u) { 01609 if (!get_ppp_stats(u, &old_link_stats)) { 01610 return; 01611 } 01612 gettimeofday(&start_time, NULL); 01613 } 01614 01615 /* 01616 * update_link_stats - get stats at link termination. 01617 */ 01618 void update_link_stats(int u) { 01619 struct timeval now; 01620 char numbuf[32]; 01621 01622 if (!get_ppp_stats(u, &link_stats) || gettimeofday(&now, NULL) < 0) { 01623 return; 01624 } 01625 link_connect_time = now.tv_sec - start_time.tv_sec; 01626 link_stats_valid = 1; 01627 01628 link_stats.bytes_in -= old_link_stats.bytes_in; 01629 link_stats.bytes_out -= old_link_stats.bytes_out; 01630 link_stats.pkts_in -= old_link_stats.pkts_in; 01631 link_stats.pkts_out -= old_link_stats.pkts_out; 01632 } 01633 01634 void print_link_stats() { 01635 /* 01636 * Print connect time and statistics. 01637 */ 01638 if (link_stats_valid) { 01639 int t = (link_connect_time + 5) / 6; /* 1/10ths of minutes */ 01640 info("Connect time %d.%d minutes.", t/10, t%10); 01641 info("Sent %u bytes, received %u bytes.", link_stats.bytes_out, link_stats.bytes_in); 01642 link_stats_valid = 0; 01643 } 01644 } 01645 #endif /* PPP_STATS_SUPPORT */ 01646 01647 #endif /* PPP_SUPPORT */
Generated on Fri Jul 22 2022 04:53:52 by
1.7.2
