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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [freertos-6.1.1/] [Demo/] [lwIP_MCF5235_GCC/] [lwip/] [src/] [netif/] [ppp/] [ppp.c] - Blame information for rev 583

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 583 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
                        pc->if_up = 1;
1011
                        pc->errCode = PPPERR_NONE;
1012
 
1013
                        PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1014
                        if(pc->linkStatusCB)
1015
                                pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs);
1016
                } else {
1017
                st = 0;
1018
                PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd));
1019
                }
1020
    }
1021
 
1022
    return st;
1023
}
1024
 
1025
/*
1026
 * sifnpmode - Set the mode for handling packets for a given NP.
1027
 */
1028
int sifnpmode(int u, int proto, enum NPmode mode)
1029
{
1030
        (void)u;
1031
        (void)proto;
1032
        (void)mode;
1033
    return 0;
1034
}
1035
 
1036
/*
1037
 * sifdown - Config the interface down and disable IP.
1038
 */
1039
int sifdown(int pd)
1040
{
1041
    PPPControl *pc = &pppControl[pd];
1042
    int st = 1;
1043
 
1044
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1045
        st = 0;
1046
        PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd));
1047
    } else {
1048
        pc->if_up = 0;
1049
        netif_remove(&pc->netif);
1050
        PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1051
        if(pc->linkStatusCB)
1052
                pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL);
1053
        }
1054
    return st;
1055
}
1056
 
1057
/*
1058
 * sifaddr - Config the interface IP addresses and netmask.
1059
 */
1060
int sifaddr(
1061
    int pd,             /* Interface unit ??? */
1062
    u32_t o,        /* Our IP address ??? */
1063
    u32_t h,        /* His IP address ??? */
1064
    u32_t m,        /* IP subnet mask ??? */
1065
    u32_t ns1,      /* Primary DNS */
1066
    u32_t ns2       /* Secondary DNS */
1067
)
1068
{
1069
    PPPControl *pc = &pppControl[pd];
1070
    int st = 1;
1071
 
1072
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1073
        st = 0;
1074
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1075
    } else {
1076
                memcpy(&pc->addrs.our_ipaddr, &o, sizeof(o));
1077
                memcpy(&pc->addrs.his_ipaddr, &h, sizeof(h));
1078
                memcpy(&pc->addrs.netmask, &m, sizeof(m));
1079
                memcpy(&pc->addrs.dns1, &ns1, sizeof(ns1));
1080
                memcpy(&pc->addrs.dns2, &ns2, sizeof(ns2));
1081
    }
1082
    return st;
1083
}
1084
 
1085
/*
1086
 * cifaddr - Clear the interface IP addresses, and delete routes
1087
 * through the interface if possible.
1088
 */
1089
int cifaddr(
1090
    int pd,         /* Interface unit ??? */
1091
    u32_t o,    /* Our IP address ??? */
1092
    u32_t h     /* IP broadcast address ??? */
1093
)
1094
{
1095
    PPPControl *pc = &pppControl[pd];
1096
    int st = 1;
1097
 
1098
        (void)o;
1099
        (void)h;
1100
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1101
        st = 0;
1102
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1103
    } else {
1104
                IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0);
1105
                IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0);
1106
                IP4_ADDR(&pc->addrs.netmask, 255,255,255,0);
1107
                IP4_ADDR(&pc->addrs.dns1, 0,0,0,0);
1108
                IP4_ADDR(&pc->addrs.dns2, 0,0,0,0);
1109
    }
1110
    return st;
1111
}
1112
 
1113
/*
1114
 * sifdefaultroute - assign a default route through the address given.
1115
 */
1116
int sifdefaultroute(int pd, u32_t l, u32_t g)
1117
{
1118
    PPPControl *pc = &pppControl[pd];
1119
    int st = 1;
1120
 
1121
        (void)l;
1122
        (void)g;
1123
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1124
        st = 0;
1125
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1126
    } else {
1127
                netif_set_default(&pc->netif);
1128
    }
1129
 
1130
    /* TODO: check how PPP handled the netMask, previously not set by ipSetDefault */
1131
 
1132
    return st;
1133
}
1134
 
1135
/*
1136
 * cifdefaultroute - delete a default route through the address given.
1137
 */
1138
int cifdefaultroute(int pd, u32_t l, u32_t g)
1139
{
1140
    PPPControl *pc = &pppControl[pd];
1141
    int st = 1;
1142
 
1143
        (void)l;
1144
        (void)g;
1145
    if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) {
1146
        st = 0;
1147
        PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd));
1148
    } else {
1149
                netif_set_default(NULL);
1150
    }
1151
 
1152
    return st;
1153
}
1154
 
1155
void
1156
pppMainWakeup(int pd)
1157
{
1158
        PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd));
1159
        sio_read_abort(pppControl[pd].fd);
1160
}
1161
 
1162
/* these callbacks are necessary because lcp_* functions
1163
   must be called in the same context as pppInput(),
1164
   namely the tcpip_thread(), essentially because
1165
   they manipulate timeouts which are thread-private
1166
*/
1167
 
1168
static void
1169
pppStartCB(void *arg)
1170
{
1171
    int pd = (int)arg;
1172
 
1173
        PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd));
1174
    lcp_lowerup(pd);
1175
    lcp_open(pd);      /* Start protocol */
1176
}
1177
 
1178
static void
1179
pppStopCB(void *arg)
1180
{
1181
    int pd = (int)arg;
1182
 
1183
        PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd));
1184
    lcp_close(pd, "User request");
1185
}
1186
 
1187
static void
1188
pppHupCB(void *arg)
1189
{
1190
    int pd = (int)arg;
1191
 
1192
        PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd));
1193
    lcp_lowerdown(pd);
1194
    link_terminated(pd);
1195
}
1196
/**********************************/
1197
/*** LOCAL FUNCTION DEFINITIONS ***/
1198
/**********************************/
1199
/* The main PPP process function.  This implements the state machine according
1200
 * to section 4 of RFC 1661: The Point-To-Point Protocol. */
1201
static void pppMain(void *arg)
1202
{
1203
    int pd = (int)arg;
1204
    struct pbuf *p;
1205
    PPPControl* pc;
1206
 
1207
    pc = &pppControl[pd];
1208
 
1209
    p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM);
1210
    if(!p) {
1211
                LWIP_ASSERT("p != NULL", p);
1212
                pc->errCode = PPPERR_ALLOC;
1213
                goto out;
1214
    }
1215
 
1216
    /*
1217
     * Start the connection and handle incoming events (packet or timeout).
1218
     */
1219
        PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd));
1220
    tcpip_callback(pppStartCB, arg);
1221
    while (lcp_phase[pd] != PHASE_DEAD) {
1222
        if (pc->kill_link) {
1223
                PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d kill_link -> pppStopCB\n", pd));
1224
                pc->errCode = PPPERR_USER;
1225
                /* This will leave us at PHASE_DEAD. */
1226
                tcpip_callback(pppStopCB, arg);
1227
                pc->kill_link = 0;
1228
        }
1229
        else if (pc->sig_hup) {
1230
                PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sig_hup -> pppHupCB\n", pd));
1231
                pc->sig_hup = 0;
1232
                tcpip_callback(pppHupCB, arg);
1233
        } else {
1234
                int c = sio_read(pc->fd, p->payload, p->len);
1235
                if(c > 0) {
1236
                        pppInProc(pd, p->payload, c);
1237
                } else {
1238
                    PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d sio_read len=%d returned %d\n", pd, p->len, c));
1239
                    sys_msleep(1); /* give other tasks a chance to run */
1240
                }
1241
        }
1242
    }
1243
        PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd));
1244
    pbuf_free(p);
1245
 
1246
out:
1247
        PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode));
1248
    if(pc->linkStatusCB)
1249
            pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL);
1250
 
1251
    pc->openFlag = 0;
1252
}
1253
 
1254
static struct pbuf *pppSingleBuf(struct pbuf *p)
1255
{
1256
        struct pbuf *q, *b;
1257
        u_char *pl;
1258
 
1259
        if(p->tot_len == p->len)
1260
                return p;
1261
 
1262
        q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
1263
        if(!q) {
1264
                PPPDEBUG((LOG_ERR,
1265
                        "pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len));
1266
                return p; /* live dangerously */
1267
        }
1268
 
1269
        for(b = p, pl = q->payload; b != NULL; b = b->next) {
1270
                memcpy(pl, b->payload, b->len);
1271
                pl += b->len;
1272
        }
1273
 
1274
        pbuf_free(p);
1275
 
1276
        return q;
1277
}
1278
 
1279
struct pppInputHeader {
1280
        int unit;
1281
        u16_t proto;
1282
};
1283
 
1284
/*
1285
 * Pass the processed input packet to the appropriate handler.
1286
 * This function and all handlers run in the context of the tcpip_thread
1287
 */
1288
static void pppInput(void *arg)
1289
{
1290
        struct pbuf *nb = (struct pbuf *)arg;
1291
    u16_t protocol;
1292
    int pd;
1293
 
1294
        pd = ((struct pppInputHeader *)nb->payload)->unit;
1295
        protocol = ((struct pppInputHeader *)nb->payload)->proto;
1296
 
1297
    pbuf_header(nb, -(int)sizeof(struct pppInputHeader));
1298
 
1299
#if LINK_STATS
1300
    lwip_stats.link.recv++;
1301
#endif /* LINK_STATS */
1302
 
1303
    /*
1304
     * Toss all non-LCP packets unless LCP is OPEN.
1305
     * Until we get past the authentication phase, toss all packets
1306
     * except LCP, LQR and authentication packets.
1307
     */
1308
    if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) {
1309
            if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) ||
1310
                        (lcp_phase[pd] != PHASE_AUTHENTICATE)) {
1311
                PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %d\n", protocol, lcp_phase[pd]));
1312
                goto drop;
1313
            }
1314
    }
1315
 
1316
    switch(protocol) {
1317
    case PPP_VJC_COMP:      /* VJ compressed TCP */
1318
#if VJ_SUPPORT > 0
1319
        PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len));
1320
        /*
1321
         * Clip off the VJ header and prepend the rebuilt TCP/IP header and
1322
         * pass the result to IP.
1323
         */
1324
        if (vj_uncompress_tcp(&nb, &pppControl[pd].vjComp) >= 0) {
1325
            pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1326
                        return;
1327
        }
1328
        /* Something's wrong so drop it. */
1329
        PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd));
1330
#else
1331
        /* No handler for this protocol so drop the packet. */
1332
        PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload));
1333
#endif /* VJ_SUPPORT > 0 */
1334
        break;
1335
    case PPP_VJC_UNCOMP:    /* VJ uncompressed TCP */
1336
#if VJ_SUPPORT > 0
1337
        PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len));
1338
        /*
1339
         * Process the TCP/IP header for VJ header compression and then pass
1340
         * the packet to IP.
1341
         */
1342
        if (vj_uncompress_uncomp(nb, &pppControl[pd].vjComp) >= 0) {
1343
            pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1344
                        return;
1345
        }
1346
        /* Something's wrong so drop it. */
1347
        PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd));
1348
#else
1349
        /* No handler for this protocol so drop the packet. */
1350
        PPPDEBUG((LOG_INFO,
1351
                    "pppInput[%d]: drop VJ UnComp in %d:.*H\n",
1352
                    pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload));
1353
#endif /* VJ_SUPPORT > 0 */
1354
        break;
1355
    case PPP_IP:            /* Internet Protocol */
1356
        PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len));
1357
        pppControl[pd].netif.input(nb, &pppControl[pd].netif);
1358
                return;
1359
    default:
1360
        {
1361
                struct protent *protp;
1362
                int i;
1363
 
1364
                /*
1365
                 * Upcall the proper protocol input routine.
1366
                 */
1367
                for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) {
1368
                        if (protp->protocol == protocol && protp->enabled_flag) {
1369
                                PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len));
1370
                                nb = pppSingleBuf(nb);
1371
                                (*protp->input)(pd, nb->payload, nb->len);
1372
                                goto out;
1373
                        }
1374
                }
1375
 
1376
                /* No handler for this protocol so reject the packet. */
1377
                PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%d\n", pd, protocol, nb->len));
1378
                pbuf_header(nb, sizeof(protocol));
1379
#if BYTE_ORDER == LITTLE_ENDIAN
1380
                protocol = htons(protocol);
1381
                memcpy(nb->payload, &protocol, sizeof(protocol));
1382
#endif
1383
                lcp_sprotrej(pd, nb->payload, nb->len);
1384
        }
1385
        break;
1386
    }
1387
 
1388
drop:
1389
#if LINK_STATS
1390
    lwip_stats.link.drop++;
1391
#endif
1392
 
1393
out:
1394
    pbuf_free(nb);
1395
    return;
1396
}
1397
 
1398
 
1399
/*
1400
 * Drop the input packet.
1401
 */
1402
static void pppDrop(PPPControl *pc)
1403
{
1404
    if (pc->inHead != NULL) {
1405
#if 0       
1406
        PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload));
1407
#endif  
1408
        PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len));
1409
        if (pc->inTail && (pc->inTail != pc->inHead))
1410
            pbuf_free(pc->inTail);
1411
        pbuf_free(pc->inHead);
1412
        pc->inHead = NULL;
1413
        pc->inTail = NULL;
1414
    }
1415
#if VJ_SUPPORT > 0
1416
    vj_uncompress_err(&pc->vjComp);
1417
#endif
1418
 
1419
#if LINK_STATS
1420
    lwip_stats.link.drop++;
1421
#endif /* LINK_STATS */
1422
}
1423
 
1424
 
1425
/*
1426
 * Process a received octet string.
1427
 */
1428
static void pppInProc(int pd, u_char *s, int l)
1429
{
1430
    PPPControl *pc = &pppControl[pd];
1431
    struct pbuf *nextNBuf;
1432
    u_char curChar;
1433
 
1434
    PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytes\n", pd, l));
1435
    while (l-- > 0) {
1436
        curChar = *s++;
1437
 
1438
        /* Handle special characters. */
1439
        if (ESCAPE_P(pc->inACCM, curChar)) {
1440
            /* Check for escape sequences. */
1441
            /* XXX Note that this does not handle an escaped 0x5d character which
1442
             * would appear as an escape character.  Since this is an ASCII ']'
1443
             * and there is no reason that I know of to escape it, I won't complicate
1444
             * the code to handle this case. GLL */
1445
            if (curChar == PPP_ESCAPE)
1446
                pc->inEscaped = 1;
1447
            /* Check for the flag character. */
1448
            else if (curChar == PPP_FLAG) {
1449
                /* If this is just an extra flag character, ignore it. */
1450
                if (pc->inState <= PDADDRESS)
1451
                    ;
1452
                /* If we haven't received the packet header, drop what has come in. */
1453
                else if (pc->inState < PDDATA) {
1454
                    PPPDEBUG((LOG_WARNING,
1455
                                "pppInProc[%d]: Dropping incomplete packet %d\n",
1456
                                pd, pc->inState));
1457
#if LINK_STATS
1458
                                        lwip_stats.link.lenerr++;
1459
#endif
1460
                    pppDrop(pc);
1461
                }
1462
                /* If the fcs is invalid, drop the packet. */
1463
                else if (pc->inFCS != PPP_GOODFCS) {
1464
                    PPPDEBUG((LOG_INFO,
1465
                                "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n",
1466
                                pd, pc->inFCS, pc->inProtocol));
1467
#if LINK_STATS
1468
                                        lwip_stats.link.chkerr++;
1469
#endif
1470
                    pppDrop(pc);
1471
                }
1472
                /* Otherwise it's a good packet so pass it on. */
1473
                else {
1474
 
1475
                    /* Trim off the checksum. */
1476
                    if(pc->inTail->len >= 2) {
1477
                        pc->inTail->len -= 2;
1478
 
1479
                        pc->inTail->tot_len = pc->inTail->len;
1480
                        if (pc->inTail != pc->inHead) {
1481
                            pbuf_cat(pc->inHead, pc->inTail);
1482
                        }
1483
                    } else {
1484
                        pc->inTail->tot_len = pc->inTail->len;
1485
                        if (pc->inTail != pc->inHead) {
1486
                            pbuf_cat(pc->inHead, pc->inTail);
1487
                        }
1488
 
1489
                        pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2);
1490
                    }
1491
 
1492
                    /* Dispatch the packet thereby consuming it. */
1493
                    if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) {
1494
                        PPPDEBUG((LOG_ERR,
1495
                                    "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd));
1496
                        pbuf_free(pc->inHead);
1497
#if LINK_STATS
1498
                        lwip_stats.link.drop++;
1499
#endif
1500
                    }
1501
                    pc->inHead = NULL;
1502
                    pc->inTail = NULL;
1503
                }
1504
 
1505
                /* Prepare for a new packet. */
1506
                pc->inFCS = PPP_INITFCS;
1507
                pc->inState = PDADDRESS;
1508
                pc->inEscaped = 0;
1509
            }
1510
            /* Other characters are usually control characters that may have
1511
             * been inserted by the physical layer so here we just drop them. */
1512
            else {
1513
                PPPDEBUG((LOG_WARNING,
1514
                            "pppInProc[%d]: Dropping ACCM char <%d>\n", pd, curChar));
1515
            }
1516
        }
1517
        /* Process other characters. */
1518
        else {
1519
            /* Unencode escaped characters. */
1520
            if (pc->inEscaped) {
1521
                pc->inEscaped = 0;
1522
                curChar ^= PPP_TRANS;
1523
            }
1524
 
1525
            /* Process character relative to current state. */
1526
            switch(pc->inState) {
1527
            case PDIDLE:                    /* Idle state - waiting. */
1528
                /* Drop the character if it's not 0xff
1529
                 * we would have processed a flag character above. */
1530
                if (curChar != PPP_ALLSTATIONS) {
1531
                        break;
1532
                                }
1533
 
1534
                                /* Fall through */
1535
            case PDSTART:                   /* Process start flag. */
1536
                /* Prepare for a new packet. */
1537
                pc->inFCS = PPP_INITFCS;
1538
 
1539
                                /* Fall through */
1540
            case PDADDRESS:                 /* Process address field. */
1541
                if (curChar == PPP_ALLSTATIONS) {
1542
                    pc->inState = PDCONTROL;
1543
                    break;
1544
                }
1545
                /* Else assume compressed address and control fields so
1546
                 * fall through to get the protocol... */
1547
            case PDCONTROL:                 /* Process control field. */
1548
                /* If we don't get a valid control code, restart. */
1549
                if (curChar == PPP_UI) {
1550
                    pc->inState = PDPROTOCOL1;
1551
                        break;
1552
                }
1553
#if 0
1554
                else {
1555
                    PPPDEBUG((LOG_WARNING,
1556
                                "pppInProc[%d]: Invalid control <%d>\n", pd, curChar));
1557
                    pc->inState = PDSTART;
1558
                }
1559
#endif
1560
            case PDPROTOCOL1:               /* Process protocol field 1. */
1561
                /* If the lower bit is set, this is the end of the protocol
1562
                 * field. */
1563
                if (curChar & 1) {
1564
                    pc->inProtocol = curChar;
1565
                    pc->inState = PDDATA;
1566
                }
1567
                else {
1568
                    pc->inProtocol = (u_int)curChar << 8;
1569
                    pc->inState = PDPROTOCOL2;
1570
                }
1571
                break;
1572
            case PDPROTOCOL2:               /* Process protocol field 2. */
1573
                pc->inProtocol |= curChar;
1574
                pc->inState = PDDATA;
1575
                break;
1576
            case PDDATA:                    /* Process data byte. */
1577
                /* Make space to receive processed data. */
1578
                if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) {
1579
                    if(pc->inTail) {
1580
                        pc->inTail->tot_len = pc->inTail->len;
1581
                        if (pc->inTail != pc->inHead) {
1582
                            pbuf_cat(pc->inHead, pc->inTail);
1583
                        }
1584
                    }
1585
                    /* If we haven't started a packet, we need a packet header. */
1586
                    nextNBuf = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
1587
                    if (nextNBuf == NULL) {
1588
                        /* No free buffers.  Drop the input packet and let the
1589
                         * higher layers deal with it.  Continue processing
1590
                         * the received pbuf chain in case a new packet starts. */
1591
                        PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd));
1592
#if LINK_STATS
1593
                                                lwip_stats.link.memerr++;
1594
#endif /* LINK_STATS */
1595
                        pppDrop(pc);
1596
                        pc->inState = PDSTART;  /* Wait for flag sequence. */
1597
                        break;
1598
                    }
1599
                    if (pc->inHead == NULL) {
1600
                        struct pppInputHeader *pih = nextNBuf->payload;
1601
 
1602
                        pih->unit = pd;
1603
                        pih->proto = pc->inProtocol;
1604
 
1605
                        nextNBuf->len += sizeof(*pih);
1606
 
1607
                        pc->inHead = nextNBuf;
1608
                    }
1609
                    pc->inTail = nextNBuf;
1610
                }
1611
                /* Load character into buffer. */
1612
                ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar;
1613
                break;
1614
            }
1615
 
1616
            /* update the frame check sequence number. */
1617
            pc->inFCS = PPP_FCS(pc->inFCS, curChar);
1618
        }
1619
    }
1620
        avRandomize();
1621
}
1622
 
1623
#endif /* PPP_SUPPORT */

powered by: WebSVN 2.1.0

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