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