1 /*****************************************************************************
2 * ppp.c - Network Point to Point Protocol program file.
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5 * portions Copyright (c) 1997 by Global Election Systems Inc.
7 * The authors hereby grant permission to use, copy, modify, distribute,
8 * and license this software and its documentation for any purpose, provided
9 * that existing copyright notices are retained in all copies and that this
10 * notice and the following disclaimer are included verbatim in any
11 * distributions. No written agreement, license, or royalty fee is required
12 * for any of the authorized uses.
14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 ******************************************************************************
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
30 * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
32 *****************************************************************************/
35 * ppp_defs.h - PPP definitions.
37 * if_pppvar.h - private structures and declarations for PPP.
39 * Copyright (c) 1994 The Australian National University.
40 * All rights reserved.
42 * Permission to use, copy, modify, and distribute this software and its
43 * documentation is hereby granted, provided that the above copyright
44 * notice appears in all copies. This software is provided without any
45 * warranty, express or implied. The Australian National University
46 * makes no representations about the suitability of this software for
49 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
50 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
51 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
52 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
55 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
56 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
57 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
58 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
59 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
64 * if_ppp.h - Point-to-Point Protocol definitions.
66 * Copyright (c) 1989 Carnegie Mellon University.
67 * All rights reserved.
69 * Redistribution and use in source and binary forms are permitted
70 * provided that the above copyright notice and this paragraph are
71 * duplicated in all such forms and that any documentation,
72 * advertising materials, and other materials related to such
73 * distribution and use acknowledge that the software was developed
74 * by Carnegie Mellon University. The name of the
75 * University may not be used to endorse or promote products derived
76 * from this software without specific prior written permission.
77 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
78 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
79 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
84 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
86 #include "lwip/ip.h" /* for ip_input() */
95 #endif /* PAP_SUPPORT */
98 #endif /* CHAP_SUPPORT */
105 #endif /* VJ_SUPPORT */
107 #include "netif/ppp_oe.h"
108 #endif /* PPPOE_SUPPORT */
110 #include "lwip/tcpip.h"
111 #include "lwip/api.h"
112 #include "lwip/snmp.h"
116 /*************************/
117 /*** LOCAL DEFINITIONS ***/
118 /*************************/
120 /** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback().
121 * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1.
122 * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded).
124 #ifndef PPP_INPROC_MULTITHREADED
125 #define PPP_INPROC_MULTITHREADED (NO_SYS==0)
128 /** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session.
129 * Default is 0: call pppos_input() for received raw characters, charcater
130 * reception is up to the port */
131 #ifndef PPP_INPROC_OWNTHREAD
132 #define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED
135 #if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED
136 #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1"
140 * The basic PPP frame.
142 #define PPP_ADDRESS(p) (((u_char *)(p))[0])
143 #define PPP_CONTROL(p) (((u_char *)(p))[1])
144 #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
146 /* PPP packet parser states. Current state indicates operation yet to be
149 PDIDLE
= 0, /* Idle state - waiting. */
150 PDSTART
, /* Process start flag. */
151 PDADDRESS
, /* Process address field. */
152 PDCONTROL
, /* Process control field. */
153 PDPROTOCOL1
, /* Process protocol field 1. */
154 PDPROTOCOL2
, /* Process protocol field 2. */
155 PDDATA
/* Process data byte. */
158 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
160 /************************/
161 /*** LOCAL DATA TYPES ***/
162 /************************/
164 /** RX buffer size: this may be configured smaller! */
165 #ifndef PPPOS_RX_BUFSIZE
166 #define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN)
169 typedef struct PPPControlRx_s
{
170 /** unit number / ppp descriptor */
172 /** the rx file descriptor */
174 /** receive buffer - encoded data is stored here */
175 u_char rxbuf
[PPPOS_RX_BUFSIZE
];
177 /* The input packet. */
178 struct pbuf
*inHead
, *inTail
;
181 u16_t inProtocol
; /* The input protocol code. */
182 u16_t inFCS
; /* Input Frame Check Sequence value. */
183 #endif /* PPPOS_SUPPORT */
184 PPPDevStates inState
; /* The input process state. */
185 char inEscaped
; /* Escape next character. */
186 ext_accm inACCM
; /* Async-Ctl-Char-Map for input. */
190 * PPP interface control block.
192 typedef struct PPPControl_s
{
194 char openFlag
; /* True when in use. */
197 struct pppoe_softc
*pppoe_sc
;
198 #endif /* PPPOE_SUPPORT */
199 int if_up
; /* True when the interface is up. */
200 int errCode
; /* Code indicating why interface is down. */
202 sio_fd_t fd
; /* File device ID of port. */
203 #endif /* PPPOS_SUPPORT */
204 u16_t mtu
; /* Peer's mru */
205 int pcomp
; /* Does peer accept protocol compression? */
206 int accomp
; /* Does peer accept addr/ctl compression? */
207 u_long lastXMit
; /* Time of last transmission. */
208 ext_accm outACCM
; /* Async-Ctl-Char-Map for output. */
209 #if PPPOS_SUPPORT && VJ_SUPPORT
210 int vjEnabled
; /* Flag indicating VJ compression enabled. */
211 struct vjcompress vjComp
; /* Van Jacobson compression header. */
212 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
216 struct ppp_addrs addrs
;
218 void (*linkStatusCB
)(void *ctx
, int errCode
, void *arg
);
229 int protocol
; /* PPP procotol, e.g. PPP_IP */
235 /***********************************/
236 /*** LOCAL FUNCTION DECLARATIONS ***/
237 /***********************************/
239 #if PPP_INPROC_OWNTHREAD
240 static void pppInputThread(void *arg
);
241 #endif /* PPP_INPROC_OWNTHREAD */
242 static void pppDrop(PPPControlRx
*pcrx
);
243 static void pppInProc(PPPControlRx
*pcrx
, u_char
*s
, int l
);
244 #endif /* PPPOS_SUPPORT */
247 /******************************/
248 /*** PUBLIC DATA STRUCTURES ***/
249 /******************************/
252 static PPPControl pppControl
[NUM_PPP
] __attribute((section("AHBSRAM1"))); /* The PPP interface control blocks. */
254 sys_mbox_t pppMbox
; //Used to signal PPP thread that a PPP session begins
257 * PPP Data Link Layer "protocol" table.
258 * One entry per supported protocol.
259 * The last entry must be NULL.
261 struct protent
*ppp_protocols
[] = {
265 #endif /* PAP_SUPPORT */
268 #endif /* CHAP_SUPPORT */
271 #endif /* CBCP_SUPPORT */
275 #endif /* CCP_SUPPORT */
281 * Buffers for outgoing packets. This must be accessed only from the appropriate
282 * PPP task so that it doesn't need to be protected to avoid collisions.
284 u_char outpacket_buf
[NUM_PPP
][PPP_MRU
+PPP_HDRLEN
] __attribute((section("AHBSRAM1")));
287 /*****************************/
288 /*** LOCAL DATA STRUCTURES ***/
289 /*****************************/
293 * FCS lookup table as calculated by genfcstab.
294 * @todo: smaller, slower implementation for lower memory footprint?
296 static const u_short fcstab
[256] = {
297 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
298 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
299 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
300 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
301 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
302 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
303 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
304 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
305 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
306 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
307 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
308 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
309 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
310 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
311 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
312 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
313 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
314 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
315 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
316 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
317 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
318 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
319 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
320 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
321 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
322 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
323 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
324 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
325 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
326 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
327 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
328 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
331 /* PPP's Asynchronous-Control-Character-Map. The mask array is used
332 * to select the specific bit for a character. */
333 static u_char pppACCMMask
[] = {
344 /** Wake up the task blocked in reading from serial line (if any) */
346 pppRecvWakeup(int pd
)
348 PPPDEBUG(LOG_DEBUG
, ("pppRecvWakeup: unit %d\n", pd
));
349 if (pppControl
[pd
].openFlag
!= 0) {
350 sio_read_abort(pppControl
[pd
].fd
);
353 #endif /* PPPOS_SUPPORT */
356 pppLinkTerminated(int pd
)
358 PPPDEBUG(LOG_DEBUG
, ("pppLinkTerminated: unit %d\n", pd
));
361 if (pppControl
[pd
].ethif
) {
362 pppoe_disconnect(pppControl
[pd
].pppoe_sc
);
364 #endif /* PPPOE_SUPPORT */
369 pc
= &pppControl
[pd
];
371 PPPDEBUG(LOG_DEBUG
, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd
, pc
->linkStatusCB
, pc
->errCode
));
372 if (pc
->linkStatusCB
) {
373 pc
->linkStatusCB(pc
->linkStatusCtx
, pc
->errCode
? pc
->errCode
: PPPERR_PROTOCOL
, NULL
);
376 pc
->openFlag
= 0;/**/
377 #endif /* PPPOS_SUPPORT */
379 PPPDEBUG(LOG_DEBUG
, ("pppLinkTerminated: finished.\n"));
385 PPPDEBUG(LOG_DEBUG
, ("pppLinkDown: unit %d\n", pd
));
388 if (pppControl
[pd
].ethif
) {
389 pppoe_disconnect(pppControl
[pd
].pppoe_sc
);
391 #endif /* PPPOE_SUPPORT */
395 #endif /* PPPOS_SUPPORT */
399 /** Initiate LCP open request */
403 PPPDEBUG(LOG_DEBUG
, ("pppStart: unit %d\n", pd
));
405 lcp_open(pd
); /* Start protocol */
406 PPPDEBUG(LOG_DEBUG
, ("pppStart: finished\n"));
409 /** LCP close request */
413 PPPDEBUG(LOG_DEBUG
, ("pppStop: unit %d\n", pd
));
414 lcp_close(pd
, "User request");
417 /** Called when carrier/link is lost */
421 PPPDEBUG(LOG_DEBUG
, ("pppHupCB: unit %d\n", pd
));
426 /***********************************/
427 /*** PUBLIC FUNCTION DEFINITIONS ***/
428 /***********************************/
429 /* Initialize the PPP subsystem. */
431 struct ppp_settings ppp_settings
;
436 struct protent
*protp
;
439 memset(&ppp_settings
, 0, sizeof(ppp_settings
));
440 ppp_settings
.usepeerdns
= 1;
441 pppSetAuth(PPPAUTHTYPE_NONE
, NULL
, NULL
);
445 subnetMask
= PP_HTONL(0xffffff00UL
);
447 for (i
= 0; i
< NUM_PPP
; i
++) {
448 /* Initialize each protocol to the standard option set. */
449 for (j
= 0; (protp
= ppp_protocols
[j
]) != NULL
; ++j
) {
454 sys_mbox_new(&pppMbox
, 1);
455 sys_thread_new(PPP_THREAD_NAME
, pppInputThread
, (void*)NULL
, PPP_THREAD_STACKSIZE
, PPP_THREAD_PRIO
); //Create PPP thread here
459 pppSetAuth(enum pppAuthType authType
, const char *user
, const char *passwd
)
462 case PPPAUTHTYPE_NONE
:
464 #ifdef LWIP_PPP_STRICT_PAP_REJECT
465 ppp_settings
.refuse_pap
= 1;
466 #else /* LWIP_PPP_STRICT_PAP_REJECT */
467 /* some providers request pap and accept an empty login/pw */
468 ppp_settings
.refuse_pap
= 0;
469 #endif /* LWIP_PPP_STRICT_PAP_REJECT */
470 ppp_settings
.refuse_chap
= 1;
473 case PPPAUTHTYPE_ANY
:
474 /* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
477 * In practice, within or associated with each PPP server, there is a
478 * database which associates "user" names with authentication
479 * information ("secrets"). It is not anticipated that a particular
480 * named user would be authenticated by multiple methods. This would
481 * make the user vulnerable to attacks which negotiate the least secure
482 * method from among a set (such as PAP rather than CHAP). If the same
483 * secret was used, PAP would reveal the secret to be used later with
486 * Instead, for each user name there should be an indication of exactly
487 * one method used to authenticate that user name. If a user needs to
488 * make use of different authentication methods under different
489 * circumstances, then distinct user names SHOULD be employed, each of
490 * which identifies exactly one authentication method.
493 ppp_settings
.refuse_pap
= 0;
494 ppp_settings
.refuse_chap
= 0;
497 case PPPAUTHTYPE_PAP
:
498 ppp_settings
.refuse_pap
= 0;
499 ppp_settings
.refuse_chap
= 1;
502 case PPPAUTHTYPE_CHAP
:
503 ppp_settings
.refuse_pap
= 1;
504 ppp_settings
.refuse_chap
= 0;
509 strncpy(ppp_settings
.user
, user
, sizeof(ppp_settings
.user
)-1);
510 ppp_settings
.user
[sizeof(ppp_settings
.user
)-1] = '\0';
512 ppp_settings
.user
[0] = '\0';
516 strncpy(ppp_settings
.passwd
, passwd
, sizeof(ppp_settings
.passwd
)-1);
517 ppp_settings
.passwd
[sizeof(ppp_settings
.passwd
)-1] = '\0';
519 ppp_settings
.passwd
[0] = '\0';
524 /** Open a new PPP connection using the given I/O device.
525 * This initializes the PPP control block but does not
526 * attempt to negotiate the LCP session. If this port
527 * connects to a modem, the modem connection must be
528 * established before calling this.
529 * Return a new PPP connection descriptor on success or
530 * an error code (negative) on failure.
532 * pppOpen() is directly defined to this function.
535 pppOverSerialOpen(sio_fd_t fd
, void (*linkStatusCB
)(void *ctx
, int errCode
, void *arg
), void *linkStatusCtx
)
540 if (linkStatusCB
== NULL
) {
541 /* PPP is single-threaded: without a callback,
542 * there is no way to know when the link is up. */
546 /* Find a free PPP session descriptor. */
547 for (pd
= 0; pd
< NUM_PPP
&& pppControl
[pd
].openFlag
!= 0; pd
++);
552 pc
= &pppControl
[pd
];
553 /* @todo: is this correct or do I overwrite something? */
554 memset(pc
, 0, sizeof(PPPControl
));
562 vj_compress_init(&pc
->vjComp
);
563 #endif /* VJ_SUPPORT */
566 * Default the in and out accm so that escape and flag characters
567 * are always escaped.
569 pc
->rx
.inACCM
[15] = 0x60; /* no need to protect since RX is not running */
570 pc
->outACCM
[15] = 0x60;
572 pc
->linkStatusCB
= linkStatusCB
;
573 pc
->linkStatusCtx
= linkStatusCtx
;
576 * Start the connection and handle incoming events (packet or timeout).
578 PPPDEBUG(LOG_INFO
, ("pppOverSerialOpen: unit %d: Connecting\n", pd
));
580 #if PPP_INPROC_OWNTHREAD
581 sys_mbox_post(&pppMbox
, (void*)&pc
->rx
);
587 #endif /* PPPOS_SUPPORT */
590 static void pppOverEthernetLinkStatusCB(int pd
, int up
);
593 pppOverEthernetClose(int pd
)
595 PPPControl
* pc
= &pppControl
[pd
];
597 /* *TJL* There's no lcp_deinit */
600 pppoe_destroy(&pc
->netif
);
603 int pppOverEthernetOpen(struct netif
*ethif
, const char *service_name
, const char *concentrator_name
, void (*linkStatusCB
)(void *ctx
, int errCode
, void *arg
), void *linkStatusCtx
)
608 LWIP_UNUSED_ARG(service_name
);
609 LWIP_UNUSED_ARG(concentrator_name
);
611 if (linkStatusCB
== NULL
) {
612 /* PPP is single-threaded: without a callback,
613 * there is no way to know when the link is up. */
617 /* Find a free PPP session descriptor. Critical region? */
618 for (pd
= 0; pd
< NUM_PPP
&& pppControl
[pd
].openFlag
!= 0; pd
++);
622 pc
= &pppControl
[pd
];
623 memset(pc
, 0, sizeof(PPPControl
));
627 pc
->linkStatusCB
= linkStatusCB
;
628 pc
->linkStatusCtx
= linkStatusCtx
;
630 lcp_wantoptions
[pd
].mru
= PPPOE_MAXMTU
;
631 lcp_wantoptions
[pd
].neg_asyncmap
= 0;
632 lcp_wantoptions
[pd
].neg_pcompression
= 0;
633 lcp_wantoptions
[pd
].neg_accompression
= 0;
635 lcp_allowoptions
[pd
].mru
= PPPOE_MAXMTU
;
636 lcp_allowoptions
[pd
].neg_asyncmap
= 0;
637 lcp_allowoptions
[pd
].neg_pcompression
= 0;
638 lcp_allowoptions
[pd
].neg_accompression
= 0;
640 if(pppoe_create(ethif
, pd
, pppOverEthernetLinkStatusCB
, &pc
->pppoe_sc
) != ERR_OK
) {
645 pppoe_connect(pc
->pppoe_sc
);
650 #endif /* PPPOE_SUPPORT */
653 /* Close a PPP connection and release the descriptor.
654 * Any outstanding packets in the queues are dropped.
655 * Return 0 on success, an error code on failure. */
659 PPPControl
*pc
= &pppControl
[pd
];
662 PPPDEBUG(LOG_DEBUG
, ("pppClose() called\n"));
667 PPPDEBUG(LOG_DEBUG
, ("pppClose: unit %d kill_link -> pppStop\n", pd
));
668 pc
->errCode
= PPPERR_USER
;
669 /* This will leave us at PHASE_DEAD. */
672 #endif /* PPPOE_SUPPORT */
675 PPPDEBUG(LOG_DEBUG
, ("pppClose: unit %d kill_link -> pppStop\n", pd
));
676 pc
->errCode
= PPPERR_USER
;
677 /* This will leave us at PHASE_DEAD. */
680 #endif /* PPPOS_SUPPORT */
686 /* This function is called when carrier is lost on the PPP channel. */
690 PPPDEBUG(LOG_DEBUG
, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd
));
696 nPut(PPPControl
*pc
, struct pbuf
*nb
)
701 for(b
= nb
; b
!= NULL
; b
= b
->next
) {
702 if((c
= sio_write(pc
->fd
, b
->payload
, b
->len
)) != b
->len
) {
703 PPPDEBUG(LOG_WARNING
,
704 ("PPP nPut: incomplete sio_write(fd:%"SZT_F
", len:%d, c: 0x%"X8_F
") c = %d\n", (size_t)pc
->fd
, b
->len
, c
, c
));
705 LINK_STATS_INC(link
.err
);
706 pc
->lastXMit
= 0; /* prepend PPP_FLAG to next packet */
707 snmp_inc_ifoutdiscards(&pc
->netif
);
713 snmp_add_ifoutoctets(&pc
->netif
, nb
->tot_len
);
714 snmp_inc_ifoutucastpkts(&pc
->netif
);
716 LINK_STATS_INC(link
.xmit
);
720 * pppAppend - append given character to end of given pbuf. If outACCM
721 * is not NULL and the character needs to be escaped, do so.
722 * If pbuf is full, append another.
723 * Return the current pbuf.
726 pppAppend(u_char c
, struct pbuf
*nb
, ext_accm
*outACCM
)
728 struct pbuf
*tb
= nb
;
730 /* Make sure there is room for the character and an escape code.
731 * Sure we don't quite fill the buffer if the character doesn't
732 * get escaped but is one character worth complicating this? */
733 /* Note: We assume no packet header. */
734 if (nb
&& (PBUF_POOL_BUFSIZE
- nb
->len
) < 2) {
735 tb
= pbuf_alloc(PBUF_RAW
, 0, PBUF_POOL
);
739 LINK_STATS_INC(link
.memerr
);
745 if (outACCM
&& ESCAPE_P(*outACCM
, c
)) {
746 *((u_char
*)nb
->payload
+ nb
->len
++) = PPP_ESCAPE
;
747 *((u_char
*)nb
->payload
+ nb
->len
++) = c
^ PPP_TRANS
;
749 *((u_char
*)nb
->payload
+ nb
->len
++) = c
;
755 #endif /* PPPOS_SUPPORT */
759 pppifOutputOverEthernet(int pd
, struct pbuf
*p
)
761 PPPControl
*pc
= &pppControl
[pd
];
763 u_short protocol
= PPP_IP
;
767 /* @todo: try to use pbuf_header() here! */
768 pb
= pbuf_alloc(PBUF_LINK
, PPPOE_HDRLEN
+ sizeof(protocol
), PBUF_RAM
);
770 LINK_STATS_INC(link
.memerr
);
771 LINK_STATS_INC(link
.proterr
);
772 snmp_inc_ifoutdiscards(&pc
->netif
);
776 pbuf_header(pb
, -(s16_t
)PPPOE_HDRLEN
);
778 pc
->lastXMit
= sys_jiffies();
780 if (!pc
->pcomp
|| protocol
> 0xFF) {
781 *((u_char
*)pb
->payload
+ i
++) = (protocol
>> 8) & 0xFF;
783 *((u_char
*)pb
->payload
+ i
) = protocol
& 0xFF;
786 tot_len
= pb
->tot_len
;
788 if(pppoe_xmit(pc
->pppoe_sc
, pb
) != ERR_OK
) {
789 LINK_STATS_INC(link
.err
);
790 snmp_inc_ifoutdiscards(&pc
->netif
);
791 return PPPERR_DEVICE
;
794 snmp_add_ifoutoctets(&pc
->netif
, tot_len
);
795 snmp_inc_ifoutucastpkts(&pc
->netif
);
796 LINK_STATS_INC(link
.xmit
);
799 #endif /* PPPOE_SUPPORT */
801 /* Send a packet on the given connection. */
803 pppifOutput(struct netif
*netif
, struct pbuf
*pb
, ip_addr_t
*ipaddr
)
805 int pd
= (int)(size_t)netif
->state
;
806 PPPControl
*pc
= &pppControl
[pd
];
808 u_short protocol
= PPP_IP
;
809 u_int fcsOut
= PPP_INITFCS
;
810 struct pbuf
*headMB
= NULL
, *tailMB
= NULL
, *p
;
812 #endif /* PPPOS_SUPPORT */
814 LWIP_UNUSED_ARG(ipaddr
);
816 /* Validate parameters. */
817 /* We let any protocol value go through - it can't hurt us
818 * and the peer will just drop it if it's not accepting it. */
819 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
|| !pb
) {
820 PPPDEBUG(LOG_WARNING
, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n",
822 LINK_STATS_INC(link
.opterr
);
823 LINK_STATS_INC(link
.drop
);
824 snmp_inc_ifoutdiscards(netif
);
828 /* Check that the link is up. */
829 if (lcp_phase
[pd
] == PHASE_DEAD
) {
830 PPPDEBUG(LOG_ERR
, ("pppifOutput[%d]: link not up\n", pd
));
831 LINK_STATS_INC(link
.rterr
);
832 LINK_STATS_INC(link
.drop
);
833 snmp_inc_ifoutdiscards(netif
);
839 return pppifOutputOverEthernet(pd
, pb
);
841 #endif /* PPPOE_SUPPORT */
844 /* Grab an output buffer. */
845 headMB
= pbuf_alloc(PBUF_RAW
, 0, PBUF_POOL
);
846 if (headMB
== NULL
) {
847 PPPDEBUG(LOG_WARNING
, ("pppifOutput[%d]: first alloc fail\n", pd
));
848 LINK_STATS_INC(link
.memerr
);
849 LINK_STATS_INC(link
.drop
);
850 snmp_inc_ifoutdiscards(netif
);
856 * Attempt Van Jacobson header compression if VJ is configured and
857 * this is an IP packet.
859 if (protocol
== PPP_IP
&& pc
->vjEnabled
) {
860 switch (vj_compress_tcp(&pc
->vjComp
, pb
)) {
863 protocol = PPP_IP_PROTOCOL; */
865 case TYPE_COMPRESSED_TCP
:
866 protocol
= PPP_VJC_COMP
;
868 case TYPE_UNCOMPRESSED_TCP
:
869 protocol
= PPP_VJC_UNCOMP
;
872 PPPDEBUG(LOG_WARNING
, ("pppifOutput[%d]: bad IP packet\n", pd
));
873 LINK_STATS_INC(link
.proterr
);
874 LINK_STATS_INC(link
.drop
);
875 snmp_inc_ifoutdiscards(netif
);
880 #endif /* VJ_SUPPORT */
884 /* Build the PPP header. */
885 if ((sys_jiffies() - pc
->lastXMit
) >= PPP_MAXIDLEFLAG
) {
886 tailMB
= pppAppend(PPP_FLAG
, tailMB
, NULL
);
889 pc
->lastXMit
= sys_jiffies();
891 fcsOut
= PPP_FCS(fcsOut
, PPP_ALLSTATIONS
);
892 tailMB
= pppAppend(PPP_ALLSTATIONS
, tailMB
, &pc
->outACCM
);
893 fcsOut
= PPP_FCS(fcsOut
, PPP_UI
);
894 tailMB
= pppAppend(PPP_UI
, tailMB
, &pc
->outACCM
);
896 if (!pc
->pcomp
|| protocol
> 0xFF) {
897 c
= (protocol
>> 8) & 0xFF;
898 fcsOut
= PPP_FCS(fcsOut
, c
);
899 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
902 fcsOut
= PPP_FCS(fcsOut
, c
);
903 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
906 for(p
= pb
; p
; p
= p
->next
) {
910 sPtr
= (u_char
*)p
->payload
;
915 /* Update FCS before checking for special characters. */
916 fcsOut
= PPP_FCS(fcsOut
, c
);
918 /* Copy to output buffer escaping special characters. */
919 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
923 /* Add FCS and trailing flag. */
925 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
926 c
= (~fcsOut
>> 8) & 0xFF;
927 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
928 tailMB
= pppAppend(PPP_FLAG
, tailMB
, NULL
);
930 /* If we failed to complete the packet, throw it away. */
932 PPPDEBUG(LOG_WARNING
,
933 ("pppifOutput[%d]: Alloc err - dropping proto=%d\n",
936 LINK_STATS_INC(link
.memerr
);
937 LINK_STATS_INC(link
.drop
);
938 snmp_inc_ifoutdiscards(netif
);
943 PPPDEBUG(LOG_INFO
, ("pppifOutput[%d]: proto=0x%"X16_F
"\n", pd
, protocol
));
946 #endif /* PPPOS_SUPPORT */
951 /* Get and set parameters for the given connection.
952 * Return 0 on success, an error code on failure. */
954 pppIOCtl(int pd
, int cmd
, void *arg
)
956 PPPControl
*pc
= &pppControl
[pd
];
959 if (pd
< 0 || pd
>= NUM_PPP
) {
963 case PPPCTLG_UPSTATUS
: /* Get the PPP up status. */
965 *(int *)arg
= (int)(pc
->if_up
);
970 case PPPCTLS_ERRCODE
: /* Set the PPP error code. */
972 pc
->errCode
= *(int *)arg
;
977 case PPPCTLG_ERRCODE
: /* Get the PPP error code. */
979 *(int *)arg
= (int)(pc
->errCode
);
985 case PPPCTLG_FD
: /* Get the fd associated with the ppp */
987 *(sio_fd_t
*)arg
= pc
->fd
;
992 #endif /* PPPOS_SUPPORT */
1003 * Return the Maximum Transmission Unit for the given PPP connection.
1008 PPPControl
*pc
= &pppControl
[pd
];
1011 /* Validate parameters. */
1012 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
) {
1023 pppWriteOverEthernet(int pd
, const u_char
*s
, int n
)
1025 PPPControl
*pc
= &pppControl
[pd
];
1028 /* skip address & flags */
1032 LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN
+ n
<= 0xffff);
1033 pb
= pbuf_alloc(PBUF_LINK
, (u16_t
)(PPPOE_HDRLEN
+ n
), PBUF_RAM
);
1035 LINK_STATS_INC(link
.memerr
);
1036 LINK_STATS_INC(link
.proterr
);
1037 snmp_inc_ifoutdiscards(&pc
->netif
);
1038 return PPPERR_ALLOC
;
1041 pbuf_header(pb
, -(s16_t
)PPPOE_HDRLEN
);
1043 pc
->lastXMit
= sys_jiffies();
1045 MEMCPY(pb
->payload
, s
, n
);
1047 if(pppoe_xmit(pc
->pppoe_sc
, pb
) != ERR_OK
) {
1048 LINK_STATS_INC(link
.err
);
1049 snmp_inc_ifoutdiscards(&pc
->netif
);
1050 return PPPERR_DEVICE
;
1053 snmp_add_ifoutoctets(&pc
->netif
, (u16_t
)n
);
1054 snmp_inc_ifoutucastpkts(&pc
->netif
);
1055 LINK_STATS_INC(link
.xmit
);
1058 #endif /* PPPOE_SUPPORT */
1061 * Write n characters to a ppp link.
1062 * RETURN: >= 0 Number of characters written
1063 * -1 Failed to write to device
1066 pppWrite(int pd
, const u_char
*s
, int n
)
1068 PPPControl
*pc
= &pppControl
[pd
];
1072 struct pbuf
*headMB
, *tailMB
;
1073 #endif /* PPPOS_SUPPORT */
1077 return pppWriteOverEthernet(pd
, s
, n
);
1079 #endif /* PPPOE_SUPPORT */
1082 headMB
= pbuf_alloc(PBUF_RAW
, 0, PBUF_POOL
);
1083 if (headMB
== NULL
) {
1084 LINK_STATS_INC(link
.memerr
);
1085 LINK_STATS_INC(link
.proterr
);
1086 snmp_inc_ifoutdiscards(&pc
->netif
);
1087 return PPPERR_ALLOC
;
1092 /* If the link has been idle, we'll send a fresh flag character to
1093 * flush any noise. */
1094 if ((sys_jiffies() - pc
->lastXMit
) >= PPP_MAXIDLEFLAG
) {
1095 tailMB
= pppAppend(PPP_FLAG
, tailMB
, NULL
);
1097 pc
->lastXMit
= sys_jiffies();
1099 fcsOut
= PPP_INITFCS
;
1100 /* Load output buffer. */
1104 /* Update FCS before checking for special characters. */
1105 fcsOut
= PPP_FCS(fcsOut
, c
);
1107 /* Copy to output buffer escaping special characters. */
1108 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
1111 /* Add FCS and trailing flag. */
1113 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
1114 c
= (~fcsOut
>> 8) & 0xFF;
1115 tailMB
= pppAppend(c
, tailMB
, &pc
->outACCM
);
1116 tailMB
= pppAppend(PPP_FLAG
, tailMB
, NULL
);
1118 /* If we failed to complete the packet, throw it away.
1119 * Otherwise send it. */
1121 PPPDEBUG(LOG_WARNING
,
1122 ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd
, headMB
->len
));
1123 /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
1125 LINK_STATS_INC(link
.memerr
);
1126 LINK_STATS_INC(link
.proterr
);
1127 snmp_inc_ifoutdiscards(&pc
->netif
);
1128 return PPPERR_ALLOC
;
1131 PPPDEBUG(LOG_INFO
, ("pppWrite[%d]: len=%d\n", pd
, headMB
->len
));
1132 /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
1134 #endif /* PPPOS_SUPPORT */
1140 * ppp_send_config - configure the transmit characteristics of
1141 * the ppp interface.
1144 ppp_send_config( int unit
, u16_t mtu
, u32_t asyncmap
, int pcomp
, int accomp
)
1146 PPPControl
*pc
= &pppControl
[unit
];
1151 pc
->accomp
= accomp
;
1153 /* Load the ACCM bits for the 32 control codes. */
1154 for (i
= 0; i
< 32/8; i
++) {
1155 pc
->outACCM
[i
] = (u_char
)((asyncmap
>> (8 * i
)) & 0xFF);
1157 PPPDEBUG(LOG_INFO
, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n",
1159 pc
->outACCM
[0], pc
->outACCM
[1], pc
->outACCM
[2], pc
->outACCM
[3]));
1164 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
1167 ppp_set_xaccm(int unit
, ext_accm
*accm
)
1169 SMEMCPY(pppControl
[unit
].outACCM
, accm
, sizeof(ext_accm
));
1170 PPPDEBUG(LOG_INFO
, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
1172 pppControl
[unit
].outACCM
[0],
1173 pppControl
[unit
].outACCM
[1],
1174 pppControl
[unit
].outACCM
[2],
1175 pppControl
[unit
].outACCM
[3]));
1180 * ppp_recv_config - configure the receive-side characteristics of
1181 * the ppp interface.
1184 ppp_recv_config( int unit
, int mru
, u32_t asyncmap
, int pcomp
, int accomp
)
1186 PPPControl
*pc
= &pppControl
[unit
];
1188 SYS_ARCH_DECL_PROTECT(lev
);
1190 LWIP_UNUSED_ARG(accomp
);
1191 LWIP_UNUSED_ARG(pcomp
);
1192 LWIP_UNUSED_ARG(mru
);
1194 /* Load the ACCM bits for the 32 control codes. */
1195 SYS_ARCH_PROTECT(lev
);
1196 for (i
= 0; i
< 32 / 8; i
++) {
1197 /* @todo: does this work? ext_accm has been modified from pppd! */
1198 pc
->rx
.inACCM
[i
] = (u_char
)(asyncmap
>> (i
* 8));
1200 SYS_ARCH_UNPROTECT(lev
);
1201 PPPDEBUG(LOG_INFO
, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
1203 pc
->rx
.inACCM
[0], pc
->rx
.inACCM
[1], pc
->rx
.inACCM
[2], pc
->rx
.inACCM
[3]));
1208 * ccp_test - ask kernel whether a given compression method
1209 * is acceptable for use. Returns 1 if the method and parameters
1210 * are OK, 0 if the method is known but the parameters are not OK
1211 * (e.g. code size should be reduced), or -1 if the method is unknown.
1214 ccp_test( int unit
, int opt_len
, int for_transmit
, u_char
*opt_ptr
)
1216 return 0; /* XXX Currently no compression. */
1220 * ccp_flags_set - inform kernel about the current state of CCP.
1223 ccp_flags_set(int unit
, int isopen
, int isup
)
1229 * ccp_fatal_error - returns 1 if decompression was disabled as a
1230 * result of an error detected after decompression of a packet,
1231 * 0 otherwise. This is necessary because of patent nonsense.
1234 ccp_fatal_error(int unit
)
1242 * get_idle_time - return how long the link has been idle.
1245 get_idle_time(int u
, struct ppp_idle
*ip
)
1249 LWIP_UNUSED_ARG(ip
);
1256 * Return user specified netmask, modified by any mask we might determine
1257 * for address `addr' (in network byte order).
1258 * Here we scan through the system's list of interfaces, looking for
1259 * any non-point-to-point interfaces which might appear to be on the same
1260 * network as `addr'. If we find any, we OR in their netmask to the
1261 * user-specified netmask.
1269 if (IP_CLASSA(addr
)) { /* determine network mask for address class */
1270 nmask
= IP_CLASSA_NET
;
1271 } else if (IP_CLASSB(addr
)) {
1272 nmask
= IP_CLASSB_NET
;
1274 nmask
= IP_CLASSC_NET
;
1277 /* class D nets are disallowed by bad_ip_adrs */
1278 mask
= subnetMask
| htonl(nmask
);
1281 * Scan through the system's network interfaces.
1282 * Get each netmask and OR them into our mask.
1289 * sifvjcomp - config tcp header compression
1292 sifvjcomp(int pd
, int vjcomp
, u8_t cidcomp
, u8_t maxcid
)
1294 #if PPPOS_SUPPORT && VJ_SUPPORT
1295 PPPControl
*pc
= &pppControl
[pd
];
1297 pc
->vjEnabled
= vjcomp
;
1298 pc
->vjComp
.compressSlot
= cidcomp
;
1299 pc
->vjComp
.maxSlotIndex
= maxcid
;
1300 PPPDEBUG(LOG_INFO
, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
1301 vjcomp
, cidcomp
, maxcid
));
1302 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
1303 LWIP_UNUSED_ARG(pd
);
1304 LWIP_UNUSED_ARG(vjcomp
);
1305 LWIP_UNUSED_ARG(cidcomp
);
1306 LWIP_UNUSED_ARG(maxcid
);
1307 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
1313 * pppifNetifInit - netif init callback
1316 pppifNetifInit(struct netif
*netif
)
1318 netif
->name
[0] = 'p';
1319 netif
->name
[1] = 'p';
1320 netif
->output
= pppifOutput
;
1321 netif
->mtu
= pppMTU((int)(size_t)netif
->state
);
1322 netif
->flags
= NETIF_FLAG_POINTTOPOINT
| NETIF_FLAG_LINK_UP
;
1323 #if LWIP_NETIF_HOSTNAME
1324 /* @todo: Initialize interface hostname */
1325 /* netif_set_hostname(netif, "lwip"); */
1326 #endif /* LWIP_NETIF_HOSTNAME */
1332 * sifup - Config the interface up and enable IP packets to pass.
1337 PPPControl
*pc
= &pppControl
[pd
];
1340 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
) {
1342 PPPDEBUG(LOG_WARNING
, ("sifup[%d]: bad parms\n", pd
));
1344 netif_remove(&pc
->netif
);
1345 if (netif_add(&pc
->netif
, &pc
->addrs
.our_ipaddr
, &pc
->addrs
.netmask
,
1346 &pc
->addrs
.his_ipaddr
, (void *)(size_t)pd
, pppifNetifInit
, ip_input
)) {
1347 netif_set_up(&pc
->netif
);
1349 pc
->errCode
= PPPERR_NONE
;
1351 PPPDEBUG(LOG_DEBUG
, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd
, pc
->linkStatusCB
, pc
->errCode
));
1352 if (pc
->linkStatusCB
) {
1353 pc
->linkStatusCB(pc
->linkStatusCtx
, pc
->errCode
, &pc
->addrs
);
1357 PPPDEBUG(LOG_ERR
, ("sifup[%d]: netif_add failed\n", pd
));
1365 * sifnpmode - Set the mode for handling packets for a given NP.
1368 sifnpmode(int u
, int proto
, enum NPmode mode
)
1371 LWIP_UNUSED_ARG(proto
);
1372 LWIP_UNUSED_ARG(mode
);
1377 * sifdown - Config the interface down and disable IP.
1382 PPPControl
*pc
= &pppControl
[pd
];
1385 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
) {
1387 PPPDEBUG(LOG_WARNING
, ("sifdown[%d]: bad parms\n", pd
));
1390 /* make sure the netif status callback is called */
1391 netif_set_down(&pc
->netif
);
1392 netif_remove(&pc
->netif
);
1393 PPPDEBUG(LOG_DEBUG
, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd
, pc
->linkStatusCB
, pc
->errCode
));
1394 if (pc
->linkStatusCB
) {
1395 pc
->linkStatusCB(pc
->linkStatusCtx
, PPPERR_CONNECT
, NULL
);
1402 * sifaddr - Config the interface IP addresses and netmask.
1403 * @param pd Interface unit ???
1404 * @param o Our IP address ???
1405 * @param h His IP address ???
1406 * @param m IP subnet mask ???
1407 * @param ns1 Primary DNS
1408 * @param ns2 Secondary DNS
1411 sifaddr( int pd
, u32_t o
, u32_t h
, u32_t m
, u32_t ns1
, u32_t ns2
)
1413 PPPControl
*pc
= &pppControl
[pd
];
1416 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
) {
1418 PPPDEBUG(LOG_WARNING
, ("sifup[%d]: bad parms\n", pd
));
1420 SMEMCPY(&pc
->addrs
.our_ipaddr
, &o
, sizeof(o
));
1421 SMEMCPY(&pc
->addrs
.his_ipaddr
, &h
, sizeof(h
));
1422 SMEMCPY(&pc
->addrs
.netmask
, &m
, sizeof(m
));
1423 SMEMCPY(&pc
->addrs
.dns1
, &ns1
, sizeof(ns1
));
1424 SMEMCPY(&pc
->addrs
.dns2
, &ns2
, sizeof(ns2
));
1430 * cifaddr - Clear the interface IP addresses, and delete routes
1431 * through the interface if possible.
1432 * @param pd Interface unit ???
1433 * @param o Our IP address ???
1434 * @param h IP broadcast address ???
1437 cifaddr( int pd
, u32_t o
, u32_t h
)
1439 PPPControl
*pc
= &pppControl
[pd
];
1444 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
) {
1446 PPPDEBUG(LOG_WARNING
, ("sifup[%d]: bad parms\n", pd
));
1448 IP4_ADDR(&pc
->addrs
.our_ipaddr
, 0,0,0,0);
1449 IP4_ADDR(&pc
->addrs
.his_ipaddr
, 0,0,0,0);
1450 IP4_ADDR(&pc
->addrs
.netmask
, 255,255,255,0);
1451 IP4_ADDR(&pc
->addrs
.dns1
, 0,0,0,0);
1452 IP4_ADDR(&pc
->addrs
.dns2
, 0,0,0,0);
1458 * sifdefaultroute - assign a default route through the address given.
1461 sifdefaultroute(int pd
, u32_t l
, u32_t g
)
1463 PPPControl
*pc
= &pppControl
[pd
];
1469 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
) {
1471 PPPDEBUG(LOG_WARNING
, ("sifup[%d]: bad parms\n", pd
));
1473 netif_set_default(&pc
->netif
);
1476 /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
1482 * cifdefaultroute - delete a default route through the address given.
1485 cifdefaultroute(int pd
, u32_t l
, u32_t g
)
1487 PPPControl
*pc
= &pppControl
[pd
];
1493 if (pd
< 0 || pd
>= NUM_PPP
|| !pc
->openFlag
) {
1495 PPPDEBUG(LOG_WARNING
, ("sifup[%d]: bad parms\n", pd
));
1497 netif_set_default(NULL
);
1503 /**********************************/
1504 /*** LOCAL FUNCTION DEFINITIONS ***/
1505 /**********************************/
1507 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD
1508 /* The main PPP process function. This implements the state machine according
1509 * to section 4 of RFC 1661: The Point-To-Point Protocol. */
1511 pppInputThread(void *arg
)
1514 PPPControlRx
*pcrx
= arg
;
1518 sys_arch_mbox_fetch(&pppMbox
, (void**)&pcrx
, 0); //Wait indefinitely
1520 while (lcp_phase
[pcrx
->pd
] != PHASE_DEAD
) {
1521 count
= sio_read(pcrx
->fd
, pcrx
->rxbuf
, PPPOS_RX_BUFSIZE
);
1523 pppInProc(pcrx
, pcrx
->rxbuf
, count
);
1525 /* nothing received, give other tasks a chance to run */
1529 } while(1); //Never terminates
1531 #endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */
1536 pppOverEthernetInitFailed(int pd
)
1543 pc
= &pppControl
[pd
];
1544 pppoe_destroy(&pc
->netif
);
1547 if(pc
->linkStatusCB
) {
1548 pc
->linkStatusCB(pc
->linkStatusCtx
, pc
->errCode
? pc
->errCode
: PPPERR_PROTOCOL
, NULL
);
1553 pppOverEthernetLinkStatusCB(int pd
, int up
)
1556 PPPDEBUG(LOG_INFO
, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd
));
1559 pppOverEthernetInitFailed(pd
);
1562 #endif /* PPPOE_SUPPORT */
1565 pppSingleBuf(struct pbuf
*p
)
1570 if(p
->tot_len
== p
->len
) {
1574 q
= pbuf_alloc(PBUF_RAW
, p
->tot_len
, PBUF_RAM
);
1577 ("pppSingleBuf: unable to alloc new buf (%d)\n", p
->tot_len
));
1578 return p
; /* live dangerously */
1581 for(b
= p
, pl
= q
->payload
; b
!= NULL
; b
= b
->next
) {
1582 MEMCPY(pl
, b
->payload
, b
->len
);
1591 struct pppInputHeader
{
1597 * Pass the processed input packet to the appropriate handler.
1598 * This function and all handlers run in the context of the tcpip_thread
1603 struct pbuf
*nb
= (struct pbuf
*)arg
;
1607 pd
= ((struct pppInputHeader
*)nb
->payload
)->unit
;
1608 protocol
= ((struct pppInputHeader
*)nb
->payload
)->proto
;
1610 if(pbuf_header(nb
, -(int)sizeof(struct pppInputHeader
))) {
1611 LWIP_ASSERT("pbuf_header failed\n", 0);
1615 LINK_STATS_INC(link
.recv
);
1616 snmp_inc_ifinucastpkts(&pppControl
[pd
].netif
);
1617 snmp_add_ifinoctets(&pppControl
[pd
].netif
, nb
->tot_len
);
1620 * Toss all non-LCP packets unless LCP is OPEN.
1621 * Until we get past the authentication phase, toss all packets
1622 * except LCP, LQR and authentication packets.
1624 if((lcp_phase
[pd
] <= PHASE_AUTHENTICATE
) && (protocol
!= PPP_LCP
)) {
1625 if(!((protocol
== PPP_LQR
) || (protocol
== PPP_PAP
) || (protocol
== PPP_CHAP
)) ||
1626 (lcp_phase
[pd
] != PHASE_AUTHENTICATE
)) {
1627 PPPDEBUG(LOG_INFO
, ("pppInput: discarding proto 0x%"X16_F
" in phase %d\n", protocol
, lcp_phase
[pd
]));
1633 case PPP_VJC_COMP
: /* VJ compressed TCP */
1634 #if PPPOS_SUPPORT && VJ_SUPPORT
1635 PPPDEBUG(LOG_INFO
, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd
, nb
->len
));
1637 * Clip off the VJ header and prepend the rebuilt TCP/IP header and
1638 * pass the result to IP.
1640 if ((vj_uncompress_tcp(&nb
, &pppControl
[pd
].vjComp
) >= 0) && (pppControl
[pd
].netif
.input
)) {
1641 pppControl
[pd
].netif
.input(nb
, &pppControl
[pd
].netif
);
1644 /* Something's wrong so drop it. */
1645 PPPDEBUG(LOG_WARNING
, ("pppInput[%d]: Dropping VJ compressed\n", pd
));
1646 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
1647 /* No handler for this protocol so drop the packet. */
1648 PPPDEBUG(LOG_INFO
, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd
, nb
->len
, nb
->payload
));
1649 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
1652 case PPP_VJC_UNCOMP
: /* VJ uncompressed TCP */
1653 #if PPPOS_SUPPORT && VJ_SUPPORT
1654 PPPDEBUG(LOG_INFO
, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd
, nb
->len
));
1656 * Process the TCP/IP header for VJ header compression and then pass
1659 if ((vj_uncompress_uncomp(nb
, &pppControl
[pd
].vjComp
) >= 0) && pppControl
[pd
].netif
.input
) {
1660 pppControl
[pd
].netif
.input(nb
, &pppControl
[pd
].netif
);
1663 /* Something's wrong so drop it. */
1664 PPPDEBUG(LOG_WARNING
, ("pppInput[%d]: Dropping VJ uncompressed\n", pd
));
1665 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
1666 /* No handler for this protocol so drop the packet. */
1668 ("pppInput[%d]: drop VJ UnComp in %d:.*H\n",
1669 pd
, nb
->len
, LWIP_MIN(nb
->len
* 2, 40), nb
->payload
));
1670 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
1673 case PPP_IP
: /* Internet Protocol */
1674 PPPDEBUG(LOG_INFO
, ("pppInput[%d]: ip in pbuf len=%d\n", pd
, nb
->len
));
1675 if (pppControl
[pd
].netif
.input
) {
1676 pppControl
[pd
].netif
.input(nb
, &pppControl
[pd
].netif
);
1682 struct protent
*protp
;
1686 * Upcall the proper protocol input routine.
1688 for (i
= 0; (protp
= ppp_protocols
[i
]) != NULL
; ++i
) {
1689 if (protp
->protocol
== protocol
&& protp
->enabled_flag
) {
1690 PPPDEBUG(LOG_INFO
, ("pppInput[%d]: %s len=%d\n", pd
, protp
->name
, nb
->len
));
1691 nb
= pppSingleBuf(nb
);
1692 (*protp
->input
)(pd
, nb
->payload
, nb
->len
);
1693 PPPDEBUG(LOG_DETAIL
, ("pppInput[%d]: packet processed\n", pd
));
1698 /* No handler for this protocol so reject the packet. */
1699 PPPDEBUG(LOG_INFO
, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F
" len=%d\n", pd
, protocol
, nb
->len
));
1700 if (pbuf_header(nb
, sizeof(protocol
))) {
1701 LWIP_ASSERT("pbuf_header failed\n", 0);
1704 #if BYTE_ORDER == LITTLE_ENDIAN
1705 protocol
= htons(protocol
);
1706 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
1707 SMEMCPY(nb
->payload
, &protocol
, sizeof(protocol
));
1708 lcp_sprotrej(pd
, nb
->payload
, nb
->len
);
1714 LINK_STATS_INC(link
.drop
);
1715 snmp_inc_ifindiscards(&pppControl
[pd
].netif
);
1724 * Drop the input packet.
1727 pppDrop(PPPControlRx
*pcrx
)
1729 if (pcrx
->inHead
!= NULL
) {
1731 PPPDEBUG(LOG_INFO
, ("pppDrop: %d:%.*H\n", pcrx
->inHead
->len
, min(60, pcrx
->inHead
->len
* 2), pcrx
->inHead
->payload
));
1733 PPPDEBUG(LOG_INFO
, ("pppDrop: pbuf len=%d, addr %p\n", pcrx
->inHead
->len
, (void*)pcrx
->inHead
));
1734 if (pcrx
->inTail
&& (pcrx
->inTail
!= pcrx
->inHead
)) {
1735 pbuf_free(pcrx
->inTail
);
1737 pbuf_free(pcrx
->inHead
);
1738 pcrx
->inHead
= NULL
;
1739 pcrx
->inTail
= NULL
;
1742 vj_uncompress_err(&pppControl
[pcrx
->pd
].vjComp
);
1743 #endif /* VJ_SUPPORT */
1745 LINK_STATS_INC(link
.drop
);
1746 snmp_inc_ifindiscards(&pppControl
[pcrx
->pd
].netif
);
1749 /** Pass received raw characters to PPPoS to be decoded. This function is
1750 * thread-safe and can be called from a dedicated RX-thread or from a main-loop.
1752 * @param pd PPP descriptor index, returned by pppOpen()
1753 * @param data received data
1754 * @param len length of received data
1757 pppos_input(int pd
, u_char
* data
, int len
)
1759 pppInProc(&pppControl
[pd
].rx
, data
, len
);
1763 * Process a received octet string.
1766 pppInProc(PPPControlRx
*pcrx
, u_char
*s
, int l
)
1768 struct pbuf
*nextNBuf
;
1771 SYS_ARCH_DECL_PROTECT(lev
);
1773 PPPDEBUG(LOG_DEBUG
, ("pppInProc[%d]: got %d bytes\n", pcrx
->pd
, l
));
1777 SYS_ARCH_PROTECT(lev
);
1778 escaped
= ESCAPE_P(pcrx
->inACCM
, curChar
);
1779 SYS_ARCH_UNPROTECT(lev
);
1780 /* Handle special characters. */
1782 /* Check for escape sequences. */
1783 /* XXX Note that this does not handle an escaped 0x5d character which
1784 * would appear as an escape character. Since this is an ASCII ']'
1785 * and there is no reason that I know of to escape it, I won't complicate
1786 * the code to handle this case. GLL */
1787 if (curChar
== PPP_ESCAPE
) {
1788 pcrx
->inEscaped
= 1;
1789 /* Check for the flag character. */
1790 } else if (curChar
== PPP_FLAG
) {
1791 /* If this is just an extra flag character, ignore it. */
1792 if (pcrx
->inState
<= PDADDRESS
) {
1794 /* If we haven't received the packet header, drop what has come in. */
1795 } else if (pcrx
->inState
< PDDATA
) {
1796 PPPDEBUG(LOG_WARNING
,
1797 ("pppInProc[%d]: Dropping incomplete packet %d\n",
1798 pcrx
->pd
, pcrx
->inState
));
1799 LINK_STATS_INC(link
.lenerr
);
1801 /* If the fcs is invalid, drop the packet. */
1802 } else if (pcrx
->inFCS
!= PPP_GOODFCS
) {
1804 ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F
" proto=0x%"X16_F
"\n",
1805 pcrx
->pd
, pcrx
->inFCS
, pcrx
->inProtocol
));
1806 /* Note: If you get lots of these, check for UART frame errors or try different baud rate */
1807 LINK_STATS_INC(link
.chkerr
);
1809 /* Otherwise it's a good packet so pass it on. */
1812 /* Trim off the checksum. */
1813 if(pcrx
->inTail
->len
>= 2) {
1814 pcrx
->inTail
->len
-= 2;
1816 pcrx
->inTail
->tot_len
= pcrx
->inTail
->len
;
1817 if (pcrx
->inTail
!= pcrx
->inHead
) {
1818 pbuf_cat(pcrx
->inHead
, pcrx
->inTail
);
1821 pcrx
->inTail
->tot_len
= pcrx
->inTail
->len
;
1822 if (pcrx
->inTail
!= pcrx
->inHead
) {
1823 pbuf_cat(pcrx
->inHead
, pcrx
->inTail
);
1826 pbuf_realloc(pcrx
->inHead
, pcrx
->inHead
->tot_len
- 2);
1829 /* Dispatch the packet thereby consuming it. */
1831 /* Packet consumed, release our references. */
1832 pcrx
->inHead
= NULL
;
1833 pcrx
->inTail
= NULL
;
1834 #if PPP_INPROC_MULTITHREADED
1835 if(tcpip_callback_with_block(pppInput
, inp
, 0) != ERR_OK
) {
1836 PPPDEBUG(LOG_ERR
, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx
->pd
));
1838 LINK_STATS_INC(link
.drop
);
1839 snmp_inc_ifindiscards(&pppControl
[pcrx
->pd
].netif
);
1841 #else /* PPP_INPROC_MULTITHREADED */
1843 #endif /* PPP_INPROC_MULTITHREADED */
1846 /* Prepare for a new packet. */
1847 pcrx
->inFCS
= PPP_INITFCS
;
1848 pcrx
->inState
= PDADDRESS
;
1849 pcrx
->inEscaped
= 0;
1850 /* Other characters are usually control characters that may have
1851 * been inserted by the physical layer so here we just drop them. */
1853 PPPDEBUG(LOG_WARNING
,
1854 ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx
->pd
, curChar
));
1856 /* Process other characters. */
1858 /* Unencode escaped characters. */
1859 if (pcrx
->inEscaped
) {
1860 pcrx
->inEscaped
= 0;
1861 curChar
^= PPP_TRANS
;
1864 /* Process character relative to current state. */
1865 switch(pcrx
->inState
) {
1866 case PDIDLE
: /* Idle state - waiting. */
1867 /* Drop the character if it's not 0xff
1868 * we would have processed a flag character above. */
1869 if (curChar
!= PPP_ALLSTATIONS
) {
1874 case PDSTART
: /* Process start flag. */
1875 /* Prepare for a new packet. */
1876 pcrx
->inFCS
= PPP_INITFCS
;
1879 case PDADDRESS
: /* Process address field. */
1880 if (curChar
== PPP_ALLSTATIONS
) {
1881 pcrx
->inState
= PDCONTROL
;
1884 /* Else assume compressed address and control fields so
1885 * fall through to get the protocol... */
1886 case PDCONTROL
: /* Process control field. */
1887 /* If we don't get a valid control code, restart. */
1888 if (curChar
== PPP_UI
) {
1889 pcrx
->inState
= PDPROTOCOL1
;
1894 PPPDEBUG(LOG_WARNING
,
1895 ("pppInProc[%d]: Invalid control <%d>\n", pcrx
->pd
, curChar
));
1896 pcrx
->inState
= PDSTART
;
1899 case PDPROTOCOL1
: /* Process protocol field 1. */
1900 /* If the lower bit is set, this is the end of the protocol
1903 pcrx
->inProtocol
= curChar
;
1904 pcrx
->inState
= PDDATA
;
1906 pcrx
->inProtocol
= (u_int
)curChar
<< 8;
1907 pcrx
->inState
= PDPROTOCOL2
;
1910 case PDPROTOCOL2
: /* Process protocol field 2. */
1911 pcrx
->inProtocol
|= curChar
;
1912 pcrx
->inState
= PDDATA
;
1914 case PDDATA
: /* Process data byte. */
1915 /* Make space to receive processed data. */
1916 if (pcrx
->inTail
== NULL
|| pcrx
->inTail
->len
== PBUF_POOL_BUFSIZE
) {
1917 if (pcrx
->inTail
!= NULL
) {
1918 pcrx
->inTail
->tot_len
= pcrx
->inTail
->len
;
1919 if (pcrx
->inTail
!= pcrx
->inHead
) {
1920 pbuf_cat(pcrx
->inHead
, pcrx
->inTail
);
1921 /* give up the inTail reference now */
1922 pcrx
->inTail
= NULL
;
1925 /* If we haven't started a packet, we need a packet header. */
1926 nextNBuf
= pbuf_alloc(PBUF_RAW
, 0, PBUF_POOL
);
1927 if (nextNBuf
== NULL
) {
1928 /* No free buffers. Drop the input packet and let the
1929 * higher layers deal with it. Continue processing
1930 * the received pbuf chain in case a new packet starts. */
1931 PPPDEBUG(LOG_ERR
, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx
->pd
));
1932 LINK_STATS_INC(link
.memerr
);
1934 pcrx
->inState
= PDSTART
; /* Wait for flag sequence. */
1937 if (pcrx
->inHead
== NULL
) {
1938 struct pppInputHeader
*pih
= nextNBuf
->payload
;
1940 pih
->unit
= pcrx
->pd
;
1941 pih
->proto
= pcrx
->inProtocol
;
1943 nextNBuf
->len
+= sizeof(*pih
);
1945 pcrx
->inHead
= nextNBuf
;
1947 pcrx
->inTail
= nextNBuf
;
1949 /* Load character into buffer. */
1950 ((u_char
*)pcrx
->inTail
->payload
)[pcrx
->inTail
->len
++] = curChar
;
1954 /* update the frame check sequence number. */
1955 pcrx
->inFCS
= PPP_FCS(pcrx
->inFCS
, curChar
);
1957 } /* while (l-- > 0), all bytes processed */
1961 #endif /* PPPOS_SUPPORT */
1965 pppInProcOverEthernet(int pd
, struct pbuf
*pb
)
1967 struct pppInputHeader
*pih
;
1970 if(pb
->len
< sizeof(inProtocol
)) {
1971 PPPDEBUG(LOG_ERR
, ("pppInProcOverEthernet: too small for protocol field\n"));
1975 inProtocol
= (((u8_t
*)pb
->payload
)[0] << 8) | ((u8_t
*)pb
->payload
)[1];
1977 /* make room for pppInputHeader - should not fail */
1978 if (pbuf_header(pb
, sizeof(*pih
) - sizeof(inProtocol
)) != 0) {
1979 PPPDEBUG(LOG_ERR
, ("pppInProcOverEthernet: could not allocate room for header\n"));
1986 pih
->proto
= inProtocol
;
1988 /* Dispatch the packet thereby consuming it. */
1993 LINK_STATS_INC(link
.drop
);
1994 snmp_inc_ifindiscards(&pppControl
[pd
].netif
);
1998 #endif /* PPPOE_SUPPORT */
2000 #if LWIP_NETIF_STATUS_CALLBACK
2001 /** Set the status callback of a PPP's netif
2003 * @param pd The PPP descriptor returned by pppOpen()
2004 * @param status_callback pointer to the status callback function
2006 * @see netif_set_status_callback
2009 ppp_set_netif_statuscallback(int pd
, netif_status_callback_fn status_callback
)
2011 netif_set_status_callback(&pppControl
[pd
].netif
, status_callback
);
2013 #endif /* LWIP_NETIF_STATUS_CALLBACK */
2015 #if LWIP_NETIF_LINK_CALLBACK
2016 /** Set the link callback of a PPP's netif
2018 * @param pd The PPP descriptor returned by pppOpen()
2019 * @param link_callback pointer to the link callback function
2021 * @see netif_set_link_callback
2024 ppp_set_netif_linkcallback(int pd
, netif_status_callback_fn link_callback
)
2026 netif_set_link_callback(&pppControl
[pd
].netif
, link_callback
);
2028 #endif /* LWIP_NETIF_LINK_CALLBACK */
2030 #endif /* PPP_SUPPORT */