OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_132/] [src/] [netif/] [ppp/] [ppp.c] - Blame information for rev 606

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.