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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [Common/] [ethernet/] [lwIP/] [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 <string.h>
83
 
84
#include "ppp.h"
85
#if PPP_SUPPORT > 0
86
#include "randm.h"
87
#include "fsm.h"
88
#if PAP_SUPPORT > 0
89
#include "pap.h"
90
#endif
91
#if CHAP_SUPPORT > 0
92
#include "chap.h"
93
#endif
94
#include "ipcp.h"
95
#include "lcp.h"
96
#include "magic.h"
97
#include "auth.h"
98
#if VJ_SUPPORT > 0
99
#include "vj.h"
100
#endif
101
 
102
#include "pppdebug.h"
103
 
104
/*************************/
105
/*** LOCAL DEFINITIONS ***/
106
/*************************/
107
 
108
/*
109
 * The basic PPP frame.
110
 */
111
#define PPP_ADDRESS(p)  (((u_char *)(p))[0])
112
#define PPP_CONTROL(p)  (((u_char *)(p))[1])
113
#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
114
 
115
/* PPP packet parser states.  Current state indicates operation yet to be
116
 * completed. */
117
typedef enum {
118
    PDIDLE = 0,                 /* Idle state - waiting. */
119
    PDSTART,                    /* Process start flag. */
120
    PDADDRESS,                  /* Process address field. */
121
    PDCONTROL,                  /* Process control field. */
122
    PDPROTOCOL1,                /* Process protocol field 1. */
123
    PDPROTOCOL2,                /* Process protocol field 2. */
124
    PDDATA                      /* Process data byte. */
125
} PPPDevStates;
126
 
127
#define ESCAPE_P(accm, c) ((accm)[(c) >> 3] & pppACCMMask[c & 0x07])
128
 
129
/************************/
130
/*** LOCAL DATA TYPES ***/
131
/************************/
132
/*
133
 * PPP interface control block.
134
 */
135
typedef struct PPPControl_s {
136
    char openFlag;                      /* True when in use. */
137
    char oldFrame;                      /* Old framing character for fd. */
138
    sio_fd_t fd;                    /* File device ID of port. */
139
    int  kill_link;                     /* Shut the link down. */
140
    int  sig_hup;                       /* Carrier lost. */
141
    int  if_up;                         /* True when the interface is up. */
142
    int  errCode;                       /* Code indicating why interface is down. */
143
    struct pbuf *inHead, *inTail;       /* The input packet. */
144
    PPPDevStates inState;               /* The input process state. */
145
    char inEscaped;                     /* Escape next character. */
146
    u16_t inProtocol;                   /* The input protocol code. */
147
    u16_t inFCS;                        /* Input Frame Check Sequence value. */
148
    int  mtu;                           /* Peer's mru */
149
    int  pcomp;                         /* Does peer accept protocol compression? */
150
    int  accomp;                        /* Does peer accept addr/ctl compression? */
151
    u_long lastXMit;                    /* Time of last transmission. */
152
    ext_accm inACCM;                    /* Async-Ctl-Char-Map for input. */
153
    ext_accm outACCM;                   /* Async-Ctl-Char-Map for output. */
154
#if VJ_SUPPORT > 0
155
    int  vjEnabled;                     /* Flag indicating VJ compression enabled. */
156
    struct vjcompress vjComp;           /* Van Jabobsen compression header. */
157
#endif
158
 
159
    struct netif netif;
160
 
161
    struct ppp_addrs addrs;
162
 
163
    void (*linkStatusCB)(void *ctx, int errCode, void *arg);
164
    void *linkStatusCtx;
165
 
166
} PPPControl;
167
 
168
 
169
/*
170
 * Ioctl definitions.
171
 */
172
 
173
struct npioctl {
174
    int     protocol;           /* PPP procotol, e.g. PPP_IP */
175
    enum NPmode mode;
176
};
177
 
178
 
179
 
180
/***********************************/
181
/*** LOCAL FUNCTION DECLARATIONS ***/
182
/***********************************/
183
static void pppMain(void *pd);
184
static void pppDrop(PPPControl *pc);
185
static void pppInProc(int pd, u_char *s, int l);
186
 
187
 
188
/******************************/
189
/*** PUBLIC DATA STRUCTURES ***/
190
/******************************/
191
u_long subnetMask;
192
 
193
static PPPControl pppControl[NUM_PPP]; /* The PPP interface control blocks. */
194
 
195
/*
196
 * PPP Data Link Layer "protocol" table.
197
 * One entry per supported protocol.
198
 * The last entry must be NULL.
199
 */
200
struct protent *ppp_protocols[] = {
201
    &lcp_protent,
202
#if PAP_SUPPORT > 0
203
    &pap_protent,
204
#endif
205
#if CHAP_SUPPORT > 0
206
    &chap_protent,
207
#endif
208
#if CBCP_SUPPORT > 0
209
    &cbcp_protent,
210
#endif
211
    &ipcp_protent,
212
#if CCP_SUPPORT > 0
213
    &ccp_protent,
214
#endif
215
    NULL
216
};
217
 
218
 
219
/*
220
 * Buffers for outgoing packets.  This must be accessed only from the appropriate
221
 * PPP task so that it doesn't need to be protected to avoid collisions.
222
 */
223
u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN];
224
 
225
 
226
/*****************************/
227
/*** LOCAL DATA STRUCTURES ***/
228
/*****************************/
229
 
230
/*
231
 * FCS lookup table as calculated by genfcstab.
232
 */
233
static const u_short fcstab[256] = {
234
    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
235
    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
236
    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
237
    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
238
    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
239
    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
240
    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
241
    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
242
    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
243
    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
244
    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
245
    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
246
    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
247
    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
248
    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
249
    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
250
    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
251
    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
252
    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
253
    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
254
    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
255
    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
256
    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
257
    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
258
    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
259
    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
260
    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
261
    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
262
    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
263
    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
264
    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
265
    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
266
};
267
 
268
/* PPP's Asynchronous-Control-Character-Map.  The mask array is used
269
 * to select the specific bit for a character. */
270
static u_char pppACCMMask[] = {
271
    0x01,
272
    0x02,
273
    0x04,
274
    0x08,
275
    0x10,
276
    0x20,
277
    0x40,
278
    0x80
279
};
280
 
281
 
282
/***********************************/
283
/*** PUBLIC FUNCTION DEFINITIONS ***/
284
/***********************************/
285
/* Initialize the PPP subsystem. */
286
 
287
struct ppp_settings ppp_settings;
288
 
289
void pppInit(void)
290
{
291
    struct protent *protp;
292
    int i, j;
293
 
294
        memset(&ppp_settings, 0, sizeof(ppp_settings));
295
        ppp_settings.usepeerdns = 1;
296
        pppSetAuth(PPPAUTHTYPE_NONE, NULL, NULL);
297
 
298
        magicInit();
299
 
300
    for (i = 0; i < NUM_PPP; i++) {
301
        pppControl[i].openFlag = 0;
302
 
303
                subnetMask = htonl(0xffffff00);
304
 
305
        /*
306
         * Initialize to the standard option set.
307
         */
308
        for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j)
309
            (*protp->init)(i);
310
    }
311
 
312
#if LINK_STATS
313
    /* Clear the statistics. */
314
    memset(&lwip_stats.link, 0, sizeof(lwip_stats.link));
315
#endif
316
}
317
 
318
void pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd)
319
{
320
    switch(authType) {
321
        case PPPAUTHTYPE_NONE:
322
        default:
323
#ifdef LWIP_PPP_STRICT_PAP_REJECT
324
            ppp_settings.refuse_pap = 1;
325
#else
326
            /* some providers request pap and accept an empty login/pw */
327
            ppp_settings.refuse_pap = 0;
328
#endif
329
            ppp_settings.refuse_chap = 1;
330
            break;
331
        case PPPAUTHTYPE_ANY:
332
/* Warning: Using PPPAUTHTYPE_ANY might have security consequences.
333
 * RFC 1994 says:
334
 *
335
 * In practice, within or associated with each PPP server, there is a
336
 * database which associates "user" names with authentication
337
 * information ("secrets").  It is not anticipated that a particular
338
 * named user would be authenticated by multiple methods.  This would
339
 * make the user vulnerable to attacks which negotiate the least secure
340
 * method from among a set (such as PAP rather than CHAP).  If the same
341
 * secret was used, PAP would reveal the secret to be used later with
342
 * CHAP.
343
 *
344
 * Instead, for each user name there should be an indication of exactly
345
 * one method used to authenticate that user name.  If a user needs to
346
 * make use of different authentication methods under different
347
 * circumstances, then distinct user names SHOULD be employed, each of
348
 * which identifies exactly one authentication method.
349
 *
350
 */
351
            ppp_settings.refuse_pap = 0;
352
            ppp_settings.refuse_chap = 0;
353
            break;
354
        case PPPAUTHTYPE_PAP:
355
            ppp_settings.refuse_pap = 0;
356
            ppp_settings.refuse_chap = 1;
357
            break;
358
        case PPPAUTHTYPE_CHAP:
359
            ppp_settings.refuse_pap = 1;
360
            ppp_settings.refuse_chap = 0;
361
            break;
362
    }
363
 
364
    if(user) {
365
        strncpy(ppp_settings.user, user, sizeof(ppp_settings.user)-1);
366
        ppp_settings.user[sizeof(ppp_settings.user)-1] = '\0';
367
    } else
368
        ppp_settings.user[0] = '\0';
369
 
370
    if(passwd) {
371
        strncpy(ppp_settings.passwd, passwd, sizeof(ppp_settings.passwd)-1);
372
        ppp_settings.passwd[sizeof(ppp_settings.passwd)-1] = '\0';
373
    } else
374
        ppp_settings.passwd[0] = '\0';
375
}
376
 
377
/* Open a new PPP connection using the given I/O device.
378
 * This initializes the PPP control block but does not
379
 * attempt to negotiate the LCP session.  If this port
380
 * connects to a modem, the modem connection must be
381
 * established before calling this.
382
 * Return a new PPP connection descriptor on success or
383
 * an error code (negative) on failure. */
384
int pppOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx)
385
{
386
    PPPControl *pc;
387
    int pd;
388
 
389
    /* Find a free PPP session descriptor. Critical region? */
390
    for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++);
391
    if (pd >= NUM_PPP)
392
        pd = PPPERR_OPEN;
393
    else
394
        pppControl[pd].openFlag = !0;
395
 
396
    /* Launch a deamon thread. */
397
    if (pd >= 0) {
398
 
399
        pppControl[pd].openFlag = 1;
400
 
401
        lcp_init(pd);
402
        pc = &pppControl[pd];
403
        pc->fd = fd;
404
        pc->kill_link = 0;
405
        pc->sig_hup = 0;
406
        pc->if_up = 0;
407
        pc->errCode = 0;
408
        pc->inState = PDIDLE;
409
        pc->inHead = NULL;
410
        pc->inTail = NULL;
411
        pc->inEscaped = 0;
412
        pc->lastXMit = 0;
413
 
414
#if VJ_SUPPORT > 0
415
        pc->vjEnabled = 0;
416
        vj_compress_init(&pc->vjComp);
417
#endif
418
 
419
        /*
420
         * Default the in and out accm so that escape and flag characters
421
         * are always escaped.
422
         */
423
        memset(pc->inACCM, 0, sizeof(ext_accm));
424
        pc->inACCM[15] = 0x60;
425
        memset(pc->outACCM, 0, sizeof(ext_accm));
426
        pc->outACCM[15] = 0x60;
427
 
428
        pc->linkStatusCB = linkStatusCB;
429
        pc->linkStatusCtx = linkStatusCtx;
430
 
431
        sys_thread_new(pppMain, (void*)pd, PPP_THREAD_PRIO);
432
        if(!linkStatusCB) {
433
                while(pd >= 0 && !pc->if_up) {
434
                        sys_msleep(500);
435
                        if (lcp_phase[pd] == PHASE_DEAD) {
436
                                pppClose(pd);
437
                                if (pc->errCode)
438
                                        pd = pc->errCode;
439
                                else
440
                                        pd = PPPERR_CONNECT;
441
                        }
442
                }
443
        }
444
    }
445
    return pd;
446
}
447
 
448
/* Close a PPP connection and release the descriptor.
449
 * Any outstanding packets in the queues are dropped.
450
 * Return 0 on success, an error code on failure. */
451
int pppClose(int pd)
452
{
453
    PPPControl *pc = &pppControl[pd];
454
    int st = 0;
455
 
456
    /* Disconnect */
457
    pc->kill_link = !0;
458
    pppMainWakeup(pd);
459
 
460
    if(!pc->linkStatusCB) {
461
            while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) {
462
                    sys_msleep(500);
463
                    break;
464
            }
465
    }
466
    return st;
467
}
468
 
469
/* This function is called when carrier is lost on the PPP channel. */
470
void pppSigHUP(int pd)
471
{
472
    PPPControl *pc = &pppControl[pd];
473
 
474
    pc->sig_hup = 1;
475
    pppMainWakeup(pd);
476
}
477
 
478
static void nPut(PPPControl *pc, struct pbuf *nb)
479
{
480
        struct pbuf *b;
481
        int c;
482
 
483
        for(b = nb; b != NULL; b = b->next) {
484
            if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) {
485
                PPPDEBUG((LOG_WARNING,
486
                            "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c));
487
#if LINK_STATS
488
                lwip_stats.link.err++;
489
#endif /* LINK_STATS */
490
                pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */
491
                break;
492
            }
493
        }
494
        pbuf_free(nb);
495
 
496
#if LINK_STATS
497
        lwip_stats.link.xmit++;
498
#endif /* LINK_STATS */
499
}
500
 
501
/*
502
 * pppAppend - append given character to end of given pbuf.  If outACCM
503
 * is not NULL and the character needs to be escaped, do so.
504
 * If pbuf is full, append another.
505
 * Return the current pbuf.
506
 */
507
static struct pbuf *pppAppend(u_char c, struct pbuf *nb, ext_accm *outACCM)
508
{
509
    struct pbuf *tb = nb;
510
 
511
    /* Make sure there is room for the character and an escape code.
512
     * Sure we don't quite fill the buffer if the character doesn't
513
     * get escaped but is one character worth complicating this? */
514
    /* Note: We assume no packet header. */
515
    if (nb && (PBUF_POOL_BUFSIZE - nb->len) < 2) {
516
        tb = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
517
        if (tb) {
518
            nb->next = tb;
519
        }
520
#if LINK_STATS
521
        else {
522
            lwip_stats.link.memerr++;
523
        }
524
#endif /* LINK_STATS */
525
        nb = tb;
526
    }
527
    if (nb) {
528
        if (outACCM && ESCAPE_P(*outACCM, c)) {
529
            *((u_char*)nb->payload + nb->len++) = PPP_ESCAPE;
530
            *((u_char*)nb->payload + nb->len++) = c ^ PPP_TRANS;
531
        }
532
        else
533
            *((u_char*)nb->payload + nb->len++) = c;
534
    }
535
 
536
    return tb;
537
}
538
 
539
/* Send a packet on the given connection. */
540
static err_t pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr)
541
{
542
    int pd = (int)netif->state;
543
    u_short protocol = PPP_IP;
544
    PPPControl *pc = &pppControl[pd];
545
    u_int fcsOut = PPP_INITFCS;
546
    struct pbuf *headMB = NULL, *tailMB = NULL, *p;
547
    u_char c;
548
 
549
    (void)ipaddr;
550
 
551
    /* Validate parameters. */
552
    /* We let any protocol value go through - it can't hurt us
553
     * and the peer will just drop it if it's not accepting it. */
554
        if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) {
555
        PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n",
556
                    pd, protocol, pb));
557
#if LINK_STATS
558
                lwip_stats.link.opterr++;
559
                lwip_stats.link.drop++;
560
#endif
561
                return ERR_ARG;
562
        }
563
 
564
    /* Check that the link is up. */
565
        if (lcp_phase[pd] == PHASE_DEAD) {
566
        PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd));
567
#if LINK_STATS
568
                lwip_stats.link.rterr++;
569
                lwip_stats.link.drop++;
570
#endif
571
                return ERR_RTE;
572
        }
573
 
574
    /* Grab an output buffer. */
575
        headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
576
    if (headMB == NULL) {
577
        PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd));
578
#if LINK_STATS
579
                lwip_stats.link.memerr++;
580
                lwip_stats.link.drop++;
581
#endif /* LINK_STATS */
582
        return ERR_MEM;
583
    }
584
 
585
#if VJ_SUPPORT > 0
586
    /*
587
     * Attempt Van Jacobson header compression if VJ is configured and
588
     * this is an IP packet.
589
     */
590
    if (protocol == PPP_IP && pc->vjEnabled) {
591
        switch (vj_compress_tcp(&pc->vjComp, pb)) {
592
        case TYPE_IP:
593
            /* No change...
594
            protocol = PPP_IP_PROTOCOL;
595
             */
596
            break;
597
        case TYPE_COMPRESSED_TCP:
598
            protocol = PPP_VJC_COMP;
599
            break;
600
        case TYPE_UNCOMPRESSED_TCP:
601
            protocol = PPP_VJC_UNCOMP;
602
            break;
603
        default:
604
            PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd));
605
#if LINK_STATS
606
                        lwip_stats.link.proterr++;
607
                        lwip_stats.link.drop++;
608
#endif
609
                pbuf_free(headMB);
610
            return ERR_VAL;
611
        }
612
    }
613
#endif
614
 
615
    tailMB = headMB;
616
 
617
    /* Build the PPP header. */
618
    if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
619
        tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
620
    pc->lastXMit = sys_jiffies();
621
    if (!pc->accomp) {
622
        fcsOut = PPP_FCS(fcsOut, PPP_ALLSTATIONS);
623
        tailMB = pppAppend(PPP_ALLSTATIONS, tailMB, &pc->outACCM);
624
        fcsOut = PPP_FCS(fcsOut, PPP_UI);
625
        tailMB = pppAppend(PPP_UI, tailMB, &pc->outACCM);
626
    }
627
    if (!pc->pcomp || protocol > 0xFF) {
628
        c = (protocol >> 8) & 0xFF;
629
        fcsOut = PPP_FCS(fcsOut, c);
630
        tailMB = pppAppend(c, tailMB, &pc->outACCM);
631
    }
632
    c = protocol & 0xFF;
633
    fcsOut = PPP_FCS(fcsOut, c);
634
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
635
 
636
    /* Load packet. */
637
        for(p = pb; p; p = p->next) {
638
        int n;
639
        u_char *sPtr;
640
 
641
        sPtr = (u_char*)p->payload;
642
        n = p->len;
643
        while (n-- > 0) {
644
            c = *sPtr++;
645
 
646
            /* Update FCS before checking for special characters. */
647
            fcsOut = PPP_FCS(fcsOut, c);
648
 
649
            /* Copy to output buffer escaping special characters. */
650
            tailMB = pppAppend(c, tailMB, &pc->outACCM);
651
        }
652
    }
653
 
654
    /* Add FCS and trailing flag. */
655
    c = ~fcsOut & 0xFF;
656
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
657
    c = (~fcsOut >> 8) & 0xFF;
658
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
659
    tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
660
 
661
    /* If we failed to complete the packet, throw it away. */
662
    if (!tailMB) {
663
        PPPDEBUG((LOG_WARNING,
664
                    "pppifOutput[%d]: Alloc err - dropping proto=%d\n",
665
                    pd, protocol));
666
        pbuf_free(headMB);
667
#if LINK_STATS
668
                lwip_stats.link.memerr++;
669
                lwip_stats.link.drop++;
670
#endif
671
        return ERR_MEM;
672
    }
673
 
674
        /* Send it. */
675
    PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol));
676
 
677
    nPut(pc, headMB);
678
 
679
    return ERR_OK;
680
}
681
 
682
/* Get and set parameters for the given connection.
683
 * Return 0 on success, an error code on failure. */
684
int  pppIOCtl(int pd, int cmd, void *arg)
685
{
686
    PPPControl *pc = &pppControl[pd];
687
    int st = 0;
688
 
689
    if (pd < 0 || pd >= NUM_PPP)
690
        st = PPPERR_PARAM;
691
    else {
692
        switch(cmd) {
693
        case PPPCTLG_UPSTATUS:      /* Get the PPP up status. */
694
            if (arg)
695
                *(int *)arg = (int)(pc->if_up);
696
            else
697
                st = PPPERR_PARAM;
698
            break;
699
        case PPPCTLS_ERRCODE:       /* Set the PPP error code. */
700
            if (arg)
701
                pc->errCode = *(int *)arg;
702
            else
703
                st = PPPERR_PARAM;
704
            break;
705
        case PPPCTLG_ERRCODE:       /* Get the PPP error code. */
706
            if (arg)
707
                *(int *)arg = (int)(pc->errCode);
708
            else
709
                st = PPPERR_PARAM;
710
            break;
711
        case PPPCTLG_FD:
712
            if (arg)
713
                *(sio_fd_t *)arg = pc->fd;
714
            else
715
                st = PPPERR_PARAM;
716
            break;
717
        default:
718
            st = PPPERR_PARAM;
719
            break;
720
        }
721
    }
722
 
723
    return st;
724
}
725
 
726
/*
727
 * Return the Maximum Transmission Unit for the given PPP connection.
728
 */
729
u_int pppMTU(int pd)
730
{
731
    PPPControl *pc = &pppControl[pd];
732
    u_int st;
733
 
734
    /* Validate parameters. */
735
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag)
736
        st = 0;
737
    else
738
        st = pc->mtu;
739
 
740
    return st;
741
}
742
 
743
/*
744
 * Write n characters to a ppp link.
745
 *  RETURN: >= 0 Number of characters written
746
 *           -1 Failed to write to device
747
 */
748
int pppWrite(int pd, const u_char *s, int n)
749
{
750
    PPPControl *pc = &pppControl[pd];
751
    u_char c;
752
    u_int fcsOut = PPP_INITFCS;
753
    struct pbuf *headMB = NULL, *tailMB;
754
        headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
755
    if (headMB == NULL) {
756
#if LINK_STATS
757
                lwip_stats.link.memerr++;
758
                lwip_stats.link.proterr++;
759
#endif /* LINK_STATS */
760
                return PPPERR_ALLOC;
761
    }
762
 
763
    tailMB = headMB;
764
 
765
    /* If the link has been idle, we'll send a fresh flag character to
766
     * flush any noise. */
767
    if ((sys_jiffies() - pc->lastXMit) >= PPP_MAXIDLEFLAG)
768
        tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
769
    pc->lastXMit = sys_jiffies();
770
 
771
    /* Load output buffer. */
772
    while (n-- > 0) {
773
        c = *s++;
774
 
775
        /* Update FCS before checking for special characters. */
776
        fcsOut = PPP_FCS(fcsOut, c);
777
 
778
        /* Copy to output buffer escaping special characters. */
779
        tailMB = pppAppend(c, tailMB, &pc->outACCM);
780
    }
781
 
782
    /* Add FCS and trailing flag. */
783
    c = ~fcsOut & 0xFF;
784
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
785
    c = (~fcsOut >> 8) & 0xFF;
786
    tailMB = pppAppend(c, tailMB, &pc->outACCM);
787
    tailMB = pppAppend(PPP_FLAG, tailMB, NULL);
788
 
789
    /* If we failed to complete the packet, throw it away.
790
     * Otherwise send it. */
791
    if (!tailMB) {
792
                PPPDEBUG((LOG_WARNING,
793
                "pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len));
794
/*                "pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
795
                pbuf_free(headMB);
796
#if LINK_STATS
797
                lwip_stats.link.memerr++;
798
                lwip_stats.link.proterr++;
799
#endif /* LINK_STATS */
800
                return PPPERR_ALLOC;
801
        }
802
 
803
    PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%d\n", pd, headMB->len));
804
/*     "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */
805
    nPut(pc, headMB);
806
 
807
    return PPPERR_NONE;
808
}
809
 
810
/*
811
 * ppp_send_config - configure the transmit characteristics of
812
 * the ppp interface.
813
 */
814
void ppp_send_config(
815
    int unit,
816
    int mtu,
817
    u32_t asyncmap,
818
    int pcomp,
819
    int accomp
820
)
821
{
822
    PPPControl *pc = &pppControl[unit];
823
    int i;
824
 
825
    pc->mtu = mtu;
826
    pc->pcomp = pcomp;
827
    pc->accomp = accomp;
828
 
829
    /* Load the ACCM bits for the 32 control codes. */
830
    for (i = 0; i < 32/8; i++)
831
        pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF);
832
    PPPDEBUG((LOG_INFO, "ppp_send_config[%d]: outACCM=%X %X %X %X\n",
833
                unit,
834
                pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3]));
835
}
836
 
837
 
838
/*
839
 * ppp_set_xaccm - set the extended transmit ACCM for the interface.
840
 */
841
void ppp_set_xaccm(int unit, ext_accm *accm)
842
{
843
    memcpy(pppControl[unit].outACCM, accm, sizeof(ext_accm));
844
    PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n",
845
                unit,
846
                pppControl[unit].outACCM[0],
847
                pppControl[unit].outACCM[1],
848
                pppControl[unit].outACCM[2],
849
                pppControl[unit].outACCM[3]));
850
}
851
 
852
 
853
/*
854
 * ppp_recv_config - configure the receive-side characteristics of
855
 * the ppp interface.
856
 */
857
void ppp_recv_config(
858
    int unit,
859
    int mru,
860
    u32_t asyncmap,
861
    int pcomp,
862
    int accomp
863
)
864
{
865
    PPPControl *pc = &pppControl[unit];
866
    int i;
867
 
868
        (void)accomp;
869
        (void)pcomp;
870
        (void)mru;
871
 
872
    /* Load the ACCM bits for the 32 control codes. */
873
    for (i = 0; i < 32 / 8; i++)
874
        pc->inACCM[i] = (u_char)(asyncmap >> (i * 8));
875
    PPPDEBUG((LOG_INFO, "ppp_recv_config[%d]: inACCM=%X %X %X %X\n",
876
                unit,
877
                pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3]));
878
}
879
 
880
#if 0
881
/*
882
 * ccp_test - ask kernel whether a given compression method
883
 * is acceptable for use.  Returns 1 if the method and parameters
884
 * are OK, 0 if the method is known but the parameters are not OK
885
 * (e.g. code size should be reduced), or -1 if the method is unknown.
886
 */
887
int ccp_test(
888
    int unit,
889
    int opt_len,
890
    int for_transmit,
891
    u_char *opt_ptr
892
)
893
{
894
    return 0;   /* XXX Currently no compression. */
895
}
896
 
897
/*
898
 * ccp_flags_set - inform kernel about the current state of CCP.
899
 */
900
void ccp_flags_set(int unit, int isopen, int isup)
901
{
902
    /* XXX */
903
}
904
 
905
/*
906
 * ccp_fatal_error - returns 1 if decompression was disabled as a
907
 * result of an error detected after decompression of a packet,
908
 * 0 otherwise.  This is necessary because of patent nonsense.
909
 */
910
int ccp_fatal_error(int unit)
911
{
912
    /* XXX */
913
    return 0;
914
}
915
#endif
916
 
917
/*
918
 * get_idle_time - return how long the link has been idle.
919
 */
920
int get_idle_time(int u, struct ppp_idle *ip)
921
{
922
    /* XXX */
923
        (void)u;
924
        (void)ip;
925
 
926
    return 0;
927
}
928
 
929
 
930
/*
931
 * Return user specified netmask, modified by any mask we might determine
932
 * for address `addr' (in network byte order).
933
 * Here we scan through the system's list of interfaces, looking for
934
 * any non-point-to-point interfaces which might appear to be on the same
935
 * network as `addr'.  If we find any, we OR in their netmask to the
936
 * user-specified netmask.
937
 */
938
u32_t GetMask(u32_t addr)
939
{
940
    u32_t mask, nmask;
941
 
942
    htonl(addr);
943
    if (IN_CLASSA(addr))    /* determine network mask for address class */
944
        nmask = IN_CLASSA_NET;
945
    else if (IN_CLASSB(addr))
946
        nmask = IN_CLASSB_NET;
947
    else
948
        nmask = IN_CLASSC_NET;
949
    /* class D nets are disallowed by bad_ip_adrs */
950
    mask = subnetMask | htonl(nmask);
951
 
952
    /* XXX
953
     * Scan through the system's network interfaces.
954
     * Get each netmask and OR them into our mask.
955
     */
956
 
957
    return mask;
958
}
959
 
960
/*
961
 * sifvjcomp - config tcp header compression
962
 */
963
int sifvjcomp(
964
    int pd,
965
    int vjcomp,
966
    int cidcomp,
967
    int maxcid
968
)
969
{
970
#if VJ_SUPPORT > 0
971
    PPPControl *pc = &pppControl[pd];
972
 
973
    pc->vjEnabled = vjcomp;
974
    pc->vjComp.compressSlot = cidcomp;
975
    pc->vjComp.maxSlotIndex = maxcid;
976
    PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n",
977
                vjcomp, cidcomp, maxcid));
978
#endif
979
 
980
    return 0;
981
}
982
 
983
/*
984
 * pppifNetifInit - netif init callback
985
 */
986
static err_t pppifNetifInit(struct netif *netif)
987
{
988
        netif->name[0] = 'p';
989
        netif->name[1] = 'p';
990
        netif->output = pppifOutput;
991
        netif->mtu = pppMTU((int)netif->state);
992
        return ERR_OK;
993
}
994
 
995
 
996
/*
997
 * sifup - Config the interface up and enable IP packets to pass.
998
 */
999
int sifup(int pd)
1000
{
1001
    PPPControl *pc = &pppControl[pd];
1002
    int st = 1;
1003
 
1004
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1005
        st = 0;
1006
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1007
    } else {
1008
                netif_remove(&pc->netif);
1009
                if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) {
1010
 
1011
                netif_set_up(&pc->netif);
1012
                pc->if_up = 1;
1013
                pc->errCode = PPPERR_NONE;
1014
 
1015
                        PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1016
                        if(pc->linkStatusCB)
1017
                                pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
1018
                } else {
1019
                st = 0;
1020
                PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd));
1021
                }
1022
    }
1023
 
1024
    return st;
1025
}
1026
 
1027
/*
1028
 * sifnpmode - Set the mode for handling packets for a given NP.
1029
 */
1030
int sifnpmode(int u, int proto, enum NPmode mode)
1031
{
1032
        (void)u;
1033
        (void)proto;
1034
        (void)mode;
1035
    return 0;
1036
}
1037
 
1038
/*
1039
 * sifdown - Config the interface down and disable IP.
1040
 */
1041
int sifdown(int pd)
1042
{
1043
    PPPControl *pc = &pppControl[pd];
1044
    int st = 1;
1045
 
1046
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1047
        st = 0;
1048
        PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
1049
    } else {
1050
        pc->if_up = 0;
1051
        netif_remove(&pc->netif);
1052
        PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1053
        if(pc->linkStatusCB)
1054
                pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
1055
        }
1056
    return st;
1057
}
1058
 
1059
/*
1060
 * sifaddr - Config the interface IP addresses and netmask.
1061
 */
1062
int sifaddr(
1063
    int pd,             /* Interface unit ??? */
1064
    u32_t o,        /* Our IP address ??? */
1065
    u32_t h,        /* His IP address ??? */
1066
    u32_t m,        /* IP subnet mask ??? */
1067
    u32_t ns1,      /* Primary DNS */
1068
    u32_t ns2       /* Secondary DNS */
1069
)
1070
{
1071
    PPPControl *pc = &pppControl[pd];
1072
    int st = 1;
1073
 
1074
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1075
        st = 0;
1076
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1077
    } else {
1078
                memcpy(&pc->addrs.our_ipaddr, &o, sizeof(o));
1079
                memcpy(&pc->addrs.his_ipaddr, &h, sizeof(h));
1080
                memcpy(&pc->addrs.netmask, &m, sizeof(m));
1081
                memcpy(&pc->addrs.dns1, &ns1, sizeof(ns1));
1082
                memcpy(&pc->addrs.dns2, &ns2, sizeof(ns2));
1083
    }
1084
    return st;
1085
}
1086
 
1087
/*
1088
 * cifaddr - Clear the interface IP addresses, and delete routes
1089
 * through the interface if possible.
1090
 */
1091
int cifaddr(
1092
    int pd,         /* Interface unit ??? */
1093
    u32_t o,    /* Our IP address ??? */
1094
    u32_t h     /* IP broadcast address ??? */
1095
)
1096
{
1097
    PPPControl *pc = &pppControl[pd];
1098
    int st = 1;
1099
 
1100
        (void)o;
1101
        (void)h;
1102
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1103
        st = 0;
1104
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1105
    } else {
1106
                IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
1107
                IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
1108
                IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
1109
                IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
1110
                IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
1111
    }
1112
    return st;
1113
}
1114
 
1115
/*
1116
 * sifdefaultroute - assign a default route through the address given.
1117
 */
1118
int sifdefaultroute(int pd, u32_t l, u32_t g)
1119
{
1120
    PPPControl *pc = &pppControl[pd];
1121
    int st = 1;
1122
 
1123
        (void)l;
1124
        (void)g;
1125
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1126
        st = 0;
1127
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1128
    } else {
1129
                netif_set_default(&pc->netif);
1130
    }
1131
 
1132
    /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
1133
 
1134
    return st;
1135
}
1136
 
1137
/*
1138
 * cifdefaultroute - delete a default route through the address given.
1139
 */
1140
int cifdefaultroute(int pd, u32_t l, u32_t g)
1141
{
1142
    PPPControl *pc = &pppControl[pd];
1143
    int st = 1;
1144
 
1145
        (void)l;
1146
        (void)g;
1147
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1148
        st = 0;
1149
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1150
    } else {
1151
                netif_set_default(NULL);
1152
    }
1153
 
1154
    return st;
1155
}
1156
 
1157
void
1158
pppMainWakeup(int pd)
1159
{
1160
        PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
1161
        sio_read_abort(pppControl[pd].fd);
1162
}
1163
 
1164
/* these callbacks are necessary because lcp_* functions
1165
   must be called in the same context as pppInput(),
1166
   namely the tcpip_thread(), essentially because
1167
   they manipulate timeouts which are thread-private
1168
*/
1169
 
1170
static void
1171
pppStartCB(void *arg)
1172
{
1173
    int pd = (int)arg;
1174
 
1175
        PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
1176
    lcp_lowerup(pd);
1177
    lcp_open(pd);      /* Start protocol */
1178
}
1179
 
1180
static void
1181
pppStopCB(void *arg)
1182
{
1183
    int pd = (int)arg;
1184
 
1185
        PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
1186
    lcp_close(pd, "User request");
1187
}
1188
 
1189
static void
1190
pppHupCB(void *arg)
1191
{
1192
    int pd = (int)arg;
1193
 
1194
        PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
1195
    lcp_lowerdown(pd);
1196
    link_terminated(pd);
1197
}
1198
/**********************************/
1199
/*** LOCAL FUNCTION DEFINITIONS ***/
1200
/**********************************/
1201
/* The main PPP process function.  This implements the state machine according
1202
 * to section 4 of RFC 1661: The Point-To-Point Protocol. */
1203
static void pppMain(void *arg)
1204
{
1205
    int pd = (int)arg;
1206
    struct pbuf *p;
1207
    PPPControl* pc;
1208
 
1209
    pc = &pppControl[pd];
1210
 
1211
    p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM);
1212
    if(!p) {
1213
                LWIP_ASSERT("p != NULL", p);
1214
                pc->errCode = PPPERR_ALLOC;
1215
                goto out;
1216
    }
1217
 
1218
    /*
1219
     * Start the connection and handle incoming events (packet or timeout).
1220
     */
1221
        PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
1222
    tcpip_callback(pppStartCB, arg);
1223
    while (lcp_phase[pd] != PHASE_DEAD) {
1224
        if (pc->kill_link) {
1225
                PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d kill_link -> pppStopCB\n", pd));
1226
                pc->errCode = PPPERR_USER;
1227
                /* This will leave us at PHASE_DEAD. */
1228
                tcpip_callback(pppStopCB, arg);
1229
                pc->kill_link = 0;
1230
        }
1231
        else if (pc->sig_hup) {
1232
                PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sig_hup -> pppHupCB\n", pd));
1233
                pc->sig_hup = 0;
1234
                tcpip_callback(pppHupCB, arg);
1235
        } else {
1236
                int c = sio_read(pc->fd, p->payload, p->len);
1237
                if(c > 0) {
1238
                        pppInProc(pd, p->payload, c);
1239
                } else {
1240
                    PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
1241
                    sys_msleep(1); /* give other tasks a chance to run */
1242
                }
1243
        }
1244
    }
1245
        PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd));
1246
    pbuf_free(p);
1247
 
1248
out:
1249
        PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1250
    if(pc->linkStatusCB)
1251
            pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
1252
 
1253
    pc->openFlag = 0;
1254
}
1255
 
1256
static struct pbuf *pppSingleBuf(struct pbuf *p)
1257
{
1258
        struct pbuf *q, *b;
1259
        u_char *pl;
1260
 
1261
        if(p->tot_len == p->len)
1262
                return p;
1263
 
1264
        q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
1265
        if(!q) {
1266
                PPPDEBUG((LOG_ERR,
1267
                        "pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
1268
                return p; /* live dangerously */
1269
        }
1270
 
1271
        for(b = p, pl = q->payload; b != NULL; b = b->next) {
1272
                memcpy(pl, b->payload, b->len);
1273
                pl += b->len;
1274
        }
1275
 
1276
        pbuf_free(p);
1277
 
1278
        return q;
1279
}
1280
 
1281
struct pppInputHeader {
1282
        int unit;
1283
        u16_t proto;
1284
};
1285
 
1286
/*
1287
 * Pass the processed input packet to the appropriate handler.
1288
 * This function and all handlers run in the context of the tcpip_thread
1289
 */
1290
static void pppInput(void *arg)
1291
{
1292
        struct pbuf *nb = (struct pbuf *)arg;
1293
    u16_t protocol;
1294
    int pd;
1295
 
1296
        pd = ((struct pppInputHeader *)nb->payload)->unit;
1297
        protocol = ((struct pppInputHeader *)nb->payload)->proto;
1298
 
1299
    pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
1300
 
1301
#if LINK_STATS
1302
    lwip_stats.link.recv++;
1303
#endif /* LINK_STATS */
1304
 
1305
    /*
1306
     * Toss all non-LCP packets unless LCP is OPEN.
1307
     * Until we get past the authentication phase, toss all packets
1308
     * except LCP, LQR and authentication packets.
1309
     */
1310
    if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
1311
            if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
1312
                        (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
1313
                PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %d\n", protocol, lcp_phase[pd]));
1314
                goto drop;
1315
            }
1316
    }
1317
 
1318
    switch(protocol) {
1319
    case PPP_VJC_COMP:      /* VJ compressed TCP */
1320
#if VJ_SUPPORT > 0
1321
        PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
1322
        /*
1323
         * Clip off the VJ header and prepend the rebuilt TCP/IP header and
1324
         * pass the result to IP.
1325
         */
1326
        if (vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) {
1327
            if (pppControl[pd].netif.input != NULL) {
1328
              pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1329
            }
1330
                        return;
1331
        }
1332
        /* Something's wrong so drop it. */
1333
        PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd));
1334
#else
1335
        /* No handler for this protocol so drop the packet. */
1336
        PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
1337
#endif /* VJ_SUPPORT > 0 */
1338
        break;
1339
    case PPP_VJC_UNCOMP:    /* VJ uncompressed TCP */
1340
#if VJ_SUPPORT > 0
1341
        PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
1342
        /*
1343
         * Process the TCP/IP header for VJ header compression and then pass
1344
         * the packet to IP.
1345
         */
1346
        if (vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) {
1347
            if (pppControl[pd].netif.input != NULL) {
1348
              pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1349
            }
1350
                        return;
1351
        }
1352
        /* Something's wrong so drop it. */
1353
        PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd));
1354
#else
1355
        /* No handler for this protocol so drop the packet. */
1356
        PPPDEBUG((LOG_INFO,
1357
                    "pppInput[%d]: drop VJ UnComp in %d:.*H\n",
1358
                    pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
1359
#endif /* VJ_SUPPORT > 0 */
1360
        break;
1361
    case PPP_IP:            /* Internet Protocol */
1362
        PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
1363
        if (pppControl[pd].netif.input != NULL) {
1364
          pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1365
        }
1366
                return;
1367
    default:
1368
        {
1369
                struct protent *protp;
1370
                int i;
1371
 
1372
                /*
1373
                 * Upcall the proper protocol input routine.
1374
                 */
1375
                for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
1376
                        if (protp->protocol == protocol && protp->enabled_flag) {
1377
                                PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
1378
                                nb = pppSingleBuf(nb);
1379
                                (*protp->input)(pd, nb->payload, nb->len);
1380
                                goto out;
1381
                        }
1382
                }
1383
 
1384
                /* No handler for this protocol so reject the packet. */
1385
                PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%d\n", pd, protocol, nb->len));
1386
                pbuf_header(nb, sizeof(protocol));
1387
#if BYTE_ORDER == LITTLE_ENDIAN
1388
                protocol = htons(protocol);
1389
                memcpy(nb->payload, &protocol, sizeof(protocol));
1390
#endif
1391
                lcp_sprotrej(pd, nb->payload, nb->len);
1392
        }
1393
        break;
1394
    }
1395
 
1396
drop:
1397
#if LINK_STATS
1398
    lwip_stats.link.drop++;
1399
#endif
1400
 
1401
out:
1402
    pbuf_free(nb);
1403
    return;
1404
}
1405
 
1406
 
1407
/*
1408
 * Drop the input packet.
1409
 */
1410
static void pppDrop(PPPControl *pc)
1411
{
1412
    if (pc->inHead != NULL) {
1413
#if 0       
1414
        PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
1415
#endif  
1416
        PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len));
1417
        if (pc->inTail && (pc->inTail != pc->inHead))
1418
            pbuf_free(pc->inTail);
1419
        pbuf_free(pc->inHead);
1420
        pc->inHead = NULL;
1421
        pc->inTail = NULL;
1422
    }
1423
#if VJ_SUPPORT > 0
1424
    vj_uncompress_err(&pc->vjComp);
1425
#endif
1426
 
1427
#if LINK_STATS
1428
    lwip_stats.link.drop++;
1429
#endif /* LINK_STATS */
1430
}
1431
 
1432
 
1433
/*
1434
 * Process a received octet string.
1435
 */
1436
static void pppInProc(int pd, u_char *s, int l)
1437
{
1438
    PPPControl *pc = &pppControl[pd];
1439
    struct pbuf *nextNBuf;
1440
    u_char curChar;
1441
 
1442
    PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytes\n", pd, l));
1443
    while (l-- > 0) {
1444
        curChar = *s++;
1445
 
1446
        /* Handle special characters. */
1447
        if (ESCAPE_P(pc->inACCM, curChar)) {
1448
            /* Check for escape sequences. */
1449
            /* XXX Note that this does not handle an escaped 0x5d character which
1450
             * would appear as an escape character.  Since this is an ASCII ']'
1451
             * and there is no reason that I know of to escape it, I won't complicate
1452
             * the code to handle this case. GLL */
1453
            if (curChar == PPP_ESCAPE)
1454
                pc->inEscaped = 1;
1455
            /* Check for the flag character. */
1456
            else if (curChar == PPP_FLAG) {
1457
                /* If this is just an extra flag character, ignore it. */
1458
                if (pc->inState <= PDADDRESS)
1459
                    ;
1460
                /* If we haven't received the packet header, drop what has come in. */
1461
                else if (pc->inState < PDDATA) {
1462
                    PPPDEBUG((LOG_WARNING,
1463
                                "pppInProc[%d]: Dropping incomplete packet %d\n",
1464
                                pd, pc->inState));
1465
#if LINK_STATS
1466
                                        lwip_stats.link.lenerr++;
1467
#endif
1468
                    pppDrop(pc);
1469
                }
1470
                /* If the fcs is invalid, drop the packet. */
1471
                else if (pc->inFCS != PPP_GOODFCS) {
1472
                    PPPDEBUG((LOG_INFO,
1473
                                "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
1474
                                pd, pc->inFCS, pc->inProtocol));
1475
#if LINK_STATS
1476
                                        lwip_stats.link.chkerr++;
1477
#endif
1478
                    pppDrop(pc);
1479
                }
1480
                /* Otherwise it's a good packet so pass it on. */
1481
                else {
1482
 
1483
                    /* Trim off the checksum. */
1484
                    if(pc->inTail->len >= 2) {
1485
                        pc->inTail->len -= 2;
1486
 
1487
                        pc->inTail->tot_len = pc->inTail->len;
1488
                        if (pc->inTail != pc->inHead) {
1489
                            pbuf_cat(pc->inHead, pc->inTail);
1490
                        }
1491
                    } else {
1492
                        pc->inTail->tot_len = pc->inTail->len;
1493
                        if (pc->inTail != pc->inHead) {
1494
                            pbuf_cat(pc->inHead, pc->inTail);
1495
                        }
1496
 
1497
                        pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
1498
                    }
1499
 
1500
                    /* Dispatch the packet thereby consuming it. */
1501
                    if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
1502
                        PPPDEBUG((LOG_ERR,
1503
                                    "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
1504
                        pbuf_free(pc->inHead);
1505
#if LINK_STATS
1506
                        lwip_stats.link.drop++;
1507
#endif
1508
                    }
1509
                    pc->inHead = NULL;
1510
                    pc->inTail = NULL;
1511
                }
1512
 
1513
                /* Prepare for a new packet. */
1514
                pc->inFCS = PPP_INITFCS;
1515
                pc->inState = PDADDRESS;
1516
                pc->inEscaped = 0;
1517
            }
1518
            /* Other characters are usually control characters that may have
1519
             * been inserted by the physical layer so here we just drop them. */
1520
            else {
1521
                PPPDEBUG((LOG_WARNING,
1522
                            "pppInProc[%d]: Dropping ACCM char <%d>\n", pd, curChar));
1523
            }
1524
        }
1525
        /* Process other characters. */
1526
        else {
1527
            /* Unencode escaped characters. */
1528
            if (pc->inEscaped) {
1529
                pc->inEscaped = 0;
1530
                curChar ^= PPP_TRANS;
1531
            }
1532
 
1533
            /* Process character relative to current state. */
1534
            switch(pc->inState) {
1535
            case PDIDLE:                    /* Idle state - waiting. */
1536
                /* Drop the character if it's not 0xff
1537
                 * we would have processed a flag character above. */
1538
                if (curChar != PPP_ALLSTATIONS) {
1539
                        break;
1540
                                }
1541
 
1542
                                /* Fall through */
1543
            case PDSTART:                   /* Process start flag. */
1544
                /* Prepare for a new packet. */
1545
                pc->inFCS = PPP_INITFCS;
1546
 
1547
                                /* Fall through */
1548
            case PDADDRESS:                 /* Process address field. */
1549
                if (curChar == PPP_ALLSTATIONS) {
1550
                    pc->inState = PDCONTROL;
1551
                    break;
1552
                }
1553
                /* Else assume compressed address and control fields so
1554
                 * fall through to get the protocol... */
1555
            case PDCONTROL:                 /* Process control field. */
1556
                /* If we don't get a valid control code, restart. */
1557
                if (curChar == PPP_UI) {
1558
                    pc->inState = PDPROTOCOL1;
1559
                        break;
1560
                }
1561
#if 0
1562
                else {
1563
                    PPPDEBUG((LOG_WARNING,
1564
                                "pppInProc[%d]: Invalid control <%d>\n", pd, curChar));
1565
                    pc->inState = PDSTART;
1566
                }
1567
#endif
1568
            case PDPROTOCOL1:               /* Process protocol field 1. */
1569
                /* If the lower bit is set, this is the end of the protocol
1570
                 * field. */
1571
                if (curChar & 1) {
1572
                    pc->inProtocol = curChar;
1573
                    pc->inState = PDDATA;
1574
                }
1575
                else {
1576
                    pc->inProtocol = (u_int)curChar << 8;
1577
                    pc->inState = PDPROTOCOL2;
1578
                }
1579
                break;
1580
            case PDPROTOCOL2:               /* Process protocol field 2. */
1581
                pc->inProtocol |= curChar;
1582
                pc->inState = PDDATA;
1583
                break;
1584
            case PDDATA:                    /* Process data byte. */
1585
                /* Make space to receive processed data. */
1586
                if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) {
1587
                    if(pc->inTail) {
1588
                        pc->inTail->tot_len = pc->inTail->len;
1589
                        if (pc->inTail != pc->inHead) {
1590
                            pbuf_cat(pc->inHead, pc->inTail);
1591
                        }
1592
                    }
1593
                    /* If we haven't started a packet, we need a packet header. */
1594
                    nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
1595
                    if (nextNBuf == NULL) {
1596
                        /* No free buffers.  Drop the input packet and let the
1597
                         * higher layers deal with it.  Continue processing
1598
                         * the received pbuf chain in case a new packet starts. */
1599
                        PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
1600
#if LINK_STATS
1601
                                                lwip_stats.link.memerr++;
1602
#endif /* LINK_STATS */
1603
                        pppDrop(pc);
1604
                        pc->inState = PDSTART;  /* Wait for flag sequence. */
1605
                        break;
1606
                    }
1607
                    if (pc->inHead == NULL) {
1608
                        struct pppInputHeader *pih = nextNBuf->payload;
1609
 
1610
                        pih->unit = pd;
1611
                        pih->proto = pc->inProtocol;
1612
 
1613
                        nextNBuf->len += sizeof(*pih);
1614
 
1615
                        pc->inHead = nextNBuf;
1616
                    }
1617
                    pc->inTail = nextNBuf;
1618
                }
1619
                /* Load character into buffer. */
1620
                ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
1621
                break;
1622
            }
1623
 
1624
            /* update the frame check sequence number. */
1625
            pc->inFCS = PPP_FCS(pc->inFCS, curChar);
1626
        }
1627
    }
1628
        avRandomize();
1629
}
1630
 
1631
#endif /* PPP_SUPPORT */

powered by: WebSVN 2.1.0

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