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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP_130/] [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 Jabobsen 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];
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
  PPPControl *pc = &pppControl[pd];
310
 
311
  PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd));
312
 
313
#if PPPOE_SUPPORT
314
  if(pc->ethif) {
315
    pppoe_disconnect(pc->pppoe_sc);
316
  } else
317
#endif /* PPPOE_SUPPORT */
318
  {
319
#if PPPOS_SUPPORT
320
    pppMainWakeup(pd);
321
#endif /* PPPOS_SUPPORT */
322
  }
323
}
324
 
325
void
326
pppLinkDown(int pd)
327
{
328
  PPPControl *pc = &pppControl[pd];
329
 
330
  PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd));
331
 
332
#if PPPOE_SUPPORT
333
  if(pc->ethif) {
334
    pppoe_disconnect(pc->pppoe_sc);
335
  } else
336
#endif /* PPPOE_SUPPORT */
337
  {
338
#if PPPOS_SUPPORT
339
    pppMainWakeup(pd);
340
#endif /* PPPOS_SUPPORT */
341
  }
342
}
343
 
344
/* these callbacks are necessary because lcp_* functions
345
   must be called in the same context as pppInput(),
346
   namely the tcpip_thread(), essentially because
347
   they manipulate timeouts which are thread-private
348
*/
349
 
350
static void
351
pppStartCB(void *arg)
352
{
353
  int pd = (int)arg;
354
 
355
  PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
356
  lcp_lowerup(pd);
357
  lcp_open(pd); /* Start protocol */
358
}
359
 
360
static void
361
pppStopCB(void *arg)
362
{
363
  int pd = (int)arg;
364
 
365
  PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
366
  lcp_close(pd, "User request");
367
}
368
 
369
static void
370
pppHupCB(void *arg)
371
{
372
  int pd = (int)arg;
373
 
374
  PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
375
  lcp_lowerdown(pd);
376
  link_terminated(pd);
377
}
378
 
379
/***********************************/
380
/*** PUBLIC FUNCTION DEFINITIONS ***/
381
/***********************************/
382
/* Initialize the PPP subsystem. */
383
 
384
struct ppp_settings ppp_settings;
385
 
386
err_t
387
pppInit(void)
388
{
389
  struct protent *protp;
390
  int i, j;
391
 
392
  memset(&ppp_settings, 0, sizeof(ppp_settings));
393
  ppp_settings.usepeerdns = 1;
394
  pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
395
 
396
  magicInit();
397
 
398
  for (i = 0; i < NUM_PPP; i++) {
399
    pppControl[i].openFlag = 0;
400
 
401
    subnetMask = htonl(0xffffff00);
402
 
403
    outpacket_buf[i] = (u_char *)mem_malloc(PPP_MRU+PPP_HDRLEN);
404
    if(!outpacket_buf[i]) {
405
      return ERR_MEM;
406
    }
407
 
408
    /*
409
     * Initialize to the standard option set.
410
     */
411
    for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) {
412
      (*protp->init)(i);
413
    }
414
  }
415
 
416
#if LINK_STATS
417
  /** @todo already done in stats_init (in fact, zeroed at boot). So, remove it? */
418
  /* Clear the statistics. */
419
  memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
420
#endif /* LINK_STATS */
421
 
422
#if PPPOE_SUPPORT
423
  pppoe_init();
424
#endif /* PPPOE_SUPPORT */
425
 
426
  return ERR_OK;
427
}
428
 
429
void
430
pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
431
{
432
  switch(authType) {
433
    case PPPAUTHTYPE_NONE:
434
    default:
435
#ifdef LWIP_PPP_STRICT_PAP_REJECT
436
      ppp_settings.refuse_pap = 1;
437
#else  /* LWIP_PPP_STRICT_PAP_REJECT */
438
      /* some providers request pap and accept an empty login/pw */
439
      ppp_settings.refuse_pap = 0;
440
#endif /* LWIP_PPP_STRICT_PAP_REJECT */
441
      ppp_settings.refuse_chap = 1;
442
      break;
443
 
444
    case PPPAUTHTYPE_ANY:
445
      /* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
446
       * RFC 1994 says:
447
       *
448
       * In practice, within or associated with each PPP server, there is a
449
       * database which associates "user" names with authentication
450
       * information ("secrets").  It is not anticipated that a particular
451
       * named user would be authenticated by multiple methods.  This would
452
       * make the user vulnerable to attacks which negotiate the least secure
453
       * method from among a set (such as PAP rather than CHAP).  If the same
454
       * secret was used, PAP would reveal the secret to be used later with
455
       * CHAP.
456
       *
457
       * Instead, for each user name there should be an indication of exactly
458
       * one method used to authenticate that user name.  If a user needs to
459
       * make use of different authentication methods under different
460
       * circumstances, then distinct user names SHOULD be employed, each of
461
       * which identifies exactly one authentication method.
462
       *
463
       */
464
      ppp_settings.refuse_pap = 0;
465
      ppp_settings.refuse_chap = 0;
466
      break;
467
 
468
    case PPPAUTHTYPE_PAP:
469
      ppp_settings.refuse_pap = 0;
470
      ppp_settings.refuse_chap = 1;
471
      break;
472
 
473
    case PPPAUTHTYPE_CHAP:
474
      ppp_settings.refuse_pap = 1;
475
      ppp_settings.refuse_chap = 0;
476
      break;
477
  }
478
 
479
  if(user) {
480
    strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
481
    ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
482
  } else {
483
    ppp_settings.user[0] = '\0';
484
  }
485
 
486
  if(passwd) {
487
    strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
488
    ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
489
  } else {
490
    ppp_settings.passwd[0] = '\0';
491
  }
492
}
493
 
494
#if PPPOS_SUPPORT
495
/* Open a new PPP connection using the given I/O device.
496
 * This initializes the PPP control block but does not
497
 * attempt to negotiate the LCP session.  If this port
498
 * connects to a modem, the modem connection must be
499
 * established before calling this.
500
 * Return a new PPP connection descriptor on success or
501
 * an error code (negative) on failure. */
502
int
503
pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
504
{
505
  PPPControl *pc;
506
  int pd;
507
 
508
  /* Find a free PPP session descriptor. Critical region? */
509
  for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
510
 
511
  if (pd >= NUM_PPP) {
512
    pd = PPPERR_OPEN;
513
  } else {
514
    pppControl[pd].openFlag = !0;
515
  }
516
 
517
  /* Launch a deamon thread. */
518
  if (pd >= 0) {
519
    pppControl[pd].openFlag = 1;
520
 
521
    lcp_init(pd);
522
    pc = &pppControl[pd];
523
    pc->fd = fd;
524
#if PPPOE_SUPPORT
525
    pc->ethif= NULL;
526
#endif /* PPPOE_SUPPORT */
527
    pc->kill_link = 0;
528
    pc->sig_hup = 0;
529
    pc->if_up = 0;
530
    pc->errCode = 0;
531
    pc->inState = PDIDLE;
532
    pc->inHead = NULL;
533
    pc->inTail = NULL;
534
    pc->inEscaped = 0;
535
    pc->lastXMit = 0;
536
 
537
#if VJ_SUPPORT
538
    pc->vjEnabled = 0;
539
    vj_compress_init(&pc->vjComp);
540
#endif /* VJ_SUPPORT */
541
 
542
    /*
543
     * Default the in and out accm so that escape and flag characters
544
     * are always escaped.
545
     */
546
    memset(pc->inACCM, 0, sizeof(ext_accm));
547
    pc->inACCM[15] = 0x60;
548
    memset(pc->outACCM, 0, sizeof(ext_accm));
549
    pc->outACCM[15] = 0x60;
550
 
551
    pc->linkStatusCB = linkStatusCB;
552
    pc->linkStatusCtx = linkStatusCtx;
553
 
554
    sys_thread_new(PPP_THREAD_NAME, pppMain, (void*)pd, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO);
555
    if(!linkStatusCB) {
556
      while(pd >= 0 && !pc->if_up) {
557
        sys_msleep(500);
558
        if (lcp_phase[pd] == PHASE_DEAD) {
559
          pppClose(pd);
560
          if (pc->errCode) {
561
            pd = pc->errCode;
562
          } else {
563
            pd = PPPERR_CONNECT;
564
          }
565
        }
566
      }
567
    }
568
  }
569
 
570
  return pd;
571
}
572
#endif /* PPPOS_SUPPORT */
573
 
574
#if PPPOE_SUPPORT
575
static void pppOverEthernetLinkStatusCB(int pd, int up);
576
 
577
void
578
pppOverEthernetClose(int pd)
579
{
580
  PPPControl* pc = &pppControl[pd];
581
 
582
  /* *TJL* There's no lcp_deinit */
583
  lcp_close(pd, NULL);
584
 
585
  pppoe_destroy(&pc->netif);
586
}
587
 
588
int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const char *concentrator_name, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
589
{
590
  PPPControl *pc;
591
  int pd;
592
 
593
  LWIP_UNUSED_ARG(service_name);
594
  LWIP_UNUSED_ARG(concentrator_name);
595
 
596
  /* Find a free PPP session descriptor. Critical region? */
597
  for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
598
  if (pd >= NUM_PPP) {
599
    pd = PPPERR_OPEN;
600
  } else {
601
    pppControl[pd].openFlag = !0;
602
  }
603
 
604
  /* Launch a deamon thread. */
605
  if (pd >= 0) {
606
 
607
    pppControl[pd].openFlag = 1;
608
 
609
    lcp_init(pd);
610
 
611
    lcp_wantoptions[pd].mru = PPPOE_MAXMTU;
612
    lcp_wantoptions[pd].neg_asyncmap = 0;
613
    lcp_wantoptions[pd].neg_pcompression = 0;
614
    lcp_wantoptions[pd].neg_accompression = 0;
615
 
616
    lcp_allowoptions[pd].mru = PPPOE_MAXMTU;
617
    lcp_allowoptions[pd].neg_asyncmap = 0;
618
    lcp_allowoptions[pd].neg_pcompression = 0;
619
    lcp_allowoptions[pd].neg_accompression = 0;
620
 
621
    pc = &pppControl[pd];
622
    pc->if_up = 0;
623
    pc->errCode = 0;
624
    pc->lastXMit = 0;
625
#if PPPOS_SUPPORT
626
    pc->kill_link = 0;
627
    pc->sig_hup = 0;
628
    pc->inState = PDIDLE;
629
    pc->inHead = NULL;
630
    pc->inTail = NULL;
631
    pc->inEscaped = 0;
632
#if VJ_SUPPORT
633
    pc->vjEnabled = 0;
634
#endif /* VJ_SUPPORT */
635
#endif /* PPPOS_SUPPORT */
636
    pc->ethif= ethif;
637
 
638
    memset(pc->inACCM,  0, sizeof(ext_accm));
639
    memset(pc->outACCM, 0, sizeof(ext_accm));
640
 
641
    pc->linkStatusCB  = linkStatusCB;
642
    pc->linkStatusCtx = linkStatusCtx;
643
 
644
    if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) {
645
      pc->openFlag = 0;
646
      return PPPERR_OPEN;
647
    }
648
 
649
    pppoe_connect(pc->pppoe_sc);
650
 
651
    if(!linkStatusCB) {
652
      while(pd >= 0 && !pc->if_up) {
653
        sys_msleep(500);
654
        if (lcp_phase[pd] == PHASE_DEAD) {
655
          pppClose(pd);
656
          if (pc->errCode) {
657
            pd = pc->errCode;
658
          } else {
659
            pd = PPPERR_CONNECT;
660
          }
661
        }
662
      }
663
    }
664
  }
665
 
666
  return pd;
667
}
668
#endif /* PPPOE_SUPPORT */
669
 
670
 
671
/* Close a PPP connection and release the descriptor.
672
 * Any outstanding packets in the queues are dropped.
673
 * Return 0 on success, an error code on failure. */
674
int
675
pppClose(int pd)
676
{
677
  PPPControl *pc = &pppControl[pd];
678
  int st = 0;
679
 
680
  /* Disconnect */
681
#if PPPOE_SUPPORT
682
  if(pc->ethif) {
683
    PPPDEBUG((LOG_DEBUG, "pppClose: unit %d kill_link -> pppStopCB\n", pd));
684
    pc->errCode = PPPERR_USER;
685
    /* This will leave us at PHASE_DEAD. */
686
    tcpip_callback(pppStopCB, (void*)pd);
687
  } else
688
#endif /* PPPOE_SUPPORT */
689
  {
690
#if PPPOS_SUPPORT
691
    pc->kill_link = !0;
692
    pppMainWakeup(pd);
693
#endif /* PPPOS_SUPPORT */
694
  }
695
 
696
  if(!pc->linkStatusCB) {
697
    while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
698
      sys_msleep(500);
699
      break;
700
    }
701
  }
702
 
703
  return st;
704
}
705
 
706
/* This function is called when carrier is lost on the PPP channel. */
707
void
708
pppSigHUP(int pd)
709
{
710
  PPPControl *pc = &pppControl[pd];
711
 
712
#if PPPOE_SUPPORT
713
  if(pc->ethif) {
714
    PPPDEBUG((LOG_DEBUG, "pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd));
715
    tcpip_callback(pppHupCB, (void*)pd);
716
  } else
717
#endif /* PPPOE_SUPPORT */
718
  {
719
#if PPPOS_SUPPORT
720
    pc->sig_hup = 1;
721
    pppMainWakeup(pd);
722
#endif /* PPPOS_SUPPORT */
723
  }
724
}
725
 
726
#if PPPOS_SUPPORT
727
static void
728
nPut(PPPControl *pc, struct pbuf *nb)
729
{
730
  struct pbuf *b;
731
  int c;
732
 
733
  for(b = nb; b != NULL; b = b->next) {
734
    if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
735
      PPPDEBUG((LOG_WARNING,
736
               "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
737
      LINK_STATS_INC(link.err);
738
      pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
739
      break;
740
    }
741
  }
742
 
743
  pbuf_free(nb);
744
  LINK_STATS_INC(link.xmit);
745
}
746
 
747
/*
748
 * pppAppend - append given character to end of given pbuf.  If outACCM
749
 * is not NULL and the character needs to be escaped, do so.
750
 * If pbuf is full, append another.
751
 * Return the current pbuf.
752
 */
753
static struct pbuf *
754
pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
755
{
756
  struct pbuf *tb = nb;
757
 
758
  /* Make sure there is room for the character and an escape code.
759
   * Sure we don't quite fill the buffer if the character doesn't
760
   * get escaped but is one character worth complicating this? */
761
  /* Note: We assume no packet header. */
762
  if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
763
    tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
764
    if (tb) {
765
      nb->next = tb;
766
    } else {
767
      LINK_STATS_INC(link.memerr);
768
    }
769
    nb = tb;
770
  }
771
 
772
  if (nb) {
773
    if (outACCM && ESCAPE_P(*outACCM, c)) {
774
      *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
775
      *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
776
    } else {
777
      *((u_char*)nb->payload + nb->len++) = c;
778
    }
779
  }
780
 
781
  return tb;
782
}
783
#endif /* PPPOS_SUPPORT */
784
 
785
#if PPPOE_SUPPORT
786
static err_t
787
pppifOutputOverEthernet(int pd, struct pbuf *p)
788
{
789
  PPPControl *pc = &pppControl[pd];
790
  struct pbuf *pb;
791
  u_short protocol = PPP_IP;
792
  int i=0;
793
 
794
  pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + sizeof(protocol), PBUF_RAM);
795
  if(!pb) {
796
    LINK_STATS_INC(link.memerr);
797
    LINK_STATS_INC(link.proterr);
798
    return ERR_MEM;
799
  }
800
 
801
  pbuf_header(pb, -pppoe_hdrlen);
802
 
803
  pc->lastXMit = sys_jiffies();
804
 
805
  if (!pc->pcomp || protocol > 0xFF) {
806
    *((u_char*)pb->payload + i++) = (protocol >> 8) & 0xFF;
807
  }
808
  *((u_char*)pb->payload + i) = protocol & 0xFF;
809
 
810
  pbuf_chain(pb, p);
811
 
812
  if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
813
    LINK_STATS_INC(link.err);
814
    return PPPERR_DEVICE;
815
  }
816
 
817
  LINK_STATS_INC(link.xmit);
818
  return ERR_OK;
819
}
820
#endif /* PPPOE_SUPPORT */
821
 
822
/* Send a packet on the given connection. */
823
static err_t
824
pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
825
{
826
  int pd = (int)netif->state;
827
  u_short protocol = PPP_IP;
828
  PPPControl *pc = &pppControl[pd];
829
#if PPPOS_SUPPORT
830
  u_int fcsOut = PPP_INITFCS;
831
  struct pbuf *headMB = NULL, *tailMB = NULL, *p;
832
  u_char c;
833
#endif /* PPPOS_SUPPORT */
834
 
835
  LWIP_UNUSED_ARG(ipaddr);
836
 
837
  /* Validate parameters. */
838
  /* We let any protocol value go through - it can't hurt us
839
   * and the peer will just drop it if it's not accepting it. */
840
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
841
    PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
842
              pd, protocol, pb));
843
    LINK_STATS_INC(link.opterr);
844
    LINK_STATS_INC(link.drop);
845
    return ERR_ARG;
846
  }
847
 
848
  /* Check that the link is up. */
849
  if (lcp_phase[pd] == PHASE_DEAD) {
850
    PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
851
    LINK_STATS_INC(link.rterr);
852
    LINK_STATS_INC(link.drop);
853
    return ERR_RTE;
854
  }
855
 
856
#if PPPOE_SUPPORT
857
  if(pc->ethif) {
858
    return pppifOutputOverEthernet(pd, pb);
859
  }
860
#endif /* PPPOE_SUPPORT */
861
 
862
#if PPPOS_SUPPORT
863
  /* Grab an output buffer. */
864
  headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
865
  if (headMB == NULL) {
866
    PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
867
    LINK_STATS_INC(link.memerr);
868
    LINK_STATS_INC(link.drop);
869
    return ERR_MEM;
870
  }
871
 
872
#if VJ_SUPPORT
873
  /*
874
   * Attempt Van Jacobson header compression if VJ is configured and
875
   * this is an IP packet.
876
   */
877
  if (protocol == PPP_IP && pc->vjEnabled) {
878
    switch (vj_compress_tcp(&pc->vjComp, pb)) {
879
      case TYPE_IP:
880
        /* No change...
881
           protocol = PPP_IP_PROTOCOL; */
882
        break;
883
      case TYPE_COMPRESSED_TCP:
884
        protocol = PPP_VJC_COMP;
885
        break;
886
      case TYPE_UNCOMPRESSED_TCP:
887
        protocol = PPP_VJC_UNCOMP;
888
        break;
889
      default:
890
        PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
891
        LINK_STATS_INC(link.proterr);
892
        LINK_STATS_INC(link.drop);
893
        pbuf_free(headMB);
894
        return ERR_VAL;
895
    }
896
  }
897
#endif /* VJ_SUPPORT */
898
 
899
  tailMB = headMB;
900
 
901
  /* Build the PPP header. */
902
  if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
903
    tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
904
  }
905
 
906
  pc->lastXMit = sys_jiffies();
907
  if (!pc->accomp) {
908
    fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
909
    tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
910
    fcsOut = PPP_FCS(fcsOut, PPP_UI);
911
    tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
912
  }
913
  if (!pc->pcomp || protocol > 0xFF) {
914
    c = (protocol >> 8) & 0xFF;
915
    fcsOut = PPP_FCS(fcsOut, c);
916
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
917
  }
918
  c = protocol & 0xFF;
919
  fcsOut = PPP_FCS(fcsOut, c);
920
  tailMB = pppAppend(c, tailMB, &pc->outACCM);
921
 
922
  /* Load packet. */
923
  for(p = pb; p; p = p->next) {
924
    int n;
925
    u_char *sPtr;
926
 
927
    sPtr = (u_char*)p->payload;
928
    n = p->len;
929
    while (n-- > 0) {
930
      c = *sPtr++;
931
 
932
      /* Update FCS before checking for special characters. */
933
      fcsOut = PPP_FCS(fcsOut, c);
934
 
935
      /* Copy to output buffer escaping special characters. */
936
      tailMB = pppAppend(c, tailMB, &pc->outACCM);
937
    }
938
  }
939
 
940
  /* Add FCS and trailing flag. */
941
  c = ~fcsOut & 0xFF;
942
  tailMB = pppAppend(c, tailMB, &pc->outACCM);
943
  c = (~fcsOut >> 8) & 0xFF;
944
  tailMB = pppAppend(c, tailMB, &pc->outACCM);
945
  tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
946
 
947
  /* If we failed to complete the packet, throw it away. */
948
  if (!tailMB) {
949
    PPPDEBUG((LOG_WARNING,
950
             "pppifOutput[%d]: Alloc err - dropping proto=%d\n",
951
              pd, protocol));
952
    pbuf_free(headMB);
953
    LINK_STATS_INC(link.memerr);
954
    LINK_STATS_INC(link.drop);
955
    return ERR_MEM;
956
  }
957
 
958
  /* Send it. */
959
  PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol));
960
 
961
  nPut(pc, headMB);
962
#endif /* PPPOS_SUPPORT */
963
 
964
  return ERR_OK;
965
}
966
 
967
/* Get and set parameters for the given connection.
968
 * Return 0 on success, an error code on failure. */
969
int
970
pppIOCtl(int pd, int cmd, void *arg)
971
{
972
  PPPControl *pc = &pppControl[pd];
973
  int st = 0;
974
 
975
  if (pd < 0 || pd >= NUM_PPP) {
976
    st = PPPERR_PARAM;
977
  } else {
978
    switch(cmd) {
979
    case PPPCTLG_UPSTATUS:      /* Get the PPP up status. */
980
      if (arg) {
981
        *(int *)arg = (int)(pc->if_up);
982
      } else {
983
        st = PPPERR_PARAM;
984
      }
985
      break;
986
    case PPPCTLS_ERRCODE:       /* Set the PPP error code. */
987
      if (arg) {
988
        pc->errCode = *(int *)arg;
989
      } else {
990
        st = PPPERR_PARAM;
991
      }
992
      break;
993
    case PPPCTLG_ERRCODE:       /* Get the PPP error code. */
994
      if (arg) {
995
        *(int *)arg = (int)(pc->errCode);
996
      } else {
997
        st = PPPERR_PARAM;
998
      }
999
      break;
1000
#if PPPOS_SUPPORT
1001
    case PPPCTLG_FD:
1002
      if (arg) {
1003
        *(sio_fd_t *)arg = pc->fd;
1004
      } else {
1005
        st = PPPERR_PARAM;
1006
      }
1007
      break;
1008
#endif /* PPPOS_SUPPORT */
1009
    default:
1010
      st = PPPERR_PARAM;
1011
      break;
1012
    }
1013
  }
1014
 
1015
  return st;
1016
}
1017
 
1018
/*
1019
 * Return the Maximum Transmission Unit for the given PPP connection.
1020
 */
1021
u_int
1022
pppMTU(int pd)
1023
{
1024
  PPPControl *pc = &pppControl[pd];
1025
  u_int st;
1026
 
1027
  /* Validate parameters. */
1028
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1029
    st = 0;
1030
  } else {
1031
    st = pc->mtu;
1032
  }
1033
 
1034
  return st;
1035
}
1036
 
1037
#if PPPOE_SUPPORT
1038
int
1039
pppWriteOverEthernet(int pd, const u_char *s, int n)
1040
{
1041
  PPPControl *pc = &pppControl[pd];
1042
  struct pbuf *pb;
1043
 
1044
  /* skip address & flags */
1045
  s += 2;
1046
  n -= 2;
1047
 
1048
  pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + n, PBUF_RAM);
1049
  if(!pb) {
1050
    LINK_STATS_INC(link.memerr);
1051
    LINK_STATS_INC(link.proterr);
1052
    return PPPERR_ALLOC;
1053
  }
1054
 
1055
  pbuf_header(pb, -pppoe_hdrlen);
1056
 
1057
  pc->lastXMit = sys_jiffies();
1058
 
1059
  SMEMCPY(pb->payload, s, n);
1060
 
1061
  if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) {
1062
    LINK_STATS_INC(link.err);
1063
    return PPPERR_DEVICE;
1064
  }
1065
 
1066
  LINK_STATS_INC(link.xmit);
1067
  return PPPERR_NONE;
1068
}
1069
#endif /* PPPOE_SUPPORT */
1070
 
1071
/*
1072
 * Write n characters to a ppp link.
1073
 *  RETURN: >= 0 Number of characters written
1074
 *           -1 Failed to write to device
1075
 */
1076
int
1077
pppWrite(int pd, const u_char *s, int n)
1078
{
1079
  PPPControl *pc = &pppControl[pd];
1080
#if PPPOS_SUPPORT
1081
  u_char c;
1082
  u_int fcsOut;
1083
  struct pbuf *headMB, *tailMB;
1084
#endif /* PPPOS_SUPPORT */
1085
 
1086
#if PPPOE_SUPPORT
1087
  if(pc->ethif) {
1088
    return pppWriteOverEthernet(pd, s, n);
1089
  }
1090
#endif /* PPPOE_SUPPORT */
1091
 
1092
#if PPPOS_SUPPORT
1093
  headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
1094
  if (headMB == NULL) {
1095
    LINK_STATS_INC(link.memerr);
1096
    LINK_STATS_INC(link.proterr);
1097
    return PPPERR_ALLOC;
1098
  }
1099
 
1100
  tailMB = headMB;
1101
 
1102
  /* If the link has been idle, we'll send a fresh flag character to
1103
   * flush any noise. */
1104
  if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG) {
1105
    tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
1106
  }
1107
  pc->lastXMit = sys_jiffies();
1108
 
1109
  fcsOut = PPP_INITFCS;
1110
  /* Load output buffer. */
1111
  while (n-- > 0) {
1112
    c = *s++;
1113
 
1114
    /* Update FCS before checking for special characters. */
1115
    fcsOut = PPP_FCS(fcsOut, c);
1116
 
1117
    /* Copy to output buffer escaping special characters. */
1118
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
1119
  }
1120
 
1121
  /* Add FCS and trailing flag. */
1122
  c = ~fcsOut & 0xFF;
1123
  tailMB = pppAppend(c, tailMB, &pc->outACCM);
1124
  c = (~fcsOut >> 8) & 0xFF;
1125
  tailMB = pppAppend(c, tailMB, &pc->outACCM);
1126
  tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
1127
 
1128
  /* If we failed to complete the packet, throw it away.
1129
   * Otherwise send it. */
1130
  if (!tailMB) {
1131
    PPPDEBUG((LOG_WARNING,
1132
             "pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
1133
           /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
1134
    pbuf_free(headMB);
1135
    LINK_STATS_INC(link.memerr);
1136
    LINK_STATS_INC(link.proterr);
1137
    return PPPERR_ALLOC;
1138
  }
1139
 
1140
  PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%d\n", pd, headMB->len));
1141
                   /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
1142
  nPut(pc, headMB);
1143
#endif /* PPPOS_SUPPORT */
1144
 
1145
  return PPPERR_NONE;
1146
}
1147
 
1148
/*
1149
 * ppp_send_config - configure the transmit characteristics of
1150
 * the ppp interface.
1151
 */
1152
void
1153
ppp_send_config( int unit, int mtu, u32_t asyncmap, int pcomp, int accomp)
1154
{
1155
  PPPControl *pc = &pppControl[unit];
1156
  int i;
1157
 
1158
  pc->mtu = mtu;
1159
  pc->pcomp = pcomp;
1160
  pc->accomp = accomp;
1161
 
1162
  /* Load the ACCM bits for the 32 control codes. */
1163
  for (i = 0; i < 32/8; i++) {
1164
    pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
1165
  }
1166
  PPPDEBUG((LOG_INFO, "ppp_send_config[%d]: outACCM=%X %X %X %X\n",
1167
            unit,
1168
            pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
1169
}
1170
 
1171
 
1172
/*
1173
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
1174
 */
1175
void
1176
ppp_set_xaccm(int unit, ext_accm *accm)
1177
{
1178
  SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm));
1179
  PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
1180
            unit,
1181
            pppControl[unit].outACCM[0],
1182
            pppControl[unit].outACCM[1],
1183
            pppControl[unit].outACCM[2],
1184
            pppControl[unit].outACCM[3]));
1185
}
1186
 
1187
 
1188
/*
1189
 * ppp_recv_config - configure the receive-side characteristics of
1190
 * the ppp interface.
1191
 */
1192
void
1193
ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp)
1194
{
1195
  PPPControl *pc = &pppControl[unit];
1196
  int i;
1197
 
1198
  LWIP_UNUSED_ARG(accomp);
1199
  LWIP_UNUSED_ARG(pcomp);
1200
  LWIP_UNUSED_ARG(mru);
1201
 
1202
  /* Load the ACCM bits for the 32 control codes. */
1203
  for (i = 0; i < 32 / 8; i++) {
1204
    pc->inACCM[i] = (u_char)(asyncmap >> (i * 8));
1205
  }
1206
  PPPDEBUG((LOG_INFO, "ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
1207
            unit,
1208
            pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
1209
}
1210
 
1211
#if 0
1212
/*
1213
 * ccp_test - ask kernel whether a given compression method
1214
 * is acceptable for use.  Returns 1 if the method and parameters
1215
 * are OK, 0 if the method is known but the parameters are not OK
1216
 * (e.g. code size should be reduced), or -1 if the method is unknown.
1217
 */
1218
int
1219
ccp_test( int unit, int opt_len,  int for_transmit, u_char *opt_ptr)
1220
{
1221
  return 0; /* XXX Currently no compression. */
1222
}
1223
 
1224
/*
1225
 * ccp_flags_set - inform kernel about the current state of CCP.
1226
 */
1227
void
1228
ccp_flags_set(int unit, int isopen, int isup)
1229
{
1230
  /* XXX */
1231
}
1232
 
1233
/*
1234
 * ccp_fatal_error - returns 1 if decompression was disabled as a
1235
 * result of an error detected after decompression of a packet,
1236
 * 0 otherwise.  This is necessary because of patent nonsense.
1237
 */
1238
int
1239
ccp_fatal_error(int unit)
1240
{
1241
  /* XXX */
1242
  return 0;
1243
}
1244
#endif
1245
 
1246
/*
1247
 * get_idle_time - return how long the link has been idle.
1248
 */
1249
int
1250
get_idle_time(int u, struct ppp_idle *ip)
1251
{
1252
  /* XXX */
1253
  LWIP_UNUSED_ARG(u);
1254
  LWIP_UNUSED_ARG(ip);
1255
 
1256
  return 0;
1257
}
1258
 
1259
 
1260
/*
1261
 * Return user specified netmask, modified by any mask we might determine
1262
 * for address `addr' (in network byte order).
1263
 * Here we scan through the system's list of interfaces, looking for
1264
 * any non-point-to-point interfaces which might appear to be on the same
1265
 * network as `addr'.  If we find any, we OR in their netmask to the
1266
 * user-specified netmask.
1267
 */
1268
u32_t
1269
GetMask(u32_t addr)
1270
{
1271
  u32_t mask, nmask;
1272
 
1273
  htonl(addr);
1274
  if (IN_CLASSA(addr)) { /* determine network mask for address class */
1275
    nmask = IN_CLASSA_NET;
1276
  } else if (IN_CLASSB(addr)) {
1277
    nmask = IN_CLASSB_NET;
1278
  } else {
1279
    nmask = IN_CLASSC_NET;
1280
  }
1281
 
1282
  /* class D nets are disallowed by bad_ip_adrs */
1283
  mask = subnetMask | htonl(nmask);
1284
 
1285
  /* XXX
1286
   * Scan through the system's network interfaces.
1287
   * Get each netmask and OR them into our mask.
1288
   */
1289
 
1290
  return mask;
1291
}
1292
 
1293
/*
1294
 * sifvjcomp - config tcp header compression
1295
 */
1296
int
1297
sifvjcomp( int pd, int vjcomp, int cidcomp, int maxcid)
1298
{
1299
#if PPPOS_SUPPORT && VJ_SUPPORT
1300
  PPPControl *pc = &pppControl[pd];
1301
 
1302
  pc->vjEnabled = vjcomp;
1303
  pc->vjComp.compressSlot = cidcomp;
1304
  pc->vjComp.maxSlotIndex = maxcid;
1305
  PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
1306
            vjcomp, cidcomp, maxcid));
1307
#endif /* PPPOS_SUPPORT && VJ_SUPPORT */
1308
 
1309
  return 0;
1310
}
1311
 
1312
/*
1313
 * pppifNetifInit - netif init callback
1314
 */
1315
static err_t
1316
pppifNetifInit(struct netif *netif)
1317
{
1318
  netif->name[0] = 'p';
1319
  netif->name[1] = 'p';
1320
  netif->output = pppifOutput;
1321
  netif->mtu = pppMTU((int)netif->state);
1322
  return ERR_OK;
1323
}
1324
 
1325
 
1326
/*
1327
 * sifup - Config the interface up and enable IP packets to pass.
1328
 */
1329
int
1330
sifup(int pd)
1331
{
1332
  PPPControl *pc = &pppControl[pd];
1333
  int st = 1;
1334
 
1335
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1336
    st = 0;
1337
    PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1338
  } else {
1339
    netif_remove(&pc->netif);
1340
    if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
1341
      netif_set_up(&pc->netif);
1342
#if LWIP_DHCP
1343
      /* ugly workaround for storing a reference to the ppp related info*/
1344
      pc->netif.dhcp = (struct dhcp *) &pc->addrs;
1345
#endif /* LWIP_DHCP */
1346
      pc->if_up = 1;
1347
      pc->errCode = PPPERR_NONE;
1348
 
1349
      PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1350
      if(pc->linkStatusCB) {
1351
        pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
1352
      }
1353
    } else {
1354
      st = 0;
1355
      PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd));
1356
    }
1357
  }
1358
 
1359
  return st;
1360
}
1361
 
1362
/*
1363
 * sifnpmode - Set the mode for handling packets for a given NP.
1364
 */
1365
int
1366
sifnpmode(int u, int proto, enum NPmode mode)
1367
{
1368
  LWIP_UNUSED_ARG(u);
1369
  LWIP_UNUSED_ARG(proto);
1370
  LWIP_UNUSED_ARG(mode);
1371
  return 0;
1372
}
1373
 
1374
/*
1375
 * sifdown - Config the interface down and disable IP.
1376
 */
1377
int
1378
sifdown(int pd)
1379
{
1380
  PPPControl *pc = &pppControl[pd];
1381
  int st = 1;
1382
 
1383
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1384
    st = 0;
1385
    PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
1386
  } else {
1387
    pc->if_up = 0;
1388
    netif_remove(&pc->netif);
1389
    PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1390
    if(pc->linkStatusCB) {
1391
      pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
1392
    }
1393
  }
1394
  return st;
1395
}
1396
 
1397
/**
1398
 * sifaddr - Config the interface IP addresses and netmask.
1399
 * @param pd Interface unit ???
1400
 * @param o Our IP address ???
1401
 * @param h His IP address ???
1402
 * @param m IP subnet mask ???
1403
 * @param ns1 Primary DNS
1404
 * @param ns2 Secondary DNS
1405
 */
1406
int
1407
sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2)
1408
{
1409
  PPPControl *pc = &pppControl[pd];
1410
  int st = 1;
1411
 
1412
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1413
    st = 0;
1414
    PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1415
  } else {
1416
    SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o));
1417
    SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h));
1418
    SMEMCPY(&pc->addrs.netmask, &m, sizeof(m));
1419
    SMEMCPY(&pc->addrs.dns1, &ns1, sizeof(ns1));
1420
    SMEMCPY(&pc->addrs.dns2, &ns2, sizeof(ns2));
1421
  }
1422
  return st;
1423
}
1424
 
1425
/**
1426
 * cifaddr - Clear the interface IP addresses, and delete routes
1427
 * through the interface if possible.
1428
 * @param pd Interface unit ???
1429
 * @param o Our IP address ???
1430
 * @param h IP broadcast address ???
1431
 */
1432
int
1433
cifaddr( int pd, u32_t o, u32_t h)
1434
{
1435
  PPPControl *pc = &pppControl[pd];
1436
  int st = 1;
1437
 
1438
  LWIP_UNUSED_ARG(o);
1439
  LWIP_UNUSED_ARG(h);
1440
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1441
    st = 0;
1442
    PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1443
  } else {
1444
    IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
1445
    IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
1446
    IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
1447
    IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
1448
    IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
1449
  }
1450
  return st;
1451
}
1452
 
1453
/*
1454
 * sifdefaultroute - assign a default route through the address given.
1455
 */
1456
int
1457
sifdefaultroute(int pd, u32_t l, u32_t g)
1458
{
1459
  PPPControl *pc = &pppControl[pd];
1460
  int st = 1;
1461
 
1462
  LWIP_UNUSED_ARG(l);
1463
  LWIP_UNUSED_ARG(g);
1464
 
1465
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1466
    st = 0;
1467
    PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1468
  } else {
1469
    netif_set_default(&pc->netif);
1470
  }
1471
 
1472
  /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
1473
 
1474
  return st;
1475
}
1476
 
1477
/*
1478
 * cifdefaultroute - delete a default route through the address given.
1479
 */
1480
int
1481
cifdefaultroute(int pd, u32_t l, u32_t g)
1482
{
1483
  PPPControl *pc = &pppControl[pd];
1484
  int st = 1;
1485
 
1486
  LWIP_UNUSED_ARG(l);
1487
  LWIP_UNUSED_ARG(g);
1488
 
1489
  if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1490
    st = 0;
1491
    PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1492
  } else {
1493
    netif_set_default(NULL);
1494
  }
1495
 
1496
  return st;
1497
}
1498
 
1499
/**********************************/
1500
/*** LOCAL FUNCTION DEFINITIONS ***/
1501
/**********************************/
1502
 
1503
#if PPPOS_SUPPORT
1504
/* The main PPP process function.  This implements the state machine according
1505
 * to section 4 of RFC 1661: The Point-To-Point Protocol. */
1506
static void
1507
pppMain(void *arg)
1508
{
1509
  int pd = (int)arg;
1510
  struct pbuf *p;
1511
  PPPControl* pc;
1512
  int c;
1513
 
1514
  pc = &pppControl[pd];
1515
 
1516
  p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM);
1517
  if (!p) {
1518
    LWIP_ASSERT("p != NULL", p);
1519
    pc->errCode = PPPERR_ALLOC;
1520
    goto out;
1521
  }
1522
 
1523
  /*
1524
   * Start the connection and handle incoming events (packet or timeout).
1525
   */
1526
  PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
1527
  tcpip_callback(pppStartCB, arg);
1528
  while (lcp_phase[pd] != PHASE_DEAD) {
1529
    if (pc->kill_link) {
1530
      PPPDEBUG((LOG_DEBUG, "pppMain: unit %d kill_link -> pppStopCB\n", pd));
1531
      pc->errCode = PPPERR_USER;
1532
      /* This will leave us at PHASE_DEAD. */
1533
      tcpip_callback(pppStopCB, arg);
1534
      pc->kill_link = 0;
1535
    } else if (pc->sig_hup) {
1536
      PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sig_hup -> pppHupCB\n", pd));
1537
      pc->sig_hup = 0;
1538
      tcpip_callback(pppHupCB, arg);
1539
    } else {
1540
      c = sio_read(pc->fd, p->payload, p->len);
1541
      if(c > 0) {
1542
        pppInProc(pd, p->payload, c);
1543
      } else {
1544
        PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
1545
        sys_msleep(1); /* give other tasks a chance to run */
1546
      }
1547
    }
1548
  }
1549
  PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd));
1550
  pppDrop(pc); /* bug fix #17726 */
1551
  pbuf_free(p);
1552
 
1553
out:
1554
  PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1555
  if(pc->linkStatusCB) {
1556
    pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
1557
  }
1558
 
1559
  pc->openFlag = 0;
1560
}
1561
#endif /* PPPOS_SUPPORT */
1562
 
1563
#if PPPOE_SUPPORT
1564
 
1565
void
1566
pppOverEthernetInitFailed(void* arg)
1567
{
1568
  PPPControl* pc;
1569
  int pd = (int)arg;
1570
 
1571
  pppHupCB(arg);
1572
  pppStopCB(arg);
1573
 
1574
  pc = &pppControl[pd];
1575
  pppoe_destroy(&pc->netif);
1576
  pc->openFlag = 0;
1577
 
1578
  if(pc->linkStatusCB) {
1579
    pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
1580
  }
1581
}
1582
 
1583
static void
1584
pppOverEthernetLinkStatusCB(int pd, int up)
1585
{
1586
  if(up) {
1587
    PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
1588
    tcpip_callback(pppStartCB, (void*)pd);
1589
  } else {
1590
    PPPControl* pc;
1591
    pc = &pppControl[pd];
1592
    tcpip_callback(pppOverEthernetInitFailed, (void*)pd);
1593
  }
1594
}
1595
#endif /* PPPOE_SUPPORT */
1596
 
1597
struct pbuf *
1598
pppSingleBuf(struct pbuf *p)
1599
{
1600
  struct pbuf *q, *b;
1601
  u_char *pl;
1602
 
1603
  if(p->tot_len == p->len) {
1604
    return p;
1605
  }
1606
 
1607
  q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
1608
  if(!q) {
1609
    PPPDEBUG((LOG_ERR,
1610
             "pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
1611
    return p; /* live dangerously */
1612
  }
1613
 
1614
  for(b = p, pl = q->payload; b != NULL; b = b->next) {
1615
    MEMCPY(pl, b->payload, b->len);
1616
    pl += b->len;
1617
  }
1618
 
1619
  pbuf_free(p);
1620
 
1621
  return q;
1622
}
1623
 
1624
struct pppInputHeader {
1625
  int unit;
1626
  u16_t proto;
1627
};
1628
 
1629
/*
1630
 * Pass the processed input packet to the appropriate handler.
1631
 * This function and all handlers run in the context of the tcpip_thread
1632
 */
1633
static void
1634
pppInput(void *arg)
1635
{
1636
  struct pbuf *nb = (struct pbuf *)arg;
1637
  u16_t protocol;
1638
  int pd;
1639
 
1640
  pd = ((struct pppInputHeader *)nb->payload)->unit;
1641
  protocol = ((struct pppInputHeader *)nb->payload)->proto;
1642
 
1643
  if(pbuf_header(nb, -(int)sizeof(struct pppInputHeader))) {
1644
    LWIP_ASSERT("pbuf_header failed\n", 0);
1645
    goto drop;
1646
  }
1647
 
1648
  LINK_STATS_INC(link.recv);
1649
 
1650
  /*
1651
   * Toss all non-LCP packets unless LCP is OPEN.
1652
   * Until we get past the authentication phase, toss all packets
1653
   * except LCP, LQR and authentication packets.
1654
   */
1655
  if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
1656
    if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
1657
        (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
1658
      PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %d\n", protocol, lcp_phase[pd]));
1659
      goto drop;
1660
    }
1661
  }
1662
 
1663
  switch(protocol) {
1664
    case PPP_VJC_COMP:      /* VJ compressed TCP */
1665
#if VJ_SUPPORT
1666
      PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
1667
      /*
1668
       * Clip off the VJ header and prepend the rebuilt TCP/IP header and
1669
       * pass the result to IP.
1670
       */
1671
      if ((vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) && (pppControl[pd].netif.input)) {
1672
        pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1673
        return;
1674
      }
1675
      /* Something's wrong so drop it. */
1676
      PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd));
1677
#else  /* VJ_SUPPORT */
1678
      /* No handler for this protocol so drop the packet. */
1679
      PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
1680
#endif /* VJ_SUPPORT */
1681
      break;
1682
 
1683
    case PPP_VJC_UNCOMP:    /* VJ uncompressed TCP */
1684
#if VJ_SUPPORT
1685
      PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
1686
      /*
1687
       * Process the TCP/IP header for VJ header compression and then pass
1688
       * the packet to IP.
1689
       */
1690
      if ((vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) && pppControl[pd].netif.input) {
1691
        pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1692
        return;
1693
      }
1694
      /* Something's wrong so drop it. */
1695
      PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd));
1696
#else  /* VJ_SUPPORT */
1697
      /* No handler for this protocol so drop the packet. */
1698
      PPPDEBUG((LOG_INFO,
1699
               "pppInput[%d]: drop VJ UnComp in %d:.*H\n",
1700
                pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
1701
#endif /* VJ_SUPPORT */
1702
      break;
1703
 
1704
    case PPP_IP:            /* Internet Protocol */
1705
      PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
1706
      if (pppControl[pd].netif.input) {
1707
        pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1708
        return;
1709
      }
1710
      break;
1711
 
1712
    default: {
1713
      struct protent *protp;
1714
      int i;
1715
 
1716
      /*
1717
       * Upcall the proper protocol input routine.
1718
       */
1719
      for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
1720
        if (protp->protocol == protocol && protp->enabled_flag) {
1721
          PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
1722
          nb = pppSingleBuf(nb);
1723
          (*protp->input)(pd, nb->payload, nb->len);
1724
          goto out;
1725
        }
1726
      }
1727
 
1728
      /* No handler for this protocol so reject the packet. */
1729
      PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%d\n", pd, protocol, nb->len));
1730
      if (pbuf_header(nb, sizeof(protocol))) {
1731
        LWIP_ASSERT("pbuf_header failed\n", 0);
1732
        goto drop;
1733
      }
1734
#if BYTE_ORDER == LITTLE_ENDIAN
1735
      protocol = htons(protocol);
1736
      SMEMCPY(nb->payload, &protocol, sizeof(protocol));
1737
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
1738
      lcp_sprotrej(pd, nb->payload, nb->len);
1739
    }
1740
    break;
1741
  }
1742
 
1743
drop:
1744
  LINK_STATS_INC(link.drop);
1745
 
1746
out:
1747
  pbuf_free(nb);
1748
  return;
1749
}
1750
 
1751
#if PPPOS_SUPPORT
1752
/*
1753
 * Drop the input packet.
1754
 */
1755
static void
1756
pppDrop(PPPControl *pc)
1757
{
1758
  if (pc->inHead != NULL) {
1759
#if 0
1760
    PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
1761
#endif
1762
    PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len));
1763
    if (pc->inTail && (pc->inTail != pc->inHead)) {
1764
      pbuf_free(pc->inTail);
1765
    }
1766
    pbuf_free(pc->inHead);
1767
    pc->inHead = NULL;
1768
    pc->inTail = NULL;
1769
  }
1770
#if VJ_SUPPORT
1771
  vj_uncompress_err(&pc->vjComp);
1772
#endif /* VJ_SUPPORT */
1773
 
1774
  LINK_STATS_INC(link.drop);
1775
}
1776
 
1777
/**
1778
 * Process a received octet string.
1779
 */
1780
static void
1781
pppInProc(int pd, u_char *s, int l)
1782
{
1783
  PPPControl *pc = &pppControl[pd];
1784
  struct pbuf *nextNBuf;
1785
  u_char curChar;
1786
 
1787
  PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytes\n", pd, l));
1788
  while (l-- > 0) {
1789
    curChar = *s++;
1790
 
1791
    /* Handle special characters. */
1792
    if (ESCAPE_P(pc->inACCM, curChar)) {
1793
      /* Check for escape sequences. */
1794
      /* XXX Note that this does not handle an escaped 0x5d character which
1795
       * would appear as an escape character.  Since this is an ASCII ']'
1796
       * and there is no reason that I know of to escape it, I won't complicate
1797
       * the code to handle this case. GLL */
1798
      if (curChar == PPP_ESCAPE) {
1799
        pc->inEscaped = 1;
1800
      /* Check for the flag character. */
1801
      } else if (curChar == PPP_FLAG) {
1802
         /* If this is just an extra flag character, ignore it. */
1803
         if (pc->inState <= PDADDRESS) {
1804
           /* ignore it */;
1805
         /* If we haven't received the packet header, drop what has come in. */
1806
         } else if (pc->inState < PDDATA) {
1807
           PPPDEBUG((LOG_WARNING,
1808
                    "pppInProc[%d]: Dropping incomplete packet %d\n",
1809
                     pd, pc->inState));
1810
           LINK_STATS_INC(link.lenerr);
1811
           pppDrop(pc);
1812
         /* If the fcs is invalid, drop the packet. */
1813
         } else if (pc->inFCS != PPP_GOODFCS) {
1814
           PPPDEBUG((LOG_INFO,
1815
                    "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
1816
                     pd, pc->inFCS, pc->inProtocol));
1817
           LINK_STATS_INC(link.chkerr);
1818
           pppDrop(pc);
1819
         /* Otherwise it's a good packet so pass it on. */
1820
         } else {
1821
           /* Trim off the checksum. */
1822
           if(pc->inTail->len >= 2) {
1823
             pc->inTail->len -= 2;
1824
 
1825
             pc->inTail->tot_len = pc->inTail->len;
1826
             if (pc->inTail != pc->inHead) {
1827
               pbuf_cat(pc->inHead, pc->inTail);
1828
             }
1829
           } else {
1830
             pc->inTail->tot_len = pc->inTail->len;
1831
             if (pc->inTail != pc->inHead) {
1832
               pbuf_cat(pc->inHead, pc->inTail);
1833
             }
1834
 
1835
             pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
1836
           }
1837
 
1838
           /* Dispatch the packet thereby consuming it. */
1839
           if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
1840
             PPPDEBUG((LOG_ERR, "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
1841
             pbuf_free(pc->inHead);
1842
             LINK_STATS_INC(link.drop);
1843
           }
1844
           pc->inHead = NULL;
1845
           pc->inTail = NULL;
1846
         }
1847
 
1848
         /* Prepare for a new packet. */
1849
         pc->inFCS = PPP_INITFCS;
1850
         pc->inState = PDADDRESS;
1851
         pc->inEscaped = 0;
1852
      /* Other characters are usually control characters that may have
1853
       * been inserted by the physical layer so here we just drop them. */
1854
      } else {
1855
        PPPDEBUG((LOG_WARNING,
1856
                 "pppInProc[%d]: Dropping ACCM char <%d>\n", pd, curChar));
1857
      }
1858
    /* Process other characters. */
1859
    } else {
1860
      /* Unencode escaped characters. */
1861
      if (pc->inEscaped) {
1862
        pc->inEscaped = 0;
1863
        curChar ^= PPP_TRANS;
1864
      }
1865
 
1866
      /* Process character relative to current state. */
1867
      switch(pc->inState) {
1868
        case PDIDLE:                    /* Idle state - waiting. */
1869
          /* Drop the character if it's not 0xff
1870
           * we would have processed a flag character above. */
1871
          if (curChar != PPP_ALLSTATIONS) {
1872
            break;
1873
          }
1874
 
1875
        /* Fall through */
1876
        case PDSTART:                   /* Process start flag. */
1877
          /* Prepare for a new packet. */
1878
          pc->inFCS = PPP_INITFCS;
1879
 
1880
        /* Fall through */
1881
        case PDADDRESS:                 /* Process address field. */
1882
          if (curChar == PPP_ALLSTATIONS) {
1883
            pc->inState = PDCONTROL;
1884
            break;
1885
          }
1886
          /* Else assume compressed address and control fields so
1887
           * fall through to get the protocol... */
1888
        case PDCONTROL:                 /* Process control field. */
1889
          /* If we don't get a valid control code, restart. */
1890
          if (curChar == PPP_UI) {
1891
            pc->inState = PDPROTOCOL1;
1892
            break;
1893
          }
1894
#if 0
1895
          else {
1896
            PPPDEBUG((LOG_WARNING,
1897
                     "pppInProc[%d]: Invalid control <%d>\n", pd, curChar));
1898
                      pc->inState = PDSTART;
1899
          }
1900
#endif
1901
        case PDPROTOCOL1:               /* Process protocol field 1. */
1902
          /* If the lower bit is set, this is the end of the protocol
1903
           * field. */
1904
          if (curChar & 1) {
1905
            pc->inProtocol = curChar;
1906
            pc->inState = PDDATA;
1907
          } else {
1908
            pc->inProtocol = (u_int)curChar << 8;
1909
            pc->inState = PDPROTOCOL2;
1910
          }
1911
          break;
1912
        case PDPROTOCOL2:               /* Process protocol field 2. */
1913
          pc->inProtocol |= curChar;
1914
          pc->inState = PDDATA;
1915
          break;
1916
        case PDDATA:                    /* Process data byte. */
1917
          /* Make space to receive processed data. */
1918
          if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) {
1919
            if(pc->inTail) {
1920
              pc->inTail->tot_len = pc->inTail->len;
1921
              if (pc->inTail != pc->inHead) {
1922
                pbuf_cat(pc->inHead, pc->inTail);
1923
              }
1924
            }
1925
            /* If we haven't started a packet, we need a packet header. */
1926
            nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
1927
            if (nextNBuf == NULL) {
1928
              /* No free buffers.  Drop the input packet and let the
1929
               * higher layers deal with it.  Continue processing
1930
               * the received pbuf chain in case a new packet starts. */
1931
              PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
1932
              LINK_STATS_INC(link.memerr);
1933
              pppDrop(pc);
1934
              pc->inState = PDSTART;  /* Wait for flag sequence. */
1935
              break;
1936
            }
1937
            if (pc->inHead == NULL) {
1938
              struct pppInputHeader *pih = nextNBuf->payload;
1939
 
1940
              pih->unit = pd;
1941
              pih->proto = pc->inProtocol;
1942
 
1943
              nextNBuf->len += sizeof(*pih);
1944
 
1945
              pc->inHead = nextNBuf;
1946
            }
1947
            pc->inTail = nextNBuf;
1948
          }
1949
          /* Load character into buffer. */
1950
          ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
1951
          break;
1952
      }
1953
 
1954
      /* update the frame check sequence number. */
1955
      pc->inFCS = PPP_FCS(pc->inFCS, curChar);
1956
    }
1957
  }
1958
 
1959
  avRandomize();
1960
}
1961
#endif /* PPPOS_SUPPORT */
1962
 
1963
#if PPPOE_SUPPORT
1964
void
1965
pppInProcOverEthernet(int pd, struct pbuf *pb)
1966
{
1967
  struct pppInputHeader *pih;
1968
  u16_t inProtocol;
1969
 
1970
  if(pb->len < sizeof(inProtocol)) {
1971
    PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: too small for protocol field\n"));
1972
    goto drop;
1973
  }
1974
 
1975
  inProtocol = (((u8_t *)pb->payload)[0] << 8) | ((u8_t*)pb->payload)[1];
1976
 
1977
  /* make room for pppInputHeader - should not fail */
1978
  if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) {
1979
    PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: could not allocate room for header\n"));
1980
    goto drop;
1981
  }
1982
 
1983
  pih = pb->payload;
1984
 
1985
  pih->unit = pd;
1986
  pih->proto = inProtocol;
1987
 
1988
  /* Dispatch the packet thereby consuming it. */
1989
  if(tcpip_callback(pppInput, pb) != ERR_OK) {
1990
    PPPDEBUG((LOG_ERR, "pppInProcOverEthernet[%d]: tcpip_callback() failed, dropping packet\n", pd));
1991
    goto drop;
1992
  }
1993
 
1994
  return;
1995
 
1996
drop:
1997
  LINK_STATS_INC(link.drop);
1998
  pbuf_free(pb);
1999
  return;
2000
}
2001
#endif /* PPPOE_SUPPORT */
2002
 
2003
#endif /* PPP_SUPPORT */

powered by: WebSVN 2.1.0

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