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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [lwip_tcpip/] [current/] [src/] [netif/] [ppp/] [ppp.c] - Blame information for rev 865

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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