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.
Dependents: mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510
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 11:02:42 by
