Bonjour/Zerconf library

Dependencies:   mbed

Committer:
dirkx
Date:
Sat Aug 14 15:54:31 2010 +0000
Revision:
5:8e53abda9900
Parent:
0:355018f44c9f

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dirkx 0:355018f44c9f 1 /*****************************************************************************
dirkx 0:355018f44c9f 2 * ppp.c - Network Point to Point Protocol program file.
dirkx 0:355018f44c9f 3 *
dirkx 0:355018f44c9f 4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
dirkx 0:355018f44c9f 5 * portions Copyright (c) 1997 by Global Election Systems Inc.
dirkx 0:355018f44c9f 6 *
dirkx 0:355018f44c9f 7 * The authors hereby grant permission to use, copy, modify, distribute,
dirkx 0:355018f44c9f 8 * and license this software and its documentation for any purpose, provided
dirkx 0:355018f44c9f 9 * that existing copyright notices are retained in all copies and that this
dirkx 0:355018f44c9f 10 * notice and the following disclaimer are included verbatim in any
dirkx 0:355018f44c9f 11 * distributions. No written agreement, license, or royalty fee is required
dirkx 0:355018f44c9f 12 * for any of the authorized uses.
dirkx 0:355018f44c9f 13 *
dirkx 0:355018f44c9f 14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
dirkx 0:355018f44c9f 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
dirkx 0:355018f44c9f 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
dirkx 0:355018f44c9f 17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
dirkx 0:355018f44c9f 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
dirkx 0:355018f44c9f 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
dirkx 0:355018f44c9f 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
dirkx 0:355018f44c9f 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
dirkx 0:355018f44c9f 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
dirkx 0:355018f44c9f 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
dirkx 0:355018f44c9f 24 *
dirkx 0:355018f44c9f 25 ******************************************************************************
dirkx 0:355018f44c9f 26 * REVISION HISTORY
dirkx 0:355018f44c9f 27 *
dirkx 0:355018f44c9f 28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
dirkx 0:355018f44c9f 29 * Ported to lwIP.
dirkx 0:355018f44c9f 30 * 97-11-05 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
dirkx 0:355018f44c9f 31 * Original.
dirkx 0:355018f44c9f 32 *****************************************************************************/
dirkx 0:355018f44c9f 33
dirkx 0:355018f44c9f 34 /*
dirkx 0:355018f44c9f 35 * ppp_defs.h - PPP definitions.
dirkx 0:355018f44c9f 36 *
dirkx 0:355018f44c9f 37 * if_pppvar.h - private structures and declarations for PPP.
dirkx 0:355018f44c9f 38 *
dirkx 0:355018f44c9f 39 * Copyright (c) 1994 The Australian National University.
dirkx 0:355018f44c9f 40 * All rights reserved.
dirkx 0:355018f44c9f 41 *
dirkx 0:355018f44c9f 42 * Permission to use, copy, modify, and distribute this software and its
dirkx 0:355018f44c9f 43 * documentation is hereby granted, provided that the above copyright
dirkx 0:355018f44c9f 44 * notice appears in all copies. This software is provided without any
dirkx 0:355018f44c9f 45 * warranty, express or implied. The Australian National University
dirkx 0:355018f44c9f 46 * makes no representations about the suitability of this software for
dirkx 0:355018f44c9f 47 * any purpose.
dirkx 0:355018f44c9f 48 *
dirkx 0:355018f44c9f 49 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
dirkx 0:355018f44c9f 50 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
dirkx 0:355018f44c9f 51 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
dirkx 0:355018f44c9f 52 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
dirkx 0:355018f44c9f 53 * OF SUCH DAMAGE.
dirkx 0:355018f44c9f 54 *
dirkx 0:355018f44c9f 55 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
dirkx 0:355018f44c9f 56 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
dirkx 0:355018f44c9f 57 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
dirkx 0:355018f44c9f 58 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
dirkx 0:355018f44c9f 59 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
dirkx 0:355018f44c9f 60 * OR MODIFICATIONS.
dirkx 0:355018f44c9f 61 */
dirkx 0:355018f44c9f 62
dirkx 0:355018f44c9f 63 /*
dirkx 0:355018f44c9f 64 * if_ppp.h - Point-to-Point Protocol definitions.
dirkx 0:355018f44c9f 65 *
dirkx 0:355018f44c9f 66 * Copyright (c) 1989 Carnegie Mellon University.
dirkx 0:355018f44c9f 67 * All rights reserved.
dirkx 0:355018f44c9f 68 *
dirkx 0:355018f44c9f 69 * Redistribution and use in source and binary forms are permitted
dirkx 0:355018f44c9f 70 * provided that the above copyright notice and this paragraph are
dirkx 0:355018f44c9f 71 * duplicated in all such forms and that any documentation,
dirkx 0:355018f44c9f 72 * advertising materials, and other materials related to such
dirkx 0:355018f44c9f 73 * distribution and use acknowledge that the software was developed
dirkx 0:355018f44c9f 74 * by Carnegie Mellon University. The name of the
dirkx 0:355018f44c9f 75 * University may not be used to endorse or promote products derived
dirkx 0:355018f44c9f 76 * from this software without specific prior written permission.
dirkx 0:355018f44c9f 77 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
dirkx 0:355018f44c9f 78 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
dirkx 0:355018f44c9f 79 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
dirkx 0:355018f44c9f 80 */
dirkx 0:355018f44c9f 81
dirkx 0:355018f44c9f 82 #include "lwip/opt.h"
dirkx 0:355018f44c9f 83
dirkx 0:355018f44c9f 84 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
dirkx 0:355018f44c9f 85
dirkx 0:355018f44c9f 86 #include "lwip/ip.h" /* for ip_input() */
dirkx 0:355018f44c9f 87
dirkx 0:355018f44c9f 88 #include "ppp.h"
dirkx 0:355018f44c9f 89 #include "pppdebug.h"
dirkx 0:355018f44c9f 90
dirkx 0:355018f44c9f 91 #include "randm.h"
dirkx 0:355018f44c9f 92 #include "fsm.h"
dirkx 0:355018f44c9f 93 #if PAP_SUPPORT
dirkx 0:355018f44c9f 94 #include "pap.h"
dirkx 0:355018f44c9f 95 #endif /* PAP_SUPPORT */
dirkx 0:355018f44c9f 96 #if CHAP_SUPPORT
dirkx 0:355018f44c9f 97 #include "chap.h"
dirkx 0:355018f44c9f 98 #endif /* CHAP_SUPPORT */
dirkx 0:355018f44c9f 99 #include "ipcp.h"
dirkx 0:355018f44c9f 100 #include "lcp.h"
dirkx 0:355018f44c9f 101 #include "magic.h"
dirkx 0:355018f44c9f 102 #include "auth.h"
dirkx 0:355018f44c9f 103 #if VJ_SUPPORT
dirkx 0:355018f44c9f 104 #include "vj.h"
dirkx 0:355018f44c9f 105 #endif /* VJ_SUPPORT */
dirkx 0:355018f44c9f 106 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 107 #include "netif/ppp_oe.h"
dirkx 0:355018f44c9f 108 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 109
dirkx 0:355018f44c9f 110 #include "lwip/tcpip.h"
dirkx 0:355018f44c9f 111 #include "lwip/api.h"
dirkx 0:355018f44c9f 112 #include "lwip/snmp.h"
dirkx 0:355018f44c9f 113
dirkx 0:355018f44c9f 114 #include <string.h>
dirkx 0:355018f44c9f 115
dirkx 0:355018f44c9f 116 /*************************/
dirkx 0:355018f44c9f 117 /*** LOCAL DEFINITIONS ***/
dirkx 0:355018f44c9f 118 /*************************/
dirkx 0:355018f44c9f 119
dirkx 0:355018f44c9f 120 /** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback().
dirkx 0:355018f44c9f 121 * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1.
dirkx 0:355018f44c9f 122 * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded).
dirkx 0:355018f44c9f 123 */
dirkx 0:355018f44c9f 124 #ifndef PPP_INPROC_MULTITHREADED
dirkx 0:355018f44c9f 125 #define PPP_INPROC_MULTITHREADED (NO_SYS==0)
dirkx 0:355018f44c9f 126 #endif
dirkx 0:355018f44c9f 127
dirkx 0:355018f44c9f 128 /** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session.
dirkx 0:355018f44c9f 129 * Default is 0: call pppos_input() for received raw characters, charcater
dirkx 0:355018f44c9f 130 * reception is up to the port */
dirkx 0:355018f44c9f 131 #ifndef PPP_INPROC_OWNTHREAD
dirkx 0:355018f44c9f 132 #define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED
dirkx 0:355018f44c9f 133 #endif
dirkx 0:355018f44c9f 134
dirkx 0:355018f44c9f 135 #if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED
dirkx 0:355018f44c9f 136 #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1"
dirkx 0:355018f44c9f 137 #endif
dirkx 0:355018f44c9f 138
dirkx 0:355018f44c9f 139 /*
dirkx 0:355018f44c9f 140 * The basic PPP frame.
dirkx 0:355018f44c9f 141 */
dirkx 0:355018f44c9f 142 #define PPP_ADDRESS(p) (((u_char *)(p))[0])
dirkx 0:355018f44c9f 143 #define PPP_CONTROL(p) (((u_char *)(p))[1])
dirkx 0:355018f44c9f 144 #define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
dirkx 0:355018f44c9f 145
dirkx 0:355018f44c9f 146 /* PPP packet parser states. Current state indicates operation yet to be
dirkx 0:355018f44c9f 147 * completed. */
dirkx 0:355018f44c9f 148 typedef enum {
dirkx 0:355018f44c9f 149 PDIDLE = 0, /* Idle state - waiting. */
dirkx 0:355018f44c9f 150 PDSTART, /* Process start flag. */
dirkx 0:355018f44c9f 151 PDADDRESS, /* Process address field. */
dirkx 0:355018f44c9f 152 PDCONTROL, /* Process control field. */
dirkx 0:355018f44c9f 153 PDPROTOCOL1, /* Process protocol field 1. */
dirkx 0:355018f44c9f 154 PDPROTOCOL2, /* Process protocol field 2. */
dirkx 0:355018f44c9f 155 PDDATA /* Process data byte. */
dirkx 0:355018f44c9f 156 } PPPDevStates;
dirkx 0:355018f44c9f 157
dirkx 0:355018f44c9f 158 #define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
dirkx 0:355018f44c9f 159
dirkx 0:355018f44c9f 160 /************************/
dirkx 0:355018f44c9f 161 /*** LOCAL DATA TYPES ***/
dirkx 0:355018f44c9f 162 /************************/
dirkx 0:355018f44c9f 163
dirkx 0:355018f44c9f 164 /** RX buffer size: this may be configured smaller! */
dirkx 0:355018f44c9f 165 #ifndef PPPOS_RX_BUFSIZE
dirkx 0:355018f44c9f 166 #define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN)
dirkx 0:355018f44c9f 167 #endif
dirkx 0:355018f44c9f 168
dirkx 0:355018f44c9f 169 typedef struct PPPControlRx_s {
dirkx 0:355018f44c9f 170 /** unit number / ppp descriptor */
dirkx 0:355018f44c9f 171 int pd;
dirkx 0:355018f44c9f 172 /** the rx file descriptor */
dirkx 0:355018f44c9f 173 sio_fd_t fd;
dirkx 0:355018f44c9f 174 /** receive buffer - encoded data is stored here */
dirkx 0:355018f44c9f 175 u_char rxbuf[PPPOS_RX_BUFSIZE];
dirkx 0:355018f44c9f 176
dirkx 0:355018f44c9f 177 /* The input packet. */
dirkx 0:355018f44c9f 178 struct pbuf *inHead, *inTail;
dirkx 0:355018f44c9f 179
dirkx 0:355018f44c9f 180 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 181 u16_t inProtocol; /* The input protocol code. */
dirkx 0:355018f44c9f 182 u16_t inFCS; /* Input Frame Check Sequence value. */
dirkx 0:355018f44c9f 183 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 184 PPPDevStates inState; /* The input process state. */
dirkx 0:355018f44c9f 185 char inEscaped; /* Escape next character. */
dirkx 0:355018f44c9f 186 ext_accm inACCM; /* Async-Ctl-Char-Map for input. */
dirkx 0:355018f44c9f 187 } PPPControlRx;
dirkx 0:355018f44c9f 188
dirkx 0:355018f44c9f 189 /*
dirkx 0:355018f44c9f 190 * PPP interface control block.
dirkx 0:355018f44c9f 191 */
dirkx 0:355018f44c9f 192 typedef struct PPPControl_s {
dirkx 0:355018f44c9f 193 PPPControlRx rx;
dirkx 0:355018f44c9f 194 char openFlag; /* True when in use. */
dirkx 0:355018f44c9f 195 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 196 struct netif *ethif;
dirkx 0:355018f44c9f 197 struct pppoe_softc *pppoe_sc;
dirkx 0:355018f44c9f 198 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 199 int if_up; /* True when the interface is up. */
dirkx 0:355018f44c9f 200 int errCode; /* Code indicating why interface is down. */
dirkx 0:355018f44c9f 201 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 202 sio_fd_t fd; /* File device ID of port. */
dirkx 0:355018f44c9f 203 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 204 u16_t mtu; /* Peer's mru */
dirkx 0:355018f44c9f 205 int pcomp; /* Does peer accept protocol compression? */
dirkx 0:355018f44c9f 206 int accomp; /* Does peer accept addr/ctl compression? */
dirkx 0:355018f44c9f 207 u_long lastXMit; /* Time of last transmission. */
dirkx 0:355018f44c9f 208 ext_accm outACCM; /* Async-Ctl-Char-Map for output. */
dirkx 0:355018f44c9f 209 #if PPPOS_SUPPORT && VJ_SUPPORT
dirkx 0:355018f44c9f 210 int vjEnabled; /* Flag indicating VJ compression enabled. */
dirkx 0:355018f44c9f 211 struct vjcompress vjComp; /* Van Jacobson compression header. */
dirkx 0:355018f44c9f 212 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
dirkx 0:355018f44c9f 213
dirkx 0:355018f44c9f 214 struct netif netif;
dirkx 0:355018f44c9f 215
dirkx 0:355018f44c9f 216 struct ppp_addrs addrs;
dirkx 0:355018f44c9f 217
dirkx 0:355018f44c9f 218 void (*linkStatusCB)(void *ctx, int errCode, void *arg);
dirkx 0:355018f44c9f 219 void *linkStatusCtx;
dirkx 0:355018f44c9f 220
dirkx 0:355018f44c9f 221 } PPPControl;
dirkx 0:355018f44c9f 222
dirkx 0:355018f44c9f 223
dirkx 0:355018f44c9f 224 /*
dirkx 0:355018f44c9f 225 * Ioctl definitions.
dirkx 0:355018f44c9f 226 */
dirkx 0:355018f44c9f 227
dirkx 0:355018f44c9f 228 struct npioctl {
dirkx 0:355018f44c9f 229 int protocol; /* PPP procotol, e.g. PPP_IP */
dirkx 0:355018f44c9f 230 enum NPmode mode;
dirkx 0:355018f44c9f 231 };
dirkx 0:355018f44c9f 232
dirkx 0:355018f44c9f 233
dirkx 0:355018f44c9f 234
dirkx 0:355018f44c9f 235 /***********************************/
dirkx 0:355018f44c9f 236 /*** LOCAL FUNCTION DECLARATIONS ***/
dirkx 0:355018f44c9f 237 /***********************************/
dirkx 0:355018f44c9f 238 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 239 #if PPP_INPROC_OWNTHREAD
dirkx 0:355018f44c9f 240 static void pppInputThread(void *arg);
dirkx 0:355018f44c9f 241 #endif /* PPP_INPROC_OWNTHREAD */
dirkx 0:355018f44c9f 242 static void pppDrop(PPPControlRx *pcrx);
dirkx 0:355018f44c9f 243 static void pppInProc(PPPControlRx *pcrx, u_char *s, int l);
dirkx 0:355018f44c9f 244 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 245
dirkx 0:355018f44c9f 246
dirkx 0:355018f44c9f 247 /******************************/
dirkx 0:355018f44c9f 248 /*** PUBLIC DATA STRUCTURES ***/
dirkx 0:355018f44c9f 249 /******************************/
dirkx 0:355018f44c9f 250 u_long subnetMask;
dirkx 0:355018f44c9f 251
dirkx 0:355018f44c9f 252 static PPPControl pppControl[NUM_PPP] MEM_POSITION; /* The PPP interface control blocks. */
dirkx 0:355018f44c9f 253
dirkx 0:355018f44c9f 254 /*
dirkx 0:355018f44c9f 255 * PPP Data Link Layer "protocol" table.
dirkx 0:355018f44c9f 256 * One entry per supported protocol.
dirkx 0:355018f44c9f 257 * The last entry must be NULL.
dirkx 0:355018f44c9f 258 */
dirkx 0:355018f44c9f 259 struct protent *ppp_protocols[] = {
dirkx 0:355018f44c9f 260 &lcp_protent,
dirkx 0:355018f44c9f 261 #if PAP_SUPPORT
dirkx 0:355018f44c9f 262 &pap_protent,
dirkx 0:355018f44c9f 263 #endif /* PAP_SUPPORT */
dirkx 0:355018f44c9f 264 #if CHAP_SUPPORT
dirkx 0:355018f44c9f 265 &chap_protent,
dirkx 0:355018f44c9f 266 #endif /* CHAP_SUPPORT */
dirkx 0:355018f44c9f 267 #if CBCP_SUPPORT
dirkx 0:355018f44c9f 268 &cbcp_protent,
dirkx 0:355018f44c9f 269 #endif /* CBCP_SUPPORT */
dirkx 0:355018f44c9f 270 &ipcp_protent,
dirkx 0:355018f44c9f 271 #if CCP_SUPPORT
dirkx 0:355018f44c9f 272 &ccp_protent,
dirkx 0:355018f44c9f 273 #endif /* CCP_SUPPORT */
dirkx 0:355018f44c9f 274 NULL
dirkx 0:355018f44c9f 275 };
dirkx 0:355018f44c9f 276
dirkx 0:355018f44c9f 277
dirkx 0:355018f44c9f 278 /*
dirkx 0:355018f44c9f 279 * Buffers for outgoing packets. This must be accessed only from the appropriate
dirkx 0:355018f44c9f 280 * PPP task so that it doesn't need to be protected to avoid collisions.
dirkx 0:355018f44c9f 281 */
dirkx 0:355018f44c9f 282 u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN] MEM_POSITION;
dirkx 0:355018f44c9f 283
dirkx 0:355018f44c9f 284
dirkx 0:355018f44c9f 285 /*****************************/
dirkx 0:355018f44c9f 286 /*** LOCAL DATA STRUCTURES ***/
dirkx 0:355018f44c9f 287 /*****************************/
dirkx 0:355018f44c9f 288
dirkx 0:355018f44c9f 289 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 290 /*
dirkx 0:355018f44c9f 291 * FCS lookup table as calculated by genfcstab.
dirkx 0:355018f44c9f 292 * @todo: smaller, slower implementation for lower memory footprint?
dirkx 0:355018f44c9f 293 */
dirkx 0:355018f44c9f 294 static const u_short fcstab[256] = {
dirkx 0:355018f44c9f 295 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
dirkx 0:355018f44c9f 296 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
dirkx 0:355018f44c9f 297 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
dirkx 0:355018f44c9f 298 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
dirkx 0:355018f44c9f 299 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
dirkx 0:355018f44c9f 300 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
dirkx 0:355018f44c9f 301 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
dirkx 0:355018f44c9f 302 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
dirkx 0:355018f44c9f 303 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
dirkx 0:355018f44c9f 304 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
dirkx 0:355018f44c9f 305 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
dirkx 0:355018f44c9f 306 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
dirkx 0:355018f44c9f 307 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
dirkx 0:355018f44c9f 308 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
dirkx 0:355018f44c9f 309 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
dirkx 0:355018f44c9f 310 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
dirkx 0:355018f44c9f 311 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
dirkx 0:355018f44c9f 312 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
dirkx 0:355018f44c9f 313 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
dirkx 0:355018f44c9f 314 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
dirkx 0:355018f44c9f 315 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
dirkx 0:355018f44c9f 316 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
dirkx 0:355018f44c9f 317 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
dirkx 0:355018f44c9f 318 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
dirkx 0:355018f44c9f 319 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
dirkx 0:355018f44c9f 320 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
dirkx 0:355018f44c9f 321 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
dirkx 0:355018f44c9f 322 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
dirkx 0:355018f44c9f 323 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
dirkx 0:355018f44c9f 324 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
dirkx 0:355018f44c9f 325 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
dirkx 0:355018f44c9f 326 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
dirkx 0:355018f44c9f 327 };
dirkx 0:355018f44c9f 328
dirkx 0:355018f44c9f 329 /* PPP's Asynchronous-Control-Character-Map. The mask array is used
dirkx 0:355018f44c9f 330 * to select the specific bit for a character. */
dirkx 0:355018f44c9f 331 static u_char pppACCMMask[] = {
dirkx 0:355018f44c9f 332 0x01,
dirkx 0:355018f44c9f 333 0x02,
dirkx 0:355018f44c9f 334 0x04,
dirkx 0:355018f44c9f 335 0x08,
dirkx 0:355018f44c9f 336 0x10,
dirkx 0:355018f44c9f 337 0x20,
dirkx 0:355018f44c9f 338 0x40,
dirkx 0:355018f44c9f 339 0x80
dirkx 0:355018f44c9f 340 };
dirkx 0:355018f44c9f 341
dirkx 0:355018f44c9f 342 /** Wake up the task blocked in reading from serial line (if any) */
dirkx 0:355018f44c9f 343 static void
dirkx 0:355018f44c9f 344 pppRecvWakeup(int pd)
dirkx 0:355018f44c9f 345 {
dirkx 0:355018f44c9f 346 PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd));
dirkx 0:355018f44c9f 347 sio_read_abort(pppControl[pd].fd);
dirkx 0:355018f44c9f 348 }
dirkx 0:355018f44c9f 349 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 350
dirkx 0:355018f44c9f 351 void
dirkx 0:355018f44c9f 352 pppLinkTerminated(int pd)
dirkx 0:355018f44c9f 353 {
dirkx 0:355018f44c9f 354 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd));
dirkx 0:355018f44c9f 355
dirkx 0:355018f44c9f 356 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 357 if (pppControl[pd].ethif) {
dirkx 0:355018f44c9f 358 pppoe_disconnect(pppControl[pd].pppoe_sc);
dirkx 0:355018f44c9f 359 } else
dirkx 0:355018f44c9f 360 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 361 {
dirkx 0:355018f44c9f 362 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 363 PPPControl* pc;
dirkx 0:355018f44c9f 364 pppRecvWakeup(pd);
dirkx 0:355018f44c9f 365 pc = &pppControl[pd];
dirkx 0:355018f44c9f 366 pppDrop(&pc->rx); /* bug fix #17726 */
dirkx 0:355018f44c9f 367
dirkx 0:355018f44c9f 368 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
dirkx 0:355018f44c9f 369 if (pc->linkStatusCB) {
dirkx 0:355018f44c9f 370 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
dirkx 0:355018f44c9f 371 }
dirkx 0:355018f44c9f 372
dirkx 0:355018f44c9f 373 pc->openFlag = 0;/**/
dirkx 0:355018f44c9f 374 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 375 }
dirkx 0:355018f44c9f 376 PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n"));
dirkx 0:355018f44c9f 377 }
dirkx 0:355018f44c9f 378
dirkx 0:355018f44c9f 379 void
dirkx 0:355018f44c9f 380 pppLinkDown(int pd)
dirkx 0:355018f44c9f 381 {
dirkx 0:355018f44c9f 382 PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd));
dirkx 0:355018f44c9f 383
dirkx 0:355018f44c9f 384 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 385 if (pppControl[pd].ethif) {
dirkx 0:355018f44c9f 386 pppoe_disconnect(pppControl[pd].pppoe_sc);
dirkx 0:355018f44c9f 387 } else
dirkx 0:355018f44c9f 388 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 389 {
dirkx 0:355018f44c9f 390 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 391 pppRecvWakeup(pd);
dirkx 0:355018f44c9f 392 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 393 }
dirkx 0:355018f44c9f 394 }
dirkx 0:355018f44c9f 395
dirkx 0:355018f44c9f 396 /** Initiate LCP open request */
dirkx 0:355018f44c9f 397 static void
dirkx 0:355018f44c9f 398 pppStart(int pd)
dirkx 0:355018f44c9f 399 {
dirkx 0:355018f44c9f 400 PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd));
dirkx 0:355018f44c9f 401 lcp_lowerup(pd);
dirkx 0:355018f44c9f 402 lcp_open(pd); /* Start protocol */
dirkx 0:355018f44c9f 403 PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n"));
dirkx 0:355018f44c9f 404 }
dirkx 0:355018f44c9f 405
dirkx 0:355018f44c9f 406 /** LCP close request */
dirkx 0:355018f44c9f 407 static void
dirkx 0:355018f44c9f 408 pppStop(int pd)
dirkx 0:355018f44c9f 409 {
dirkx 0:355018f44c9f 410 PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd));
dirkx 0:355018f44c9f 411 lcp_close(pd, "User request");
dirkx 0:355018f44c9f 412 }
dirkx 0:355018f44c9f 413
dirkx 0:355018f44c9f 414 /** Called when carrier/link is lost */
dirkx 0:355018f44c9f 415 static void
dirkx 0:355018f44c9f 416 pppHup(int pd)
dirkx 0:355018f44c9f 417 {
dirkx 0:355018f44c9f 418 PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd));
dirkx 0:355018f44c9f 419 lcp_lowerdown(pd);
dirkx 0:355018f44c9f 420 link_terminated(pd);
dirkx 0:355018f44c9f 421 }
dirkx 0:355018f44c9f 422
dirkx 0:355018f44c9f 423 /***********************************/
dirkx 0:355018f44c9f 424 /*** PUBLIC FUNCTION DEFINITIONS ***/
dirkx 0:355018f44c9f 425 /***********************************/
dirkx 0:355018f44c9f 426 /* Initialize the PPP subsystem. */
dirkx 0:355018f44c9f 427
dirkx 0:355018f44c9f 428 struct ppp_settings ppp_settings;
dirkx 0:355018f44c9f 429
dirkx 0:355018f44c9f 430 void
dirkx 0:355018f44c9f 431 pppInit(void)
dirkx 0:355018f44c9f 432 {
dirkx 0:355018f44c9f 433 struct protent *protp;
dirkx 0:355018f44c9f 434 int i, j;
dirkx 0:355018f44c9f 435
dirkx 0:355018f44c9f 436 memset(&ppp_settings, 0, sizeof(ppp_settings));
dirkx 0:355018f44c9f 437 ppp_settings.usepeerdns = 1;
dirkx 0:355018f44c9f 438 pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
dirkx 0:355018f44c9f 439
dirkx 0:355018f44c9f 440 magicInit();
dirkx 0:355018f44c9f 441
dirkx 0:355018f44c9f 442 subnetMask = htonl(0xffffff00);
dirkx 0:355018f44c9f 443
dirkx 0:355018f44c9f 444 for (i = 0; i < NUM_PPP; i++) {
dirkx 0:355018f44c9f 445 /* Initialize each protocol to the standard option set. */
dirkx 0:355018f44c9f 446 for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) {
dirkx 0:355018f44c9f 447 (*protp->init)(i);
dirkx 0:355018f44c9f 448 }
dirkx 0:355018f44c9f 449 }
dirkx 0:355018f44c9f 450
dirkx 0:355018f44c9f 451 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 452 pppoe_init();
dirkx 0:355018f44c9f 453 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 454 }
dirkx 0:355018f44c9f 455
dirkx 0:355018f44c9f 456 void
dirkx 0:355018f44c9f 457 pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
dirkx 0:355018f44c9f 458 {
dirkx 0:355018f44c9f 459 switch(authType) {
dirkx 0:355018f44c9f 460 case PPPAUTHTYPE_NONE:
dirkx 0:355018f44c9f 461 default:
dirkx 0:355018f44c9f 462 #ifdef LWIP_PPP_STRICT_PAP_REJECT
dirkx 0:355018f44c9f 463 ppp_settings.refuse_pap = 1;
dirkx 0:355018f44c9f 464 #else /* LWIP_PPP_STRICT_PAP_REJECT */
dirkx 0:355018f44c9f 465 /* some providers request pap and accept an empty login/pw */
dirkx 0:355018f44c9f 466 ppp_settings.refuse_pap = 0;
dirkx 0:355018f44c9f 467 #endif /* LWIP_PPP_STRICT_PAP_REJECT */
dirkx 0:355018f44c9f 468 ppp_settings.refuse_chap = 1;
dirkx 0:355018f44c9f 469 break;
dirkx 0:355018f44c9f 470
dirkx 0:355018f44c9f 471 case PPPAUTHTYPE_ANY:
dirkx 0:355018f44c9f 472 /* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
dirkx 0:355018f44c9f 473 * RFC 1994 says:
dirkx 0:355018f44c9f 474 *
dirkx 0:355018f44c9f 475 * In practice, within or associated with each PPP server, there is a
dirkx 0:355018f44c9f 476 * database which associates "user" names with authentication
dirkx 0:355018f44c9f 477 * information ("secrets"). It is not anticipated that a particular
dirkx 0:355018f44c9f 478 * named user would be authenticated by multiple methods. This would
dirkx 0:355018f44c9f 479 * make the user vulnerable to attacks which negotiate the least secure
dirkx 0:355018f44c9f 480 * method from among a set (such as PAP rather than CHAP). If the same
dirkx 0:355018f44c9f 481 * secret was used, PAP would reveal the secret to be used later with
dirkx 0:355018f44c9f 482 * CHAP.
dirkx 0:355018f44c9f 483 *
dirkx 0:355018f44c9f 484 * Instead, for each user name there should be an indication of exactly
dirkx 0:355018f44c9f 485 * one method used to authenticate that user name. If a user needs to
dirkx 0:355018f44c9f 486 * make use of different authentication methods under different
dirkx 0:355018f44c9f 487 * circumstances, then distinct user names SHOULD be employed, each of
dirkx 0:355018f44c9f 488 * which identifies exactly one authentication method.
dirkx 0:355018f44c9f 489 *
dirkx 0:355018f44c9f 490 */
dirkx 0:355018f44c9f 491 ppp_settings.refuse_pap = 0;
dirkx 0:355018f44c9f 492 ppp_settings.refuse_chap = 0;
dirkx 0:355018f44c9f 493 break;
dirkx 0:355018f44c9f 494
dirkx 0:355018f44c9f 495 case PPPAUTHTYPE_PAP:
dirkx 0:355018f44c9f 496 ppp_settings.refuse_pap = 0;
dirkx 0:355018f44c9f 497 ppp_settings.refuse_chap = 1;
dirkx 0:355018f44c9f 498 break;
dirkx 0:355018f44c9f 499
dirkx 0:355018f44c9f 500 case PPPAUTHTYPE_CHAP:
dirkx 0:355018f44c9f 501 ppp_settings.refuse_pap = 1;
dirkx 0:355018f44c9f 502 ppp_settings.refuse_chap = 0;
dirkx 0:355018f44c9f 503 break;
dirkx 0:355018f44c9f 504 }
dirkx 0:355018f44c9f 505
dirkx 0:355018f44c9f 506 if(user) {
dirkx 0:355018f44c9f 507 strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
dirkx 0:355018f44c9f 508 ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
dirkx 0:355018f44c9f 509 } else {
dirkx 0:355018f44c9f 510 ppp_settings.user[0] = '\0';
dirkx 0:355018f44c9f 511 }
dirkx 0:355018f44c9f 512
dirkx 0:355018f44c9f 513 if(passwd) {
dirkx 0:355018f44c9f 514 strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
dirkx 0:355018f44c9f 515 ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
dirkx 0:355018f44c9f 516 } else {
dirkx 0:355018f44c9f 517 ppp_settings.passwd[0] = '\0';
dirkx 0:355018f44c9f 518 }
dirkx 0:355018f44c9f 519 }
dirkx 0:355018f44c9f 520
dirkx 0:355018f44c9f 521 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 522 /** Open a new PPP connection using the given I/O device.
dirkx 0:355018f44c9f 523 * This initializes the PPP control block but does not
dirkx 0:355018f44c9f 524 * attempt to negotiate the LCP session. If this port
dirkx 0:355018f44c9f 525 * connects to a modem, the modem connection must be
dirkx 0:355018f44c9f 526 * established before calling this.
dirkx 0:355018f44c9f 527 * Return a new PPP connection descriptor on success or
dirkx 0:355018f44c9f 528 * an error code (negative) on failure.
dirkx 0:355018f44c9f 529 *
dirkx 0:355018f44c9f 530 * pppOpen() is directly defined to this function.
dirkx 0:355018f44c9f 531 */
dirkx 0:355018f44c9f 532 int
dirkx 0:355018f44c9f 533 pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
dirkx 0:355018f44c9f 534 {
dirkx 0:355018f44c9f 535 PPPControl *pc;
dirkx 0:355018f44c9f 536 int pd;
dirkx 0:355018f44c9f 537
dirkx 0:355018f44c9f 538 if (linkStatusCB == NULL) {
dirkx 0:355018f44c9f 539 /* PPP is single-threaded: without a callback,
dirkx 0:355018f44c9f 540 * there is no way to know when the link is up. */
dirkx 0:355018f44c9f 541 return PPPERR_PARAM;
dirkx 0:355018f44c9f 542 }
dirkx 0:355018f44c9f 543
dirkx 0:355018f44c9f 544 /* Find a free PPP session descriptor. */
dirkx 0:355018f44c9f 545 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
dirkx 0:355018f44c9f 546
dirkx 0:355018f44c9f 547 if (pd >= NUM_PPP) {
dirkx 0:355018f44c9f 548 pd = PPPERR_OPEN;
dirkx 0:355018f44c9f 549 } else {
dirkx 0:355018f44c9f 550 pc = &pppControl[pd];
dirkx 0:355018f44c9f 551 /* @todo: is this correct or do I overwrite something? */
dirkx 0:355018f44c9f 552 memset(pc, 0, sizeof(PPPControl));
dirkx 0:355018f44c9f 553 pc->rx.pd = pd;
dirkx 0:355018f44c9f 554 pc->rx.fd = fd;
dirkx 0:355018f44c9f 555
dirkx 0:355018f44c9f 556 pc->openFlag = 1;
dirkx 0:355018f44c9f 557 pc->fd = fd;
dirkx 0:355018f44c9f 558
dirkx 0:355018f44c9f 559 #if VJ_SUPPORT
dirkx 0:355018f44c9f 560 vj_compress_init(&pc->vjComp);
dirkx 0:355018f44c9f 561 #endif /* VJ_SUPPORT */
dirkx 0:355018f44c9f 562
dirkx 0:355018f44c9f 563 /*
dirkx 0:355018f44c9f 564 * Default the in and out accm so that escape and flag characters
dirkx 0:355018f44c9f 565 * are always escaped.
dirkx 0:355018f44c9f 566 */
dirkx 0:355018f44c9f 567 pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */
dirkx 0:355018f44c9f 568 pc->outACCM[15] = 0x60;
dirkx 0:355018f44c9f 569
dirkx 0:355018f44c9f 570 pc->linkStatusCB = linkStatusCB;
dirkx 0:355018f44c9f 571 pc->linkStatusCtx = linkStatusCtx;
dirkx 0:355018f44c9f 572
dirkx 0:355018f44c9f 573 /*
dirkx 0:355018f44c9f 574 * Start the connection and handle incoming events (packet or timeout).
dirkx 0:355018f44c9f 575 */
dirkx 0:355018f44c9f 576 PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd));
dirkx 0:355018f44c9f 577 pppStart(pd);
dirkx 0:355018f44c9f 578 #if PPP_INPROC_OWNTHREAD
dirkx 0:355018f44c9f 579 sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
dirkx 0:355018f44c9f 580 #endif
dirkx 0:355018f44c9f 581 }
dirkx 0:355018f44c9f 582
dirkx 0:355018f44c9f 583 return pd;
dirkx 0:355018f44c9f 584 }
dirkx 0:355018f44c9f 585 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 586
dirkx 0:355018f44c9f 587 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 588 static void pppOverEthernetLinkStatusCB(int pd, int up);
dirkx 0:355018f44c9f 589
dirkx 0:355018f44c9f 590 void
dirkx 0:355018f44c9f 591 pppOverEthernetClose(int pd)
dirkx 0:355018f44c9f 592 {
dirkx 0:355018f44c9f 593 PPPControl* pc = &pppControl[pd];
dirkx 0:355018f44c9f 594
dirkx 0:355018f44c9f 595 /* *TJL* There's no lcp_deinit */
dirkx 0:355018f44c9f 596 lcp_close(pd, NULL);
dirkx 0:355018f44c9f 597
dirkx 0:355018f44c9f 598 pppoe_destroy(&pc->netif);
dirkx 0:355018f44c9f 599 }
dirkx 0:355018f44c9f 600
dirkx 0:355018f44c9f 601 int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
dirkx 0:355018f44c9f 602 {
dirkx 0:355018f44c9f 603 PPPControl *pc;
dirkx 0:355018f44c9f 604 int pd;
dirkx 0:355018f44c9f 605
dirkx 0:355018f44c9f 606 LWIP_UNUSED_ARG(service_name);
dirkx 0:355018f44c9f 607 LWIP_UNUSED_ARG(concentrator_name);
dirkx 0:355018f44c9f 608
dirkx 0:355018f44c9f 609 if (linkStatusCB == NULL) {
dirkx 0:355018f44c9f 610 /* PPP is single-threaded: without a callback,
dirkx 0:355018f44c9f 611 * there is no way to know when the link is up. */
dirkx 0:355018f44c9f 612 return PPPERR_PARAM;
dirkx 0:355018f44c9f 613 }
dirkx 0:355018f44c9f 614
dirkx 0:355018f44c9f 615 /* Find a free PPP session descriptor. Critical region? */
dirkx 0:355018f44c9f 616 for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
dirkx 0:355018f44c9f 617 if (pd >= NUM_PPP) {
dirkx 0:355018f44c9f 618 pd = PPPERR_OPEN;
dirkx 0:355018f44c9f 619 } else {
dirkx 0:355018f44c9f 620 pc = &pppControl[pd];
dirkx 0:355018f44c9f 621 memset(pc, 0, sizeof(PPPControl));
dirkx 0:355018f44c9f 622 pc->openFlag = 1;
dirkx 0:355018f44c9f 623 pc->ethif = ethif;
dirkx 0:355018f44c9f 624
dirkx 0:355018f44c9f 625 pc->linkStatusCB = linkStatusCB;
dirkx 0:355018f44c9f 626 pc->linkStatusCtx = linkStatusCtx;
dirkx 0:355018f44c9f 627
dirkx 0:355018f44c9f 628 lcp_wantoptions[pd].mru = PPPOE_MAXMTU;
dirkx 0:355018f44c9f 629 lcp_wantoptions[pd].neg_asyncmap = 0;
dirkx 0:355018f44c9f 630 lcp_wantoptions[pd].neg_pcompression = 0;
dirkx 0:355018f44c9f 631 lcp_wantoptions[pd].neg_accompression = 0;
dirkx 0:355018f44c9f 632
dirkx 0:355018f44c9f 633 lcp_allowoptions[pd].mru = PPPOE_MAXMTU;
dirkx 0:355018f44c9f 634 lcp_allowoptions[pd].neg_asyncmap = 0;
dirkx 0:355018f44c9f 635 lcp_allowoptions[pd].neg_pcompression = 0;
dirkx 0:355018f44c9f 636 lcp_allowoptions[pd].neg_accompression = 0;
dirkx 0:355018f44c9f 637
dirkx 0:355018f44c9f 638 if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
dirkx 0:355018f44c9f 639 pc->openFlag = 0;
dirkx 0:355018f44c9f 640 return PPPERR_OPEN;
dirkx 0:355018f44c9f 641 }
dirkx 0:355018f44c9f 642
dirkx 0:355018f44c9f 643 pppoe_connect(pc->pppoe_sc);
dirkx 0:355018f44c9f 644 }
dirkx 0:355018f44c9f 645
dirkx 0:355018f44c9f 646 return pd;
dirkx 0:355018f44c9f 647 }
dirkx 0:355018f44c9f 648 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 649
dirkx 0:355018f44c9f 650
dirkx 0:355018f44c9f 651 /* Close a PPP connection and release the descriptor.
dirkx 0:355018f44c9f 652 * Any outstanding packets in the queues are dropped.
dirkx 0:355018f44c9f 653 * Return 0 on success, an error code on failure. */
dirkx 0:355018f44c9f 654 int
dirkx 0:355018f44c9f 655 pppClose(int pd)
dirkx 0:355018f44c9f 656 {
dirkx 0:355018f44c9f 657 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 658 int st = 0;
dirkx 0:355018f44c9f 659
dirkx 0:355018f44c9f 660 PPPDEBUG(LOG_DEBUG, ("pppClose() called\n"));
dirkx 0:355018f44c9f 661
dirkx 0:355018f44c9f 662 /* Disconnect */
dirkx 0:355018f44c9f 663 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 664 if(pc->ethif) {
dirkx 0:355018f44c9f 665 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
dirkx 0:355018f44c9f 666 pc->errCode = PPPERR_USER;
dirkx 0:355018f44c9f 667 /* This will leave us at PHASE_DEAD. */
dirkx 0:355018f44c9f 668 pppStop(pd);
dirkx 0:355018f44c9f 669 } else
dirkx 0:355018f44c9f 670 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 671 {
dirkx 0:355018f44c9f 672 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 673 PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd));
dirkx 0:355018f44c9f 674 pc->errCode = PPPERR_USER;
dirkx 0:355018f44c9f 675 /* This will leave us at PHASE_DEAD. */
dirkx 0:355018f44c9f 676 pppStop(pd);
dirkx 0:355018f44c9f 677 pppRecvWakeup(pd);
dirkx 0:355018f44c9f 678 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 679 }
dirkx 0:355018f44c9f 680
dirkx 0:355018f44c9f 681 return st;
dirkx 0:355018f44c9f 682 }
dirkx 0:355018f44c9f 683
dirkx 0:355018f44c9f 684 /* This function is called when carrier is lost on the PPP channel. */
dirkx 0:355018f44c9f 685 void
dirkx 0:355018f44c9f 686 pppSigHUP(int pd)
dirkx 0:355018f44c9f 687 {
dirkx 0:355018f44c9f 688 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 689 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 690 if(pc->ethif) {
dirkx 0:355018f44c9f 691 PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
dirkx 0:355018f44c9f 692 pppHup(pd);
dirkx 0:355018f44c9f 693 } else
dirkx 0:355018f44c9f 694 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 695 {
dirkx 0:355018f44c9f 696 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 697 PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
dirkx 0:355018f44c9f 698 pppHup(pd);
dirkx 0:355018f44c9f 699 pppRecvWakeup(pd);
dirkx 0:355018f44c9f 700 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 701 }
dirkx 0:355018f44c9f 702 }
dirkx 0:355018f44c9f 703
dirkx 0:355018f44c9f 704 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 705 static void
dirkx 0:355018f44c9f 706 nPut(PPPControl *pc, struct pbuf *nb)
dirkx 0:355018f44c9f 707 {
dirkx 0:355018f44c9f 708 struct pbuf *b;
dirkx 0:355018f44c9f 709 int c = 0;
dirkx 0:355018f44c9f 710
dirkx 0:355018f44c9f 711 for(b = nb; b != NULL; b = b->next) {
dirkx 0:355018f44c9f 712 if((c = sio_write(pc->fd, (u8_t*)b->payload, b->len)) != b->len) {
dirkx 0:355018f44c9f 713 PPPDEBUG(LOG_WARNING,
dirkx 0:355018f44c9f 714 ("PPP nPut: incomplete sio_write(fd:%d, len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c));
dirkx 0:355018f44c9f 715 LINK_STATS_INC(link.err);
dirkx 0:355018f44c9f 716 pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
dirkx 0:355018f44c9f 717 snmp_inc_ifoutdiscards(&pc->netif);
dirkx 0:355018f44c9f 718 pbuf_free(nb);
dirkx 0:355018f44c9f 719 return;
dirkx 0:355018f44c9f 720 }
dirkx 0:355018f44c9f 721 }
dirkx 0:355018f44c9f 722
dirkx 0:355018f44c9f 723 snmp_add_ifoutoctets(&pc->netif, nb->tot_len);
dirkx 0:355018f44c9f 724 snmp_inc_ifoutucastpkts(&pc->netif);
dirkx 0:355018f44c9f 725 pbuf_free(nb);
dirkx 0:355018f44c9f 726 LINK_STATS_INC(link.xmit);
dirkx 0:355018f44c9f 727 }
dirkx 0:355018f44c9f 728
dirkx 0:355018f44c9f 729 /*
dirkx 0:355018f44c9f 730 * pppAppend - append given character to end of given pbuf. If outACCM
dirkx 0:355018f44c9f 731 * is not NULL and the character needs to be escaped, do so.
dirkx 0:355018f44c9f 732 * If pbuf is full, append another.
dirkx 0:355018f44c9f 733 * Return the current pbuf.
dirkx 0:355018f44c9f 734 */
dirkx 0:355018f44c9f 735 static struct pbuf *
dirkx 0:355018f44c9f 736 pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
dirkx 0:355018f44c9f 737 {
dirkx 0:355018f44c9f 738 struct pbuf *tb = nb;
dirkx 0:355018f44c9f 739
dirkx 0:355018f44c9f 740 /* Make sure there is room for the character and an escape code.
dirkx 0:355018f44c9f 741 * Sure we don't quite fill the buffer if the character doesn't
dirkx 0:355018f44c9f 742 * get escaped but is one character worth complicating this? */
dirkx 0:355018f44c9f 743 /* Note: We assume no packet header. */
dirkx 0:355018f44c9f 744 if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
dirkx 0:355018f44c9f 745 tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
dirkx 0:355018f44c9f 746 if (tb) {
dirkx 0:355018f44c9f 747 nb->next = tb;
dirkx 0:355018f44c9f 748 } else {
dirkx 0:355018f44c9f 749 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 750 }
dirkx 0:355018f44c9f 751 nb = tb;
dirkx 0:355018f44c9f 752 }
dirkx 0:355018f44c9f 753
dirkx 0:355018f44c9f 754 if (nb) {
dirkx 0:355018f44c9f 755 if (outACCM && ESCAPE_P(*outACCM, c)) {
dirkx 0:355018f44c9f 756 *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
dirkx 0:355018f44c9f 757 *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
dirkx 0:355018f44c9f 758 } else {
dirkx 0:355018f44c9f 759 *((u_char*)nb->payload + nb->len++) = c;
dirkx 0:355018f44c9f 760 }
dirkx 0:355018f44c9f 761 }
dirkx 0:355018f44c9f 762
dirkx 0:355018f44c9f 763 return tb;
dirkx 0:355018f44c9f 764 }
dirkx 0:355018f44c9f 765 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 766
dirkx 0:355018f44c9f 767 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 768 static err_t
dirkx 0:355018f44c9f 769 pppnetifOutputOverEthernet(int pd, struct pbuf *p)
dirkx 0:355018f44c9f 770 {
dirkx 0:355018f44c9f 771 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 772 struct pbuf *pb;
dirkx 0:355018f44c9f 773 u_short protocol = PPP_IP;
dirkx 0:355018f44c9f 774 int i=0;
dirkx 0:355018f44c9f 775 u16_t tot_len;
dirkx 0:355018f44c9f 776
dirkx 0:355018f44c9f 777 /* @todo: try to use pbuf_header() here! */
dirkx 0:355018f44c9f 778 pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM);
dirkx 0:355018f44c9f 779 if(!pb) {
dirkx 0:355018f44c9f 780 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 781 LINK_STATS_INC(link.proterr);
dirkx 0:355018f44c9f 782 snmp_inc_ifoutdiscards(&pc->netif);
dirkx 0:355018f44c9f 783 return ERR_MEM;
dirkx 0:355018f44c9f 784 }
dirkx 0:355018f44c9f 785
dirkx 0:355018f44c9f 786 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
dirkx 0:355018f44c9f 787
dirkx 0:355018f44c9f 788 pc->lastXMit = sys_jiffies();
dirkx 0:355018f44c9f 789
dirkx 0:355018f44c9f 790 if (!pc->pcomp || protocol > 0xFF) {
dirkx 0:355018f44c9f 791 *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF;
dirkx 0:355018f44c9f 792 }
dirkx 0:355018f44c9f 793 *((u_char*)pb->payload + i) = protocol & 0xFF;
dirkx 0:355018f44c9f 794
dirkx 0:355018f44c9f 795 pbuf_chain(pb, p);
dirkx 0:355018f44c9f 796 tot_len = pb->tot_len;
dirkx 0:355018f44c9f 797
dirkx 0:355018f44c9f 798 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
dirkx 0:355018f44c9f 799 LINK_STATS_INC(link.err);
dirkx 0:355018f44c9f 800 snmp_inc_ifoutdiscards(&pc->netif);
dirkx 0:355018f44c9f 801 return PPPERR_DEVICE;
dirkx 0:355018f44c9f 802 }
dirkx 0:355018f44c9f 803
dirkx 0:355018f44c9f 804 snmp_add_ifoutoctets(&pc->netif, tot_len);
dirkx 0:355018f44c9f 805 snmp_inc_ifoutucastpkts(&pc->netif);
dirkx 0:355018f44c9f 806 LINK_STATS_INC(link.xmit);
dirkx 0:355018f44c9f 807 return ERR_OK;
dirkx 0:355018f44c9f 808 }
dirkx 0:355018f44c9f 809 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 810
dirkx 0:355018f44c9f 811 /* Send a packet on the given connection. */
dirkx 0:355018f44c9f 812 static err_t
dirkx 0:355018f44c9f 813 pppnetifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr)
dirkx 0:355018f44c9f 814 {
dirkx 0:355018f44c9f 815 int pd = (int)(size_t)netif->state;
dirkx 0:355018f44c9f 816 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 817 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 818 u_short protocol = PPP_IP;
dirkx 0:355018f44c9f 819 u_int fcsOut = PPP_INITFCS;
dirkx 0:355018f44c9f 820 struct pbuf *headMB = NULL, *tailMB = NULL, *p;
dirkx 0:355018f44c9f 821 u_char c;
dirkx 0:355018f44c9f 822 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 823
dirkx 0:355018f44c9f 824 LWIP_UNUSED_ARG(ipaddr);
dirkx 0:355018f44c9f 825
dirkx 0:355018f44c9f 826 /* Validate parameters. */
dirkx 0:355018f44c9f 827 /* We let any protocol value go through - it can't hurt us
dirkx 0:355018f44c9f 828 * and the peer will just drop it if it's not accepting it. */
dirkx 0:355018f44c9f 829 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
dirkx 0:355018f44c9f 830 PPPDEBUG(LOG_WARNING, ("pppnetifOutput[%d]: bad parms prot=%d pb=%p\n",
dirkx 0:355018f44c9f 831 pd, PPP_IP, pb));
dirkx 0:355018f44c9f 832 LINK_STATS_INC(link.opterr);
dirkx 0:355018f44c9f 833 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 834 snmp_inc_ifoutdiscards(netif);
dirkx 0:355018f44c9f 835 return ERR_ARG;
dirkx 0:355018f44c9f 836 }
dirkx 0:355018f44c9f 837
dirkx 0:355018f44c9f 838 /* Check that the link is up. */
dirkx 0:355018f44c9f 839 if (lcp_phase[pd] == PHASE_DEAD) {
dirkx 0:355018f44c9f 840 PPPDEBUG(LOG_ERR, ("pppnetifOutput[%d]: link not up\n", pd));
dirkx 0:355018f44c9f 841 LINK_STATS_INC(link.rterr);
dirkx 0:355018f44c9f 842 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 843 snmp_inc_ifoutdiscards(netif);
dirkx 0:355018f44c9f 844 return ERR_RTE;
dirkx 0:355018f44c9f 845 }
dirkx 0:355018f44c9f 846
dirkx 0:355018f44c9f 847 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 848 if(pc->ethif) {
dirkx 0:355018f44c9f 849 return pppnetifOutputOverEthernet(pd, pb);
dirkx 0:355018f44c9f 850 }
dirkx 0:355018f44c9f 851 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 852
dirkx 0:355018f44c9f 853 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 854 /* Grab an output buffer. */
dirkx 0:355018f44c9f 855 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
dirkx 0:355018f44c9f 856 if (headMB == NULL) {
dirkx 0:355018f44c9f 857 PPPDEBUG(LOG_WARNING, ("pppnetifOutput[%d]: first alloc fail\n", pd));
dirkx 0:355018f44c9f 858 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 859 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 860 snmp_inc_ifoutdiscards(netif);
dirkx 0:355018f44c9f 861 return ERR_MEM;
dirkx 0:355018f44c9f 862 }
dirkx 0:355018f44c9f 863
dirkx 0:355018f44c9f 864 #if VJ_SUPPORT
dirkx 0:355018f44c9f 865 /*
dirkx 0:355018f44c9f 866 * Attempt Van Jacobson header compression if VJ is configured and
dirkx 0:355018f44c9f 867 * this is an IP packet.
dirkx 0:355018f44c9f 868 */
dirkx 0:355018f44c9f 869 if (protocol == PPP_IP && pc->vjEnabled) {
dirkx 0:355018f44c9f 870 switch (vj_compress_tcp(&pc->vjComp, pb)) {
dirkx 0:355018f44c9f 871 case TYPE_IP:
dirkx 0:355018f44c9f 872 /* No change...
dirkx 0:355018f44c9f 873 protocol = PPP_IP_PROTOCOL; */
dirkx 0:355018f44c9f 874 break;
dirkx 0:355018f44c9f 875 case TYPE_COMPRESSED_TCP:
dirkx 0:355018f44c9f 876 protocol = PPP_VJC_COMP;
dirkx 0:355018f44c9f 877 break;
dirkx 0:355018f44c9f 878 case TYPE_UNCOMPRESSED_TCP:
dirkx 0:355018f44c9f 879 protocol = PPP_VJC_UNCOMP;
dirkx 0:355018f44c9f 880 break;
dirkx 0:355018f44c9f 881 default:
dirkx 0:355018f44c9f 882 PPPDEBUG(LOG_WARNING, ("pppnetifOutput[%d]: bad IP packet\n", pd));
dirkx 0:355018f44c9f 883 LINK_STATS_INC(link.proterr);
dirkx 0:355018f44c9f 884 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 885 snmp_inc_ifoutdiscards(netif);
dirkx 0:355018f44c9f 886 pbuf_free(headMB);
dirkx 0:355018f44c9f 887 return ERR_VAL;
dirkx 0:355018f44c9f 888 }
dirkx 0:355018f44c9f 889 }
dirkx 0:355018f44c9f 890 #endif /* VJ_SUPPORT */
dirkx 0:355018f44c9f 891
dirkx 0:355018f44c9f 892 tailMB = headMB;
dirkx 0:355018f44c9f 893
dirkx 0:355018f44c9f 894 /* Build the PPP header. */
dirkx 0:355018f44c9f 895 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
dirkx 0:355018f44c9f 896 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
dirkx 0:355018f44c9f 897 }
dirkx 0:355018f44c9f 898
dirkx 0:355018f44c9f 899 pc->lastXMit = sys_jiffies();
dirkx 0:355018f44c9f 900 if (!pc->accomp) {
dirkx 0:355018f44c9f 901 fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
dirkx 0:355018f44c9f 902 tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 903 fcsOut = PPP_FCS(fcsOut, PPP_UI);
dirkx 0:355018f44c9f 904 tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 905 }
dirkx 0:355018f44c9f 906 if (!pc->pcomp || protocol > 0xFF) {
dirkx 0:355018f44c9f 907 c = (protocol >> 8) & 0xFF;
dirkx 0:355018f44c9f 908 fcsOut = PPP_FCS(fcsOut, c);
dirkx 0:355018f44c9f 909 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 910 }
dirkx 0:355018f44c9f 911 c = protocol & 0xFF;
dirkx 0:355018f44c9f 912 fcsOut = PPP_FCS(fcsOut, c);
dirkx 0:355018f44c9f 913 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 914
dirkx 0:355018f44c9f 915 /* Load packet. */
dirkx 0:355018f44c9f 916 for(p = pb; p; p = p->next) {
dirkx 0:355018f44c9f 917 int n;
dirkx 0:355018f44c9f 918 u_char *sPtr;
dirkx 0:355018f44c9f 919
dirkx 0:355018f44c9f 920 sPtr = (u_char*)p->payload;
dirkx 0:355018f44c9f 921 n = p->len;
dirkx 0:355018f44c9f 922 while (n-- > 0) {
dirkx 0:355018f44c9f 923 c = *sPtr++;
dirkx 0:355018f44c9f 924
dirkx 0:355018f44c9f 925 /* Update FCS before checking for special characters. */
dirkx 0:355018f44c9f 926 fcsOut = PPP_FCS(fcsOut, c);
dirkx 0:355018f44c9f 927
dirkx 0:355018f44c9f 928 /* Copy to output buffer escaping special characters. */
dirkx 0:355018f44c9f 929 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 930 }
dirkx 0:355018f44c9f 931 }
dirkx 0:355018f44c9f 932
dirkx 0:355018f44c9f 933 /* Add FCS and trailing flag. */
dirkx 0:355018f44c9f 934 c = ~fcsOut & 0xFF;
dirkx 0:355018f44c9f 935 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 936 c = (~fcsOut >> 8) & 0xFF;
dirkx 0:355018f44c9f 937 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 938 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
dirkx 0:355018f44c9f 939
dirkx 0:355018f44c9f 940 /* If we failed to complete the packet, throw it away. */
dirkx 0:355018f44c9f 941 if (!tailMB) {
dirkx 0:355018f44c9f 942 PPPDEBUG(LOG_WARNING,
dirkx 0:355018f44c9f 943 ("pppnetifOutput[%d]: Alloc err - dropping proto=%d\n",
dirkx 0:355018f44c9f 944 pd, protocol));
dirkx 0:355018f44c9f 945 pbuf_free(headMB);
dirkx 0:355018f44c9f 946 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 947 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 948 snmp_inc_ifoutdiscards(netif);
dirkx 0:355018f44c9f 949 return ERR_MEM;
dirkx 0:355018f44c9f 950 }
dirkx 0:355018f44c9f 951
dirkx 0:355018f44c9f 952 /* Send it. */
dirkx 0:355018f44c9f 953 PPPDEBUG(LOG_INFO, ("pppnetifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol));
dirkx 0:355018f44c9f 954
dirkx 0:355018f44c9f 955 nPut(pc, headMB);
dirkx 0:355018f44c9f 956 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 957
dirkx 0:355018f44c9f 958 return ERR_OK;
dirkx 0:355018f44c9f 959 }
dirkx 0:355018f44c9f 960
dirkx 0:355018f44c9f 961 /* Get and set parameters for the given connection.
dirkx 0:355018f44c9f 962 * Return 0 on success, an error code on failure. */
dirkx 0:355018f44c9f 963 int
dirkx 0:355018f44c9f 964 pppIOCtl(int pd, int cmd, void *arg)
dirkx 0:355018f44c9f 965 {
dirkx 0:355018f44c9f 966 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 967 int st = 0;
dirkx 0:355018f44c9f 968
dirkx 0:355018f44c9f 969 if (pd < 0 || pd >= NUM_PPP) {
dirkx 0:355018f44c9f 970 st = PPPERR_PARAM;
dirkx 0:355018f44c9f 971 } else {
dirkx 0:355018f44c9f 972 switch(cmd) {
dirkx 0:355018f44c9f 973 case PPPCTLG_UPSTATUS: /* Get the PPP up status. */
dirkx 0:355018f44c9f 974 if (arg) {
dirkx 0:355018f44c9f 975 *(int *)arg = (int)(pc->if_up);
dirkx 0:355018f44c9f 976 } else {
dirkx 0:355018f44c9f 977 st = PPPERR_PARAM;
dirkx 0:355018f44c9f 978 }
dirkx 0:355018f44c9f 979 break;
dirkx 0:355018f44c9f 980 case PPPCTLS_ERRCODE: /* Set the PPP error code. */
dirkx 0:355018f44c9f 981 if (arg) {
dirkx 0:355018f44c9f 982 pc->errCode = *(int *)arg;
dirkx 0:355018f44c9f 983 } else {
dirkx 0:355018f44c9f 984 st = PPPERR_PARAM;
dirkx 0:355018f44c9f 985 }
dirkx 0:355018f44c9f 986 break;
dirkx 0:355018f44c9f 987 case PPPCTLG_ERRCODE: /* Get the PPP error code. */
dirkx 0:355018f44c9f 988 if (arg) {
dirkx 0:355018f44c9f 989 *(int *)arg = (int)(pc->errCode);
dirkx 0:355018f44c9f 990 } else {
dirkx 0:355018f44c9f 991 st = PPPERR_PARAM;
dirkx 0:355018f44c9f 992 }
dirkx 0:355018f44c9f 993 break;
dirkx 0:355018f44c9f 994 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 995 case PPPCTLG_FD: /* Get the fd associated with the ppp */
dirkx 0:355018f44c9f 996 if (arg) {
dirkx 0:355018f44c9f 997 *(sio_fd_t *)arg = pc->fd;
dirkx 0:355018f44c9f 998 } else {
dirkx 0:355018f44c9f 999 st = PPPERR_PARAM;
dirkx 0:355018f44c9f 1000 }
dirkx 0:355018f44c9f 1001 break;
dirkx 0:355018f44c9f 1002 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 1003 default:
dirkx 0:355018f44c9f 1004 st = PPPERR_PARAM;
dirkx 0:355018f44c9f 1005 break;
dirkx 0:355018f44c9f 1006 }
dirkx 0:355018f44c9f 1007 }
dirkx 0:355018f44c9f 1008
dirkx 0:355018f44c9f 1009 return st;
dirkx 0:355018f44c9f 1010 }
dirkx 0:355018f44c9f 1011
dirkx 0:355018f44c9f 1012 /*
dirkx 0:355018f44c9f 1013 * Return the Maximum Transmission Unit for the given PPP connection.
dirkx 0:355018f44c9f 1014 */
dirkx 0:355018f44c9f 1015 u_short
dirkx 0:355018f44c9f 1016 pppMTU(int pd)
dirkx 0:355018f44c9f 1017 {
dirkx 0:355018f44c9f 1018 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1019 u_short st;
dirkx 0:355018f44c9f 1020
dirkx 0:355018f44c9f 1021 /* Validate parameters. */
dirkx 0:355018f44c9f 1022 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
dirkx 0:355018f44c9f 1023 st = 0;
dirkx 0:355018f44c9f 1024 } else {
dirkx 0:355018f44c9f 1025 st = pc->mtu;
dirkx 0:355018f44c9f 1026 }
dirkx 0:355018f44c9f 1027
dirkx 0:355018f44c9f 1028 return st;
dirkx 0:355018f44c9f 1029 }
dirkx 0:355018f44c9f 1030
dirkx 0:355018f44c9f 1031 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 1032 int
dirkx 0:355018f44c9f 1033 pppWriteOverEthernet(int pd, const u_char *s, int n)
dirkx 0:355018f44c9f 1034 {
dirkx 0:355018f44c9f 1035 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1036 struct pbuf *pb;
dirkx 0:355018f44c9f 1037
dirkx 0:355018f44c9f 1038 /* skip address & flags */
dirkx 0:355018f44c9f 1039 s += 2;
dirkx 0:355018f44c9f 1040 n -= 2;
dirkx 0:355018f44c9f 1041
dirkx 0:355018f44c9f 1042 LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff);
dirkx 0:355018f44c9f 1043 pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM);
dirkx 0:355018f44c9f 1044 if(!pb) {
dirkx 0:355018f44c9f 1045 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 1046 LINK_STATS_INC(link.proterr);
dirkx 0:355018f44c9f 1047 snmp_inc_ifoutdiscards(&pc->netif);
dirkx 0:355018f44c9f 1048 return PPPERR_ALLOC;
dirkx 0:355018f44c9f 1049 }
dirkx 0:355018f44c9f 1050
dirkx 0:355018f44c9f 1051 pbuf_header(pb, -(s16_t)PPPOE_HDRLEN);
dirkx 0:355018f44c9f 1052
dirkx 0:355018f44c9f 1053 pc->lastXMit = sys_jiffies();
dirkx 0:355018f44c9f 1054
dirkx 0:355018f44c9f 1055 MEMCPY(pb->payload, s, n);
dirkx 0:355018f44c9f 1056
dirkx 0:355018f44c9f 1057 if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
dirkx 0:355018f44c9f 1058 LINK_STATS_INC(link.err);
dirkx 0:355018f44c9f 1059 snmp_inc_ifoutdiscards(&pc->netif);
dirkx 0:355018f44c9f 1060 return PPPERR_DEVICE;
dirkx 0:355018f44c9f 1061 }
dirkx 0:355018f44c9f 1062
dirkx 0:355018f44c9f 1063 snmp_add_ifoutoctets(&pc->netif, (u16_t)n);
dirkx 0:355018f44c9f 1064 snmp_inc_ifoutucastpkts(&pc->netif);
dirkx 0:355018f44c9f 1065 LINK_STATS_INC(link.xmit);
dirkx 0:355018f44c9f 1066 return PPPERR_NONE;
dirkx 0:355018f44c9f 1067 }
dirkx 0:355018f44c9f 1068 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 1069
dirkx 0:355018f44c9f 1070 /*
dirkx 0:355018f44c9f 1071 * Write n characters to a ppp link.
dirkx 0:355018f44c9f 1072 * RETURN: >= 0 Number of characters written
dirkx 0:355018f44c9f 1073 * -1 Failed to write to device
dirkx 0:355018f44c9f 1074 */
dirkx 0:355018f44c9f 1075 int
dirkx 0:355018f44c9f 1076 pppWrite(int pd, const u_char *s, int n)
dirkx 0:355018f44c9f 1077 {
dirkx 0:355018f44c9f 1078 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1079 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 1080 u_char c;
dirkx 0:355018f44c9f 1081 u_int fcsOut;
dirkx 0:355018f44c9f 1082 struct pbuf *headMB, *tailMB;
dirkx 0:355018f44c9f 1083 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 1084
dirkx 0:355018f44c9f 1085 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 1086 if(pc->ethif) {
dirkx 0:355018f44c9f 1087 return pppWriteOverEthernet(pd, s, n);
dirkx 0:355018f44c9f 1088 }
dirkx 0:355018f44c9f 1089 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 1090
dirkx 0:355018f44c9f 1091 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 1092 headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
dirkx 0:355018f44c9f 1093 if (headMB == NULL) {
dirkx 0:355018f44c9f 1094 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 1095 LINK_STATS_INC(link.proterr);
dirkx 0:355018f44c9f 1096 snmp_inc_ifoutdiscards(&pc->netif);
dirkx 0:355018f44c9f 1097 return PPPERR_ALLOC;
dirkx 0:355018f44c9f 1098 }
dirkx 0:355018f44c9f 1099
dirkx 0:355018f44c9f 1100 tailMB = headMB;
dirkx 0:355018f44c9f 1101
dirkx 0:355018f44c9f 1102 /* If the link has been idle, we'll send a fresh flag character to
dirkx 0:355018f44c9f 1103 * flush any noise. */
dirkx 0:355018f44c9f 1104 if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
dirkx 0:355018f44c9f 1105 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
dirkx 0:355018f44c9f 1106 }
dirkx 0:355018f44c9f 1107 pc->lastXMit = sys_jiffies();
dirkx 0:355018f44c9f 1108
dirkx 0:355018f44c9f 1109 fcsOut = PPP_INITFCS;
dirkx 0:355018f44c9f 1110 /* Load output buffer. */
dirkx 0:355018f44c9f 1111 while (n-- > 0) {
dirkx 0:355018f44c9f 1112 c = *s++;
dirkx 0:355018f44c9f 1113
dirkx 0:355018f44c9f 1114 /* Update FCS before checking for special characters. */
dirkx 0:355018f44c9f 1115 fcsOut = PPP_FCS(fcsOut, c);
dirkx 0:355018f44c9f 1116
dirkx 0:355018f44c9f 1117 /* Copy to output buffer escaping special characters. */
dirkx 0:355018f44c9f 1118 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 1119 }
dirkx 0:355018f44c9f 1120
dirkx 0:355018f44c9f 1121 /* Add FCS and trailing flag. */
dirkx 0:355018f44c9f 1122 c = ~fcsOut & 0xFF;
dirkx 0:355018f44c9f 1123 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 1124 c = (~fcsOut >> 8) & 0xFF;
dirkx 0:355018f44c9f 1125 tailMB = pppAppend(c, tailMB, &pc->outACCM);
dirkx 0:355018f44c9f 1126 tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
dirkx 0:355018f44c9f 1127
dirkx 0:355018f44c9f 1128 /* If we failed to complete the packet, throw it away.
dirkx 0:355018f44c9f 1129 * Otherwise send it. */
dirkx 0:355018f44c9f 1130 if (!tailMB) {
dirkx 0:355018f44c9f 1131 PPPDEBUG(LOG_WARNING,
dirkx 0:355018f44c9f 1132 ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
dirkx 0:355018f44c9f 1133 /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
dirkx 0:355018f44c9f 1134 pbuf_free(headMB);
dirkx 0:355018f44c9f 1135 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 1136 LINK_STATS_INC(link.proterr);
dirkx 0:355018f44c9f 1137 snmp_inc_ifoutdiscards(&pc->netif);
dirkx 0:355018f44c9f 1138 return PPPERR_ALLOC;
dirkx 0:355018f44c9f 1139 }
dirkx 0:355018f44c9f 1140
dirkx 0:355018f44c9f 1141 PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len));
dirkx 0:355018f44c9f 1142 /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
dirkx 0:355018f44c9f 1143 nPut(pc, headMB);
dirkx 0:355018f44c9f 1144 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 1145
dirkx 0:355018f44c9f 1146 return PPPERR_NONE;
dirkx 0:355018f44c9f 1147 }
dirkx 0:355018f44c9f 1148
dirkx 0:355018f44c9f 1149 /*
dirkx 0:355018f44c9f 1150 * ppp_send_config - configure the transmit characteristics of
dirkx 0:355018f44c9f 1151 * the ppp interface.
dirkx 0:355018f44c9f 1152 */
dirkx 0:355018f44c9f 1153 void
dirkx 0:355018f44c9f 1154 ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp)
dirkx 0:355018f44c9f 1155 {
dirkx 0:355018f44c9f 1156 PPPControl *pc = &pppControl[unit];
dirkx 0:355018f44c9f 1157 int i;
dirkx 0:355018f44c9f 1158
dirkx 0:355018f44c9f 1159 pc->mtu = mtu;
dirkx 0:355018f44c9f 1160 pc->pcomp = pcomp;
dirkx 0:355018f44c9f 1161 pc->accomp = accomp;
dirkx 0:355018f44c9f 1162
dirkx 0:355018f44c9f 1163 /* Load the ACCM bits for the 32 control codes. */
dirkx 0:355018f44c9f 1164 for (i = 0; i < 32/8; i++) {
dirkx 0:355018f44c9f 1165 pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
dirkx 0:355018f44c9f 1166 }
dirkx 0:355018f44c9f 1167 PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n",
dirkx 0:355018f44c9f 1168 unit,
dirkx 0:355018f44c9f 1169 pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
dirkx 0:355018f44c9f 1170 }
dirkx 0:355018f44c9f 1171
dirkx 0:355018f44c9f 1172
dirkx 0:355018f44c9f 1173 /*
dirkx 0:355018f44c9f 1174 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
dirkx 0:355018f44c9f 1175 */
dirkx 0:355018f44c9f 1176 void
dirkx 0:355018f44c9f 1177 ppp_set_xaccm(int unit, ext_accm *accm)
dirkx 0:355018f44c9f 1178 {
dirkx 0:355018f44c9f 1179 SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm));
dirkx 0:355018f44c9f 1180 PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
dirkx 0:355018f44c9f 1181 unit,
dirkx 0:355018f44c9f 1182 pppControl[unit].outACCM[0],
dirkx 0:355018f44c9f 1183 pppControl[unit].outACCM[1],
dirkx 0:355018f44c9f 1184 pppControl[unit].outACCM[2],
dirkx 0:355018f44c9f 1185 pppControl[unit].outACCM[3]));
dirkx 0:355018f44c9f 1186 }
dirkx 0:355018f44c9f 1187
dirkx 0:355018f44c9f 1188
dirkx 0:355018f44c9f 1189 /*
dirkx 0:355018f44c9f 1190 * ppp_recv_config - configure the receive-side characteristics of
dirkx 0:355018f44c9f 1191 * the ppp interface.
dirkx 0:355018f44c9f 1192 */
dirkx 0:355018f44c9f 1193 void
dirkx 0:355018f44c9f 1194 ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp)
dirkx 0:355018f44c9f 1195 {
dirkx 0:355018f44c9f 1196 PPPControl *pc = &pppControl[unit];
dirkx 0:355018f44c9f 1197 int i;
dirkx 0:355018f44c9f 1198 SYS_ARCH_DECL_PROTECT(lev);
dirkx 0:355018f44c9f 1199
dirkx 0:355018f44c9f 1200 LWIP_UNUSED_ARG(accomp);
dirkx 0:355018f44c9f 1201 LWIP_UNUSED_ARG(pcomp);
dirkx 0:355018f44c9f 1202 LWIP_UNUSED_ARG(mru);
dirkx 0:355018f44c9f 1203
dirkx 0:355018f44c9f 1204 /* Load the ACCM bits for the 32 control codes. */
dirkx 0:355018f44c9f 1205 SYS_ARCH_PROTECT(lev);
dirkx 0:355018f44c9f 1206 for (i = 0; i < 32 / 8; i++) {
dirkx 0:355018f44c9f 1207 /* @todo: does this work? ext_accm has been modified from pppd! */
dirkx 0:355018f44c9f 1208 pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8));
dirkx 0:355018f44c9f 1209 }
dirkx 0:355018f44c9f 1210 SYS_ARCH_UNPROTECT(lev);
dirkx 0:355018f44c9f 1211 PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
dirkx 0:355018f44c9f 1212 unit,
dirkx 0:355018f44c9f 1213 pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3]));
dirkx 0:355018f44c9f 1214 }
dirkx 0:355018f44c9f 1215
dirkx 0:355018f44c9f 1216 #if 0
dirkx 0:355018f44c9f 1217 /*
dirkx 0:355018f44c9f 1218 * ccp_test - ask kernel whether a given compression method
dirkx 0:355018f44c9f 1219 * is acceptable for use. Returns 1 if the method and parameters
dirkx 0:355018f44c9f 1220 * are OK, 0 if the method is known but the parameters are not OK
dirkx 0:355018f44c9f 1221 * (e.g. code size should be reduced), or -1 if the method is unknown.
dirkx 0:355018f44c9f 1222 */
dirkx 0:355018f44c9f 1223 int
dirkx 0:355018f44c9f 1224 ccp_test( int unit, int opt_len, int for_transmit, u_char *opt_ptr)
dirkx 0:355018f44c9f 1225 {
dirkx 0:355018f44c9f 1226 return 0; /* XXX Currently no compression. */
dirkx 0:355018f44c9f 1227 }
dirkx 0:355018f44c9f 1228
dirkx 0:355018f44c9f 1229 /*
dirkx 0:355018f44c9f 1230 * ccp_flags_set - inform kernel about the current state of CCP.
dirkx 0:355018f44c9f 1231 */
dirkx 0:355018f44c9f 1232 void
dirkx 0:355018f44c9f 1233 ccp_flags_set(int unit, int isopen, int isup)
dirkx 0:355018f44c9f 1234 {
dirkx 0:355018f44c9f 1235 /* XXX */
dirkx 0:355018f44c9f 1236 }
dirkx 0:355018f44c9f 1237
dirkx 0:355018f44c9f 1238 /*
dirkx 0:355018f44c9f 1239 * ccp_fatal_error - returns 1 if decompression was disabled as a
dirkx 0:355018f44c9f 1240 * result of an error detected after decompression of a packet,
dirkx 0:355018f44c9f 1241 * 0 otherwise. This is necessary because of patent nonsense.
dirkx 0:355018f44c9f 1242 */
dirkx 0:355018f44c9f 1243 int
dirkx 0:355018f44c9f 1244 ccp_fatal_error(int unit)
dirkx 0:355018f44c9f 1245 {
dirkx 0:355018f44c9f 1246 /* XXX */
dirkx 0:355018f44c9f 1247 return 0;
dirkx 0:355018f44c9f 1248 }
dirkx 0:355018f44c9f 1249 #endif
dirkx 0:355018f44c9f 1250
dirkx 0:355018f44c9f 1251 /*
dirkx 0:355018f44c9f 1252 * get_idle_time - return how long the link has been idle.
dirkx 0:355018f44c9f 1253 */
dirkx 0:355018f44c9f 1254 int
dirkx 0:355018f44c9f 1255 get_idle_time(int u, struct ppp_idle *ip)
dirkx 0:355018f44c9f 1256 {
dirkx 0:355018f44c9f 1257 /* XXX */
dirkx 0:355018f44c9f 1258 LWIP_UNUSED_ARG(u);
dirkx 0:355018f44c9f 1259 LWIP_UNUSED_ARG(ip);
dirkx 0:355018f44c9f 1260
dirkx 0:355018f44c9f 1261 return 0;
dirkx 0:355018f44c9f 1262 }
dirkx 0:355018f44c9f 1263
dirkx 0:355018f44c9f 1264
dirkx 0:355018f44c9f 1265 /*
dirkx 0:355018f44c9f 1266 * Return user specified netmask, modified by any mask we might determine
dirkx 0:355018f44c9f 1267 * for address `addr' (in network byte order).
dirkx 0:355018f44c9f 1268 * Here we scan through the system's list of interfaces, looking for
dirkx 0:355018f44c9f 1269 * any non-point-to-point interfaces which might appear to be on the same
dirkx 0:355018f44c9f 1270 * network as `addr'. If we find any, we OR in their netmask to the
dirkx 0:355018f44c9f 1271 * user-specified netmask.
dirkx 0:355018f44c9f 1272 */
dirkx 0:355018f44c9f 1273 u32_t
dirkx 0:355018f44c9f 1274 GetMask(u32_t addr)
dirkx 0:355018f44c9f 1275 {
dirkx 0:355018f44c9f 1276 u32_t mask, nmask;
dirkx 0:355018f44c9f 1277
dirkx 0:355018f44c9f 1278 htonl(addr);
dirkx 0:355018f44c9f 1279 if (IP_CLASSA(addr)) { /* determine network mask for address class */
dirkx 0:355018f44c9f 1280 nmask = IP_CLASSA_NET;
dirkx 0:355018f44c9f 1281 } else if (IP_CLASSB(addr)) {
dirkx 0:355018f44c9f 1282 nmask = IP_CLASSB_NET;
dirkx 0:355018f44c9f 1283 } else {
dirkx 0:355018f44c9f 1284 nmask = IP_CLASSC_NET;
dirkx 0:355018f44c9f 1285 }
dirkx 0:355018f44c9f 1286
dirkx 0:355018f44c9f 1287 /* class D nets are disallowed by bad_ip_adrs */
dirkx 0:355018f44c9f 1288 mask = subnetMask | htonl(nmask);
dirkx 0:355018f44c9f 1289
dirkx 0:355018f44c9f 1290 /* XXX
dirkx 0:355018f44c9f 1291 * Scan through the system's network interfaces.
dirkx 0:355018f44c9f 1292 * Get each netmask and OR them into our mask.
dirkx 0:355018f44c9f 1293 */
dirkx 0:355018f44c9f 1294
dirkx 0:355018f44c9f 1295 return mask;
dirkx 0:355018f44c9f 1296 }
dirkx 0:355018f44c9f 1297
dirkx 0:355018f44c9f 1298 /*
dirkx 0:355018f44c9f 1299 * sifvjcomp - config tcp header compression
dirkx 0:355018f44c9f 1300 */
dirkx 0:355018f44c9f 1301 int
dirkx 0:355018f44c9f 1302 sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid)
dirkx 0:355018f44c9f 1303 {
dirkx 0:355018f44c9f 1304 #if PPPOS_SUPPORT && VJ_SUPPORT
dirkx 0:355018f44c9f 1305 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1306
dirkx 0:355018f44c9f 1307 pc->vjEnabled = vjcomp;
dirkx 0:355018f44c9f 1308 pc->vjComp.compressSlot = cidcomp;
dirkx 0:355018f44c9f 1309 pc->vjComp.maxSlotIndex = maxcid;
dirkx 0:355018f44c9f 1310 PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
dirkx 0:355018f44c9f 1311 vjcomp, cidcomp, maxcid));
dirkx 0:355018f44c9f 1312 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
dirkx 0:355018f44c9f 1313 LWIP_UNUSED_ARG(pd);
dirkx 0:355018f44c9f 1314 LWIP_UNUSED_ARG(vjcomp);
dirkx 0:355018f44c9f 1315 LWIP_UNUSED_ARG(cidcomp);
dirkx 0:355018f44c9f 1316 LWIP_UNUSED_ARG(maxcid);
dirkx 0:355018f44c9f 1317 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
dirkx 0:355018f44c9f 1318
dirkx 0:355018f44c9f 1319 return 0;
dirkx 0:355018f44c9f 1320 }
dirkx 0:355018f44c9f 1321
dirkx 0:355018f44c9f 1322 /*
dirkx 0:355018f44c9f 1323 * pppnetifNetifInit - netif init callback
dirkx 0:355018f44c9f 1324 */
dirkx 0:355018f44c9f 1325 static err_t
dirkx 0:355018f44c9f 1326 pppnetifNetifInit(struct netif *netif)
dirkx 0:355018f44c9f 1327 {
dirkx 0:355018f44c9f 1328 netif->name[0] = 'p';
dirkx 0:355018f44c9f 1329 netif->name[1] = 'p';
dirkx 0:355018f44c9f 1330 netif->output = pppnetifOutput;
dirkx 0:355018f44c9f 1331 netif->mtu = pppMTU((int)(size_t)netif->state);
dirkx 0:355018f44c9f 1332 netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP;
dirkx 0:355018f44c9f 1333 #if LWIP_NETIF_HOSTNAME
dirkx 0:355018f44c9f 1334 /* @todo: Initialize interface hostname */
dirkx 0:355018f44c9f 1335 /* netif_set_hostname(netif, "lwip"); */
dirkx 0:355018f44c9f 1336 #endif /* LWIP_NETIF_HOSTNAME */
dirkx 0:355018f44c9f 1337 return ERR_OK;
dirkx 0:355018f44c9f 1338 }
dirkx 0:355018f44c9f 1339
dirkx 0:355018f44c9f 1340
dirkx 0:355018f44c9f 1341 /*
dirkx 0:355018f44c9f 1342 * sifup - Config the interface up and enable IP packets to pass.
dirkx 0:355018f44c9f 1343 */
dirkx 0:355018f44c9f 1344 int
dirkx 0:355018f44c9f 1345 sifup(int pd)
dirkx 0:355018f44c9f 1346 {
dirkx 0:355018f44c9f 1347 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1348 int st = 1;
dirkx 0:355018f44c9f 1349
dirkx 0:355018f44c9f 1350 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
dirkx 0:355018f44c9f 1351 st = 0;
dirkx 0:355018f44c9f 1352 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
dirkx 0:355018f44c9f 1353 } else {
dirkx 0:355018f44c9f 1354 netif_remove(&pc->netif);
dirkx 0:355018f44c9f 1355 if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask,
dirkx 0:355018f44c9f 1356 &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppnetifNetifInit, ip_input)) {
dirkx 0:355018f44c9f 1357 netif_set_up(&pc->netif);
dirkx 0:355018f44c9f 1358 pc->if_up = 1;
dirkx 0:355018f44c9f 1359 pc->errCode = PPPERR_NONE;
dirkx 0:355018f44c9f 1360
dirkx 0:355018f44c9f 1361 PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
dirkx 0:355018f44c9f 1362 if (pc->linkStatusCB) {
dirkx 0:355018f44c9f 1363 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
dirkx 0:355018f44c9f 1364 }
dirkx 0:355018f44c9f 1365 } else {
dirkx 0:355018f44c9f 1366 st = 0;
dirkx 0:355018f44c9f 1367 PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd));
dirkx 0:355018f44c9f 1368 }
dirkx 0:355018f44c9f 1369 }
dirkx 0:355018f44c9f 1370
dirkx 0:355018f44c9f 1371 return st;
dirkx 0:355018f44c9f 1372 }
dirkx 0:355018f44c9f 1373
dirkx 0:355018f44c9f 1374 /*
dirkx 0:355018f44c9f 1375 * sifnpmode - Set the mode for handling packets for a given NP.
dirkx 0:355018f44c9f 1376 */
dirkx 0:355018f44c9f 1377 int
dirkx 0:355018f44c9f 1378 sifnpmode(int u, int proto, enum NPmode mode)
dirkx 0:355018f44c9f 1379 {
dirkx 0:355018f44c9f 1380 LWIP_UNUSED_ARG(u);
dirkx 0:355018f44c9f 1381 LWIP_UNUSED_ARG(proto);
dirkx 0:355018f44c9f 1382 LWIP_UNUSED_ARG(mode);
dirkx 0:355018f44c9f 1383 return 0;
dirkx 0:355018f44c9f 1384 }
dirkx 0:355018f44c9f 1385
dirkx 0:355018f44c9f 1386 /*
dirkx 0:355018f44c9f 1387 * sifdown - Config the interface down and disable IP.
dirkx 0:355018f44c9f 1388 */
dirkx 0:355018f44c9f 1389 int
dirkx 0:355018f44c9f 1390 sifdown(int pd)
dirkx 0:355018f44c9f 1391 {
dirkx 0:355018f44c9f 1392 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1393 int st = 1;
dirkx 0:355018f44c9f 1394
dirkx 0:355018f44c9f 1395 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
dirkx 0:355018f44c9f 1396 st = 0;
dirkx 0:355018f44c9f 1397 PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd));
dirkx 0:355018f44c9f 1398 } else {
dirkx 0:355018f44c9f 1399 pc->if_up = 0;
dirkx 0:355018f44c9f 1400 /* make sure the netif status callback is called */
dirkx 0:355018f44c9f 1401 netif_set_down(&pc->netif);
dirkx 0:355018f44c9f 1402 netif_remove(&pc->netif);
dirkx 0:355018f44c9f 1403 PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
dirkx 0:355018f44c9f 1404 if (pc->linkStatusCB) {
dirkx 0:355018f44c9f 1405 pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
dirkx 0:355018f44c9f 1406 }
dirkx 0:355018f44c9f 1407 }
dirkx 0:355018f44c9f 1408 return st;
dirkx 0:355018f44c9f 1409 }
dirkx 0:355018f44c9f 1410
dirkx 0:355018f44c9f 1411 /**
dirkx 0:355018f44c9f 1412 * sifaddr - Config the interface IP addresses and netmask.
dirkx 0:355018f44c9f 1413 * @param pd Interface unit ???
dirkx 0:355018f44c9f 1414 * @param o Our IP address ???
dirkx 0:355018f44c9f 1415 * @param h His IP address ???
dirkx 0:355018f44c9f 1416 * @param m IP subnet mask ???
dirkx 0:355018f44c9f 1417 * @param ns1 Primary DNS
dirkx 0:355018f44c9f 1418 * @param ns2 Secondary DNS
dirkx 0:355018f44c9f 1419 */
dirkx 0:355018f44c9f 1420 int
dirkx 0:355018f44c9f 1421 sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2)
dirkx 0:355018f44c9f 1422 {
dirkx 0:355018f44c9f 1423 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1424 int st = 1;
dirkx 0:355018f44c9f 1425
dirkx 0:355018f44c9f 1426 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
dirkx 0:355018f44c9f 1427 st = 0;
dirkx 0:355018f44c9f 1428 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
dirkx 0:355018f44c9f 1429 } else {
dirkx 0:355018f44c9f 1430 SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o));
dirkx 0:355018f44c9f 1431 SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h));
dirkx 0:355018f44c9f 1432 SMEMCPY(&pc->addrs.netmask, &m, sizeof(m));
dirkx 0:355018f44c9f 1433 SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1));
dirkx 0:355018f44c9f 1434 SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2));
dirkx 0:355018f44c9f 1435 }
dirkx 0:355018f44c9f 1436 return st;
dirkx 0:355018f44c9f 1437 }
dirkx 0:355018f44c9f 1438
dirkx 0:355018f44c9f 1439 /**
dirkx 0:355018f44c9f 1440 * cifaddr - Clear the interface IP addresses, and delete routes
dirkx 0:355018f44c9f 1441 * through the interface if possible.
dirkx 0:355018f44c9f 1442 * @param pd Interface unit ???
dirkx 0:355018f44c9f 1443 * @param o Our IP address ???
dirkx 0:355018f44c9f 1444 * @param h IP broadcast address ???
dirkx 0:355018f44c9f 1445 */
dirkx 0:355018f44c9f 1446 int
dirkx 0:355018f44c9f 1447 cifaddr( int pd, u32_t o, u32_t h)
dirkx 0:355018f44c9f 1448 {
dirkx 0:355018f44c9f 1449 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1450 int st = 1;
dirkx 0:355018f44c9f 1451
dirkx 0:355018f44c9f 1452 LWIP_UNUSED_ARG(o);
dirkx 0:355018f44c9f 1453 LWIP_UNUSED_ARG(h);
dirkx 0:355018f44c9f 1454 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
dirkx 0:355018f44c9f 1455 st = 0;
dirkx 0:355018f44c9f 1456 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
dirkx 0:355018f44c9f 1457 } else {
dirkx 0:355018f44c9f 1458 IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
dirkx 0:355018f44c9f 1459 IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
dirkx 0:355018f44c9f 1460 IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
dirkx 0:355018f44c9f 1461 IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
dirkx 0:355018f44c9f 1462 IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
dirkx 0:355018f44c9f 1463 }
dirkx 0:355018f44c9f 1464 return st;
dirkx 0:355018f44c9f 1465 }
dirkx 0:355018f44c9f 1466
dirkx 0:355018f44c9f 1467 /*
dirkx 0:355018f44c9f 1468 * sifdefaultroute - assign a default route through the address given.
dirkx 0:355018f44c9f 1469 */
dirkx 0:355018f44c9f 1470 int
dirkx 0:355018f44c9f 1471 sifdefaultroute(int pd, u32_t l, u32_t g)
dirkx 0:355018f44c9f 1472 {
dirkx 0:355018f44c9f 1473 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1474 int st = 1;
dirkx 0:355018f44c9f 1475
dirkx 0:355018f44c9f 1476 LWIP_UNUSED_ARG(l);
dirkx 0:355018f44c9f 1477 LWIP_UNUSED_ARG(g);
dirkx 0:355018f44c9f 1478
dirkx 0:355018f44c9f 1479 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
dirkx 0:355018f44c9f 1480 st = 0;
dirkx 0:355018f44c9f 1481 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
dirkx 0:355018f44c9f 1482 } else {
dirkx 0:355018f44c9f 1483 netif_set_default(&pc->netif);
dirkx 0:355018f44c9f 1484 }
dirkx 0:355018f44c9f 1485
dirkx 0:355018f44c9f 1486 /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
dirkx 0:355018f44c9f 1487
dirkx 0:355018f44c9f 1488 return st;
dirkx 0:355018f44c9f 1489 }
dirkx 0:355018f44c9f 1490
dirkx 0:355018f44c9f 1491 /*
dirkx 0:355018f44c9f 1492 * cifdefaultroute - delete a default route through the address given.
dirkx 0:355018f44c9f 1493 */
dirkx 0:355018f44c9f 1494 int
dirkx 0:355018f44c9f 1495 cifdefaultroute(int pd, u32_t l, u32_t g)
dirkx 0:355018f44c9f 1496 {
dirkx 0:355018f44c9f 1497 PPPControl *pc = &pppControl[pd];
dirkx 0:355018f44c9f 1498 int st = 1;
dirkx 0:355018f44c9f 1499
dirkx 0:355018f44c9f 1500 LWIP_UNUSED_ARG(l);
dirkx 0:355018f44c9f 1501 LWIP_UNUSED_ARG(g);
dirkx 0:355018f44c9f 1502
dirkx 0:355018f44c9f 1503 if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
dirkx 0:355018f44c9f 1504 st = 0;
dirkx 0:355018f44c9f 1505 PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd));
dirkx 0:355018f44c9f 1506 } else {
dirkx 0:355018f44c9f 1507 netif_set_default(NULL);
dirkx 0:355018f44c9f 1508 }
dirkx 0:355018f44c9f 1509
dirkx 0:355018f44c9f 1510 return st;
dirkx 0:355018f44c9f 1511 }
dirkx 0:355018f44c9f 1512
dirkx 0:355018f44c9f 1513 /**********************************/
dirkx 0:355018f44c9f 1514 /*** LOCAL FUNCTION DEFINITIONS ***/
dirkx 0:355018f44c9f 1515 /**********************************/
dirkx 0:355018f44c9f 1516
dirkx 0:355018f44c9f 1517 #if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD
dirkx 0:355018f44c9f 1518 /* The main PPP process function. This implements the state machine according
dirkx 0:355018f44c9f 1519 * to section 4 of RFC 1661: The Point-To-Point Protocol. */
dirkx 0:355018f44c9f 1520 static void
dirkx 0:355018f44c9f 1521 pppInputThread(void *arg)
dirkx 0:355018f44c9f 1522 {
dirkx 0:355018f44c9f 1523 int count;
dirkx 0:355018f44c9f 1524 PPPControlRx *pcrx = arg;
dirkx 0:355018f44c9f 1525
dirkx 0:355018f44c9f 1526 while (lcp_phase[pcrx->pd] != PHASE_DEAD) {
dirkx 0:355018f44c9f 1527 count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE);
dirkx 0:355018f44c9f 1528 if(count > 0) {
dirkx 0:355018f44c9f 1529 pppInProc(pcrx, pcrx->rxbuf, count);
dirkx 0:355018f44c9f 1530 } else {
dirkx 0:355018f44c9f 1531 /* nothing received, give other tasks a chance to run */
dirkx 0:355018f44c9f 1532 sys_msleep(1);
dirkx 0:355018f44c9f 1533 }
dirkx 0:355018f44c9f 1534 }
dirkx 0:355018f44c9f 1535 }
dirkx 0:355018f44c9f 1536 #endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */
dirkx 0:355018f44c9f 1537
dirkx 0:355018f44c9f 1538 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 1539
dirkx 0:355018f44c9f 1540 void
dirkx 0:355018f44c9f 1541 pppOverEthernetInitFailed(int pd)
dirkx 0:355018f44c9f 1542 {
dirkx 0:355018f44c9f 1543 PPPControl* pc;
dirkx 0:355018f44c9f 1544
dirkx 0:355018f44c9f 1545 pppHup(pd);
dirkx 0:355018f44c9f 1546 pppStop(pd);
dirkx 0:355018f44c9f 1547
dirkx 0:355018f44c9f 1548 pc = &pppControl[pd];
dirkx 0:355018f44c9f 1549 pppoe_destroy(&pc->netif);
dirkx 0:355018f44c9f 1550 pc->openFlag = 0;
dirkx 0:355018f44c9f 1551
dirkx 0:355018f44c9f 1552 if(pc->linkStatusCB) {
dirkx 0:355018f44c9f 1553 pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
dirkx 0:355018f44c9f 1554 }
dirkx 0:355018f44c9f 1555 }
dirkx 0:355018f44c9f 1556
dirkx 0:355018f44c9f 1557 static void
dirkx 0:355018f44c9f 1558 pppOverEthernetLinkStatusCB(int pd, int up)
dirkx 0:355018f44c9f 1559 {
dirkx 0:355018f44c9f 1560 if(up) {
dirkx 0:355018f44c9f 1561 PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd));
dirkx 0:355018f44c9f 1562 pppStart(pd);
dirkx 0:355018f44c9f 1563 } else {
dirkx 0:355018f44c9f 1564 pppOverEthernetInitFailed(pd);
dirkx 0:355018f44c9f 1565 }
dirkx 0:355018f44c9f 1566 }
dirkx 0:355018f44c9f 1567 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 1568
dirkx 0:355018f44c9f 1569 struct pbuf *
dirkx 0:355018f44c9f 1570 pppSingleBuf(struct pbuf *p)
dirkx 0:355018f44c9f 1571 {
dirkx 0:355018f44c9f 1572 struct pbuf *q, *b;
dirkx 0:355018f44c9f 1573 u_char *pl;
dirkx 0:355018f44c9f 1574
dirkx 0:355018f44c9f 1575 if(p->tot_len == p->len) {
dirkx 0:355018f44c9f 1576 return p;
dirkx 0:355018f44c9f 1577 }
dirkx 0:355018f44c9f 1578
dirkx 0:355018f44c9f 1579 q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
dirkx 0:355018f44c9f 1580 if(!q) {
dirkx 0:355018f44c9f 1581 PPPDEBUG(LOG_ERR,
dirkx 0:355018f44c9f 1582 ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
dirkx 0:355018f44c9f 1583 return p; /* live dangerously */
dirkx 0:355018f44c9f 1584 }
dirkx 0:355018f44c9f 1585
dirkx 0:355018f44c9f 1586 for(b = p, pl = (u_char*) q->payload; b != NULL; b = b->next) {
dirkx 0:355018f44c9f 1587 MEMCPY(pl, b->payload, b->len);
dirkx 0:355018f44c9f 1588 pl += b->len;
dirkx 0:355018f44c9f 1589 }
dirkx 0:355018f44c9f 1590
dirkx 0:355018f44c9f 1591 pbuf_free(p);
dirkx 0:355018f44c9f 1592
dirkx 0:355018f44c9f 1593 return q;
dirkx 0:355018f44c9f 1594 }
dirkx 0:355018f44c9f 1595
dirkx 0:355018f44c9f 1596 struct pppInputHeader {
dirkx 0:355018f44c9f 1597 int unit;
dirkx 0:355018f44c9f 1598 u16_t proto;
dirkx 0:355018f44c9f 1599 };
dirkx 0:355018f44c9f 1600
dirkx 0:355018f44c9f 1601 /*
dirkx 0:355018f44c9f 1602 * Pass the processed input packet to the appropriate handler.
dirkx 0:355018f44c9f 1603 * This function and all handlers run in the context of the tcpip_thread
dirkx 0:355018f44c9f 1604 */
dirkx 0:355018f44c9f 1605 static void
dirkx 0:355018f44c9f 1606 pppInput(void *arg)
dirkx 0:355018f44c9f 1607 {
dirkx 0:355018f44c9f 1608 struct pbuf *nb = (struct pbuf *)arg;
dirkx 0:355018f44c9f 1609 u16_t protocol;
dirkx 0:355018f44c9f 1610 int pd;
dirkx 0:355018f44c9f 1611
dirkx 0:355018f44c9f 1612 pd = ((struct pppInputHeader *)nb->payload)->unit;
dirkx 0:355018f44c9f 1613 protocol = ((struct pppInputHeader *)nb->payload)->proto;
dirkx 0:355018f44c9f 1614
dirkx 0:355018f44c9f 1615 if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) {
dirkx 0:355018f44c9f 1616 LWIP_ASSERT("pbuf_header failed\n", 0);
dirkx 0:355018f44c9f 1617 goto drop;
dirkx 0:355018f44c9f 1618 }
dirkx 0:355018f44c9f 1619
dirkx 0:355018f44c9f 1620 LINK_STATS_INC(link.recv);
dirkx 0:355018f44c9f 1621 snmp_inc_ifinucastpkts(&pppControl[pd].netif);
dirkx 0:355018f44c9f 1622 snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len);
dirkx 0:355018f44c9f 1623
dirkx 0:355018f44c9f 1624 /*
dirkx 0:355018f44c9f 1625 * Toss all non-LCP packets unless LCP is OPEN.
dirkx 0:355018f44c9f 1626 * Until we get past the authentication phase, toss all packets
dirkx 0:355018f44c9f 1627 * except LCP, LQR and authentication packets.
dirkx 0:355018f44c9f 1628 */
dirkx 0:355018f44c9f 1629 if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
dirkx 0:355018f44c9f 1630 if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
dirkx 0:355018f44c9f 1631 (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
dirkx 0:355018f44c9f 1632 PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd]));
dirkx 0:355018f44c9f 1633 goto drop;
dirkx 0:355018f44c9f 1634 }
dirkx 0:355018f44c9f 1635 }
dirkx 0:355018f44c9f 1636
dirkx 0:355018f44c9f 1637 switch(protocol) {
dirkx 0:355018f44c9f 1638 case PPP_VJC_COMP: /* VJ compressed TCP */
dirkx 0:355018f44c9f 1639 #if PPPOS_SUPPORT && VJ_SUPPORT
dirkx 0:355018f44c9f 1640 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
dirkx 0:355018f44c9f 1641 /*
dirkx 0:355018f44c9f 1642 * Clip off the VJ header and prepend the rebuilt TCP/IP header and
dirkx 0:355018f44c9f 1643 * pass the result to IP.
dirkx 0:355018f44c9f 1644 */
dirkx 0:355018f44c9f 1645 if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) {
dirkx 0:355018f44c9f 1646 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
dirkx 0:355018f44c9f 1647 return;
dirkx 0:355018f44c9f 1648 }
dirkx 0:355018f44c9f 1649 /* Something's wrong so drop it. */
dirkx 0:355018f44c9f 1650 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd));
dirkx 0:355018f44c9f 1651 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
dirkx 0:355018f44c9f 1652 /* No handler for this protocol so drop the packet. */
dirkx 0:355018f44c9f 1653 PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
dirkx 0:355018f44c9f 1654 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
dirkx 0:355018f44c9f 1655 break;
dirkx 0:355018f44c9f 1656
dirkx 0:355018f44c9f 1657 case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */
dirkx 0:355018f44c9f 1658 #if PPPOS_SUPPORT && VJ_SUPPORT
dirkx 0:355018f44c9f 1659 PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
dirkx 0:355018f44c9f 1660 /*
dirkx 0:355018f44c9f 1661 * Process the TCP/IP header for VJ header compression and then pass
dirkx 0:355018f44c9f 1662 * the packet to IP.
dirkx 0:355018f44c9f 1663 */
dirkx 0:355018f44c9f 1664 if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) {
dirkx 0:355018f44c9f 1665 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
dirkx 0:355018f44c9f 1666 return;
dirkx 0:355018f44c9f 1667 }
dirkx 0:355018f44c9f 1668 /* Something's wrong so drop it. */
dirkx 0:355018f44c9f 1669 PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd));
dirkx 0:355018f44c9f 1670 #else /* PPPOS_SUPPORT && VJ_SUPPORT */
dirkx 0:355018f44c9f 1671 /* No handler for this protocol so drop the packet. */
dirkx 0:355018f44c9f 1672 PPPDEBUG((LOG_INFO,
dirkx 0:355018f44c9f 1673 "pppInput[%d]: drop VJ UnComp in %d:.*H\n",
dirkx 0:355018f44c9f 1674 pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
dirkx 0:355018f44c9f 1675 #endif /* PPPOS_SUPPORT && VJ_SUPPORT */
dirkx 0:355018f44c9f 1676 break;
dirkx 0:355018f44c9f 1677
dirkx 0:355018f44c9f 1678 case PPP_IP: /* Internet Protocol */
dirkx 0:355018f44c9f 1679 PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
dirkx 0:355018f44c9f 1680 if (pppControl[pd].netif.input) {
dirkx 0:355018f44c9f 1681 pppControl[pd].netif.input(nb, &pppControl[pd].netif);
dirkx 0:355018f44c9f 1682 return;
dirkx 0:355018f44c9f 1683 }
dirkx 0:355018f44c9f 1684 break;
dirkx 0:355018f44c9f 1685
dirkx 0:355018f44c9f 1686 default: {
dirkx 0:355018f44c9f 1687 struct protent *protp;
dirkx 0:355018f44c9f 1688 int i;
dirkx 0:355018f44c9f 1689
dirkx 0:355018f44c9f 1690 /*
dirkx 0:355018f44c9f 1691 * Upcall the proper protocol input routine.
dirkx 0:355018f44c9f 1692 */
dirkx 0:355018f44c9f 1693 for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
dirkx 0:355018f44c9f 1694 if (protp->protocol == protocol && protp->enabled_flag) {
dirkx 0:355018f44c9f 1695 PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
dirkx 0:355018f44c9f 1696 nb = pppSingleBuf(nb);
dirkx 0:355018f44c9f 1697 (*protp->input)(pd, (u_char*)nb->payload, nb->len);
dirkx 0:355018f44c9f 1698 PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd));
dirkx 0:355018f44c9f 1699 goto out;
dirkx 0:355018f44c9f 1700 }
dirkx 0:355018f44c9f 1701 }
dirkx 0:355018f44c9f 1702
dirkx 0:355018f44c9f 1703 /* No handler for this protocol so reject the packet. */
dirkx 0:355018f44c9f 1704 PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len));
dirkx 0:355018f44c9f 1705 if (pbuf_header(nb, sizeof(protocol))) {
dirkx 0:355018f44c9f 1706 LWIP_ASSERT("pbuf_header failed\n", 0);
dirkx 0:355018f44c9f 1707 goto drop;
dirkx 0:355018f44c9f 1708 }
dirkx 0:355018f44c9f 1709 #if BYTE_ORDER == LITTLE_ENDIAN
dirkx 0:355018f44c9f 1710 protocol = htons(protocol);
dirkx 0:355018f44c9f 1711 SMEMCPY(nb->payload, &protocol, sizeof(protocol));
dirkx 0:355018f44c9f 1712 #endif /* BYTE_ORDER == LITTLE_ENDIAN */
dirkx 0:355018f44c9f 1713 lcp_sprotrej(pd, (u_char*) nb->payload, nb->len);
dirkx 0:355018f44c9f 1714 }
dirkx 0:355018f44c9f 1715 break;
dirkx 0:355018f44c9f 1716 }
dirkx 0:355018f44c9f 1717
dirkx 0:355018f44c9f 1718 drop:
dirkx 0:355018f44c9f 1719 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 1720 snmp_inc_ifindiscards(&pppControl[pd].netif);
dirkx 0:355018f44c9f 1721
dirkx 0:355018f44c9f 1722 out:
dirkx 0:355018f44c9f 1723 pbuf_free(nb);
dirkx 0:355018f44c9f 1724 return;
dirkx 0:355018f44c9f 1725 }
dirkx 0:355018f44c9f 1726
dirkx 0:355018f44c9f 1727 #if PPPOS_SUPPORT
dirkx 0:355018f44c9f 1728 /*
dirkx 0:355018f44c9f 1729 * Drop the input packet.
dirkx 0:355018f44c9f 1730 */
dirkx 0:355018f44c9f 1731 static void
dirkx 0:355018f44c9f 1732 pppDrop(PPPControlRx *pcrx)
dirkx 0:355018f44c9f 1733 {
dirkx 0:355018f44c9f 1734 if (pcrx->inHead != NULL) {
dirkx 0:355018f44c9f 1735 #if 0
dirkx 0:355018f44c9f 1736 PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload));
dirkx 0:355018f44c9f 1737 #endif
dirkx 0:355018f44c9f 1738 PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead));
dirkx 0:355018f44c9f 1739 if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) {
dirkx 0:355018f44c9f 1740 pbuf_free(pcrx->inTail);
dirkx 0:355018f44c9f 1741 }
dirkx 0:355018f44c9f 1742 pbuf_free(pcrx->inHead);
dirkx 0:355018f44c9f 1743 pcrx->inHead = NULL;
dirkx 0:355018f44c9f 1744 pcrx->inTail = NULL;
dirkx 0:355018f44c9f 1745 }
dirkx 0:355018f44c9f 1746 #if VJ_SUPPORT
dirkx 0:355018f44c9f 1747 vj_uncompress_err(&pppControl[pcrx->pd].vjComp);
dirkx 0:355018f44c9f 1748 #endif /* VJ_SUPPORT */
dirkx 0:355018f44c9f 1749
dirkx 0:355018f44c9f 1750 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 1751 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
dirkx 0:355018f44c9f 1752 }
dirkx 0:355018f44c9f 1753
dirkx 0:355018f44c9f 1754 /** Pass received raw characters to PPPoS to be decoded. This function is
dirkx 0:355018f44c9f 1755 * thread-safe and can be called from a dedicated RX-thread or from a main-loop.
dirkx 0:355018f44c9f 1756 *
dirkx 0:355018f44c9f 1757 * @param pd PPP descriptor index, returned by pppOpen()
dirkx 0:355018f44c9f 1758 * @param data received data
dirkx 0:355018f44c9f 1759 * @param len length of received data
dirkx 0:355018f44c9f 1760 */
dirkx 0:355018f44c9f 1761 void
dirkx 0:355018f44c9f 1762 pppos_input(int pd, u_char* data, int len)
dirkx 0:355018f44c9f 1763 {
dirkx 0:355018f44c9f 1764 pppInProc(&pppControl[pd].rx, data, len);
dirkx 0:355018f44c9f 1765 }
dirkx 0:355018f44c9f 1766
dirkx 0:355018f44c9f 1767 /**
dirkx 0:355018f44c9f 1768 * Process a received octet string.
dirkx 0:355018f44c9f 1769 */
dirkx 0:355018f44c9f 1770 static void
dirkx 0:355018f44c9f 1771 pppInProc(PPPControlRx *pcrx, u_char *s, int l)
dirkx 0:355018f44c9f 1772 {
dirkx 0:355018f44c9f 1773 struct pbuf *nextNBuf;
dirkx 0:355018f44c9f 1774 u_char curChar;
dirkx 0:355018f44c9f 1775 u_char escaped;
dirkx 0:355018f44c9f 1776 SYS_ARCH_DECL_PROTECT(lev);
dirkx 0:355018f44c9f 1777
dirkx 0:355018f44c9f 1778 PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l));
dirkx 0:355018f44c9f 1779 while (l-- > 0) {
dirkx 0:355018f44c9f 1780 curChar = *s++;
dirkx 0:355018f44c9f 1781
dirkx 0:355018f44c9f 1782 SYS_ARCH_PROTECT(lev);
dirkx 0:355018f44c9f 1783 escaped = ESCAPE_P(pcrx->inACCM, curChar);
dirkx 0:355018f44c9f 1784 SYS_ARCH_UNPROTECT(lev);
dirkx 0:355018f44c9f 1785 /* Handle special characters. */
dirkx 0:355018f44c9f 1786 if (escaped) {
dirkx 0:355018f44c9f 1787 /* Check for escape sequences. */
dirkx 0:355018f44c9f 1788 /* XXX Note that this does not handle an escaped 0x5d character which
dirkx 0:355018f44c9f 1789 * would appear as an escape character. Since this is an ASCII ']'
dirkx 0:355018f44c9f 1790 * and there is no reason that I know of to escape it, I won't complicate
dirkx 0:355018f44c9f 1791 * the code to handle this case. GLL */
dirkx 0:355018f44c9f 1792 if (curChar == PPP_ESCAPE) {
dirkx 0:355018f44c9f 1793 pcrx->inEscaped = 1;
dirkx 0:355018f44c9f 1794 /* Check for the flag character. */
dirkx 0:355018f44c9f 1795 } else if (curChar == PPP_FLAG) {
dirkx 0:355018f44c9f 1796 /* If this is just an extra flag character, ignore it. */
dirkx 0:355018f44c9f 1797 if (pcrx->inState <= PDADDRESS) {
dirkx 0:355018f44c9f 1798 /* ignore it */;
dirkx 0:355018f44c9f 1799 /* If we haven't received the packet header, drop what has come in. */
dirkx 0:355018f44c9f 1800 } else if (pcrx->inState < PDDATA) {
dirkx 0:355018f44c9f 1801 PPPDEBUG(LOG_WARNING,
dirkx 0:355018f44c9f 1802 ("pppInProc[%d]: Dropping incomplete packet %d\n",
dirkx 0:355018f44c9f 1803 pcrx->pd, pcrx->inState));
dirkx 0:355018f44c9f 1804 LINK_STATS_INC(link.lenerr);
dirkx 0:355018f44c9f 1805 pppDrop(pcrx);
dirkx 0:355018f44c9f 1806 /* If the fcs is invalid, drop the packet. */
dirkx 0:355018f44c9f 1807 } else if (pcrx->inFCS != PPP_GOODFCS) {
dirkx 0:355018f44c9f 1808 PPPDEBUG(LOG_INFO,
dirkx 0:355018f44c9f 1809 ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n",
dirkx 0:355018f44c9f 1810 pcrx->pd, pcrx->inFCS, pcrx->inProtocol));
dirkx 0:355018f44c9f 1811 /* Note: If you get lots of these, check for UART frame errors or try different baud rate */
dirkx 0:355018f44c9f 1812 LINK_STATS_INC(link.chkerr);
dirkx 0:355018f44c9f 1813 pppDrop(pcrx);
dirkx 0:355018f44c9f 1814 /* Otherwise it's a good packet so pass it on. */
dirkx 0:355018f44c9f 1815 } else {
dirkx 0:355018f44c9f 1816 /* Trim off the checksum. */
dirkx 0:355018f44c9f 1817 if(pcrx->inTail->len >= 2) {
dirkx 0:355018f44c9f 1818 pcrx->inTail->len -= 2;
dirkx 0:355018f44c9f 1819
dirkx 0:355018f44c9f 1820 pcrx->inTail->tot_len = pcrx->inTail->len;
dirkx 0:355018f44c9f 1821 if (pcrx->inTail != pcrx->inHead) {
dirkx 0:355018f44c9f 1822 pbuf_cat(pcrx->inHead, pcrx->inTail);
dirkx 0:355018f44c9f 1823 }
dirkx 0:355018f44c9f 1824 } else {
dirkx 0:355018f44c9f 1825 pcrx->inTail->tot_len = pcrx->inTail->len;
dirkx 0:355018f44c9f 1826 if (pcrx->inTail != pcrx->inHead) {
dirkx 0:355018f44c9f 1827 pbuf_cat(pcrx->inHead, pcrx->inTail);
dirkx 0:355018f44c9f 1828 }
dirkx 0:355018f44c9f 1829
dirkx 0:355018f44c9f 1830 pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2);
dirkx 0:355018f44c9f 1831 }
dirkx 0:355018f44c9f 1832
dirkx 0:355018f44c9f 1833 /* Dispatch the packet thereby consuming it. */
dirkx 0:355018f44c9f 1834 #if PPP_INPROC_MULTITHREADED
dirkx 0:355018f44c9f 1835 if(tcpip_callback_with_block(pppInput, pcrx->inHead, 0) != ERR_OK) {
dirkx 0:355018f44c9f 1836 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd));
dirkx 0:355018f44c9f 1837 pbuf_free(pcrx->inHead);
dirkx 0:355018f44c9f 1838 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 1839 snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif);
dirkx 0:355018f44c9f 1840 }
dirkx 0:355018f44c9f 1841 #else /* PPP_INPROC_MULTITHREADED */
dirkx 0:355018f44c9f 1842 pppInput(pcrx->inHead);
dirkx 0:355018f44c9f 1843 #endif /* PPP_INPROC_MULTITHREADED */
dirkx 0:355018f44c9f 1844 pcrx->inHead = NULL;
dirkx 0:355018f44c9f 1845 pcrx->inTail = NULL;
dirkx 0:355018f44c9f 1846 }
dirkx 0:355018f44c9f 1847
dirkx 0:355018f44c9f 1848 /* Prepare for a new packet. */
dirkx 0:355018f44c9f 1849 pcrx->inFCS = PPP_INITFCS;
dirkx 0:355018f44c9f 1850 pcrx->inState = PDADDRESS;
dirkx 0:355018f44c9f 1851 pcrx->inEscaped = 0;
dirkx 0:355018f44c9f 1852 /* Other characters are usually control characters that may have
dirkx 0:355018f44c9f 1853 * been inserted by the physical layer so here we just drop them. */
dirkx 0:355018f44c9f 1854 } else {
dirkx 0:355018f44c9f 1855 PPPDEBUG(LOG_WARNING,
dirkx 0:355018f44c9f 1856 ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar));
dirkx 0:355018f44c9f 1857 }
dirkx 0:355018f44c9f 1858 /* Process other characters. */
dirkx 0:355018f44c9f 1859 } else {
dirkx 0:355018f44c9f 1860 /* Unencode escaped characters. */
dirkx 0:355018f44c9f 1861 if (pcrx->inEscaped) {
dirkx 0:355018f44c9f 1862 pcrx->inEscaped = 0;
dirkx 0:355018f44c9f 1863 curChar ^= PPP_TRANS;
dirkx 0:355018f44c9f 1864 }
dirkx 0:355018f44c9f 1865
dirkx 0:355018f44c9f 1866 /* Process character relative to current state. */
dirkx 0:355018f44c9f 1867 switch(pcrx->inState) {
dirkx 0:355018f44c9f 1868 case PDIDLE: /* Idle state - waiting. */
dirkx 0:355018f44c9f 1869 /* Drop the character if it's not 0xff
dirkx 0:355018f44c9f 1870 * we would have processed a flag character above. */
dirkx 0:355018f44c9f 1871 if (curChar != PPP_ALLSTATIONS) {
dirkx 0:355018f44c9f 1872 break;
dirkx 0:355018f44c9f 1873 }
dirkx 0:355018f44c9f 1874
dirkx 0:355018f44c9f 1875 /* Fall through */
dirkx 0:355018f44c9f 1876 case PDSTART: /* Process start flag. */
dirkx 0:355018f44c9f 1877 /* Prepare for a new packet. */
dirkx 0:355018f44c9f 1878 pcrx->inFCS = PPP_INITFCS;
dirkx 0:355018f44c9f 1879
dirkx 0:355018f44c9f 1880 /* Fall through */
dirkx 0:355018f44c9f 1881 case PDADDRESS: /* Process address field. */
dirkx 0:355018f44c9f 1882 if (curChar == PPP_ALLSTATIONS) {
dirkx 0:355018f44c9f 1883 pcrx->inState = PDCONTROL;
dirkx 0:355018f44c9f 1884 break;
dirkx 0:355018f44c9f 1885 }
dirkx 0:355018f44c9f 1886 /* Else assume compressed address and control fields so
dirkx 0:355018f44c9f 1887 * fall through to get the protocol... */
dirkx 0:355018f44c9f 1888 case PDCONTROL: /* Process control field. */
dirkx 0:355018f44c9f 1889 /* If we don't get a valid control code, restart. */
dirkx 0:355018f44c9f 1890 if (curChar == PPP_UI) {
dirkx 0:355018f44c9f 1891 pcrx->inState = PDPROTOCOL1;
dirkx 0:355018f44c9f 1892 break;
dirkx 0:355018f44c9f 1893 }
dirkx 0:355018f44c9f 1894 #if 0
dirkx 0:355018f44c9f 1895 else {
dirkx 0:355018f44c9f 1896 PPPDEBUG((LOG_WARNING,
dirkx 0:355018f44c9f 1897 "pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar));
dirkx 0:355018f44c9f 1898 pcrx->inState = PDSTART;
dirkx 0:355018f44c9f 1899 }
dirkx 0:355018f44c9f 1900 #endif
dirkx 0:355018f44c9f 1901 case PDPROTOCOL1: /* Process protocol field 1. */
dirkx 0:355018f44c9f 1902 /* If the lower bit is set, this is the end of the protocol
dirkx 0:355018f44c9f 1903 * field. */
dirkx 0:355018f44c9f 1904 if (curChar & 1) {
dirkx 0:355018f44c9f 1905 pcrx->inProtocol = curChar;
dirkx 0:355018f44c9f 1906 pcrx->inState = PDDATA;
dirkx 0:355018f44c9f 1907 } else {
dirkx 0:355018f44c9f 1908 pcrx->inProtocol = (u_int)curChar << 8;
dirkx 0:355018f44c9f 1909 pcrx->inState = PDPROTOCOL2;
dirkx 0:355018f44c9f 1910 }
dirkx 0:355018f44c9f 1911 break;
dirkx 0:355018f44c9f 1912 case PDPROTOCOL2: /* Process protocol field 2. */
dirkx 0:355018f44c9f 1913 pcrx->inProtocol |= curChar;
dirkx 0:355018f44c9f 1914 pcrx->inState = PDDATA;
dirkx 0:355018f44c9f 1915 break;
dirkx 0:355018f44c9f 1916 case PDDATA: /* Process data byte. */
dirkx 0:355018f44c9f 1917 /* Make space to receive processed data. */
dirkx 0:355018f44c9f 1918 if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) {
dirkx 0:355018f44c9f 1919 if(pcrx->inTail) {
dirkx 0:355018f44c9f 1920 pcrx->inTail->tot_len = pcrx->inTail->len;
dirkx 0:355018f44c9f 1921 if (pcrx->inTail != pcrx->inHead) {
dirkx 0:355018f44c9f 1922 pbuf_cat(pcrx->inHead, pcrx->inTail);
dirkx 0:355018f44c9f 1923 }
dirkx 0:355018f44c9f 1924 }
dirkx 0:355018f44c9f 1925 /* If we haven't started a packet, we need a packet header. */
dirkx 0:355018f44c9f 1926 nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
dirkx 0:355018f44c9f 1927 if (nextNBuf == NULL) {
dirkx 0:355018f44c9f 1928 /* No free buffers. Drop the input packet and let the
dirkx 0:355018f44c9f 1929 * higher layers deal with it. Continue processing
dirkx 0:355018f44c9f 1930 * the received pbuf chain in case a new packet starts. */
dirkx 0:355018f44c9f 1931 PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd));
dirkx 0:355018f44c9f 1932 LINK_STATS_INC(link.memerr);
dirkx 0:355018f44c9f 1933 pppDrop(pcrx);
dirkx 0:355018f44c9f 1934 pcrx->inState = PDSTART; /* Wait for flag sequence. */
dirkx 0:355018f44c9f 1935 break;
dirkx 0:355018f44c9f 1936 }
dirkx 0:355018f44c9f 1937 if (pcrx->inHead == NULL) {
dirkx 0:355018f44c9f 1938 struct pppInputHeader *pih = (struct pppInputHeader*) nextNBuf->payload;
dirkx 0:355018f44c9f 1939
dirkx 0:355018f44c9f 1940 pih->unit = pcrx->pd;
dirkx 0:355018f44c9f 1941 pih->proto = pcrx->inProtocol;
dirkx 0:355018f44c9f 1942
dirkx 0:355018f44c9f 1943 nextNBuf->len += sizeof(*pih);
dirkx 0:355018f44c9f 1944
dirkx 0:355018f44c9f 1945 pcrx->inHead = nextNBuf;
dirkx 0:355018f44c9f 1946 }
dirkx 0:355018f44c9f 1947 pcrx->inTail = nextNBuf;
dirkx 0:355018f44c9f 1948 }
dirkx 0:355018f44c9f 1949 /* Load character into buffer. */
dirkx 0:355018f44c9f 1950 ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar;
dirkx 0:355018f44c9f 1951 break;
dirkx 0:355018f44c9f 1952 }
dirkx 0:355018f44c9f 1953
dirkx 0:355018f44c9f 1954 /* update the frame check sequence number. */
dirkx 0:355018f44c9f 1955 pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar);
dirkx 0:355018f44c9f 1956 }
dirkx 0:355018f44c9f 1957 } /* while (l-- > 0), all bytes processed */
dirkx 0:355018f44c9f 1958
dirkx 0:355018f44c9f 1959 avRandomize();
dirkx 0:355018f44c9f 1960 }
dirkx 0:355018f44c9f 1961 #endif /* PPPOS_SUPPORT */
dirkx 0:355018f44c9f 1962
dirkx 0:355018f44c9f 1963 #if PPPOE_SUPPORT
dirkx 0:355018f44c9f 1964 void
dirkx 0:355018f44c9f 1965 pppInProcOverEthernet(int pd, struct pbuf *pb)
dirkx 0:355018f44c9f 1966 {
dirkx 0:355018f44c9f 1967 struct pppInputHeader *pih;
dirkx 0:355018f44c9f 1968 u16_t inProtocol;
dirkx 0:355018f44c9f 1969
dirkx 0:355018f44c9f 1970 if(pb->len < sizeof(inProtocol)) {
dirkx 0:355018f44c9f 1971 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n"));
dirkx 0:355018f44c9f 1972 goto drop;
dirkx 0:355018f44c9f 1973 }
dirkx 0:355018f44c9f 1974
dirkx 0:355018f44c9f 1975 inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1];
dirkx 0:355018f44c9f 1976
dirkx 0:355018f44c9f 1977 /* make room for pppInputHeader - should not fail */
dirkx 0:355018f44c9f 1978 if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) {
dirkx 0:355018f44c9f 1979 PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n"));
dirkx 0:355018f44c9f 1980 goto drop;
dirkx 0:355018f44c9f 1981 }
dirkx 0:355018f44c9f 1982
dirkx 0:355018f44c9f 1983 pih = pb->payload;
dirkx 0:355018f44c9f 1984
dirkx 0:355018f44c9f 1985 pih->unit = pd;
dirkx 0:355018f44c9f 1986 pih->proto = inProtocol;
dirkx 0:355018f44c9f 1987
dirkx 0:355018f44c9f 1988 /* Dispatch the packet thereby consuming it. */
dirkx 0:355018f44c9f 1989 pppInput(pb);
dirkx 0:355018f44c9f 1990 return;
dirkx 0:355018f44c9f 1991
dirkx 0:355018f44c9f 1992 drop:
dirkx 0:355018f44c9f 1993 LINK_STATS_INC(link.drop);
dirkx 0:355018f44c9f 1994 snmp_inc_ifindiscards(&pppControl[pd].netif);
dirkx 0:355018f44c9f 1995 pbuf_free(pb);
dirkx 0:355018f44c9f 1996 return;
dirkx 0:355018f44c9f 1997 }
dirkx 0:355018f44c9f 1998 #endif /* PPPOE_SUPPORT */
dirkx 0:355018f44c9f 1999
dirkx 0:355018f44c9f 2000 #if LWIP_NETIF_STATUS_CALLBACK
dirkx 0:355018f44c9f 2001 /** Set the status callback of a PPP's netif
dirkx 0:355018f44c9f 2002 *
dirkx 0:355018f44c9f 2003 * @param pd The PPP descriptor returned by pppOpen()
dirkx 0:355018f44c9f 2004 * @param status_callback pointer to the status callback function
dirkx 0:355018f44c9f 2005 *
dirkx 0:355018f44c9f 2006 * @see netif_set_status_callback
dirkx 0:355018f44c9f 2007 */
dirkx 0:355018f44c9f 2008 void
dirkx 0:355018f44c9f 2009 ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback)
dirkx 0:355018f44c9f 2010 {
dirkx 0:355018f44c9f 2011 netif_set_status_callback(&pppControl[pd].netif, status_callback);
dirkx 0:355018f44c9f 2012 }
dirkx 0:355018f44c9f 2013 #endif /* LWIP_NETIF_STATUS_CALLBACK */
dirkx 0:355018f44c9f 2014
dirkx 0:355018f44c9f 2015 #if LWIP_NETIF_LINK_CALLBACK
dirkx 0:355018f44c9f 2016 /** Set the link callback of a PPP's netif
dirkx 0:355018f44c9f 2017 *
dirkx 0:355018f44c9f 2018 * @param pd The PPP descriptor returned by pppOpen()
dirkx 0:355018f44c9f 2019 * @param link_callback pointer to the link callback function
dirkx 0:355018f44c9f 2020 *
dirkx 0:355018f44c9f 2021 * @see netif_set_link_callback
dirkx 0:355018f44c9f 2022 */
dirkx 0:355018f44c9f 2023 void
dirkx 0:355018f44c9f 2024 ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback)
dirkx 0:355018f44c9f 2025 {
dirkx 0:355018f44c9f 2026 netif_set_link_callback(&pppControl[pd].netif, link_callback);
dirkx 0:355018f44c9f 2027 }
dirkx 0:355018f44c9f 2028 #endif /* LWIP_NETIF_LINK_CALLBACK */
dirkx 0:355018f44c9f 2029
dirkx 0:355018f44c9f 2030 #endif /* PPP_SUPPORT */