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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/ccp.c
4
//
5
//==========================================================================
6
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
7
// -------------------------------------------                              
8
// This file is part of eCos, the Embedded Configurable Operating System.   
9
// Copyright (C) 2003 Free Software Foundation, Inc.                        
10
//
11
// eCos is free software; you can redistribute it and/or modify it under    
12
// the terms of the GNU General Public License as published by the Free     
13
// Software Foundation; either version 2 or (at your option) any later      
14
// version.                                                                 
15
//
16
// eCos is distributed in the hope that it will be useful, but WITHOUT      
17
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
18
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
19
// for more details.                                                        
20
//
21
// You should have received a copy of the GNU General Public License        
22
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
23
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
24
//
25
// As a special exception, if other files instantiate templates or use      
26
// macros or inline functions from this file, or you compile this file      
27
// and link it with other works to produce a work based on this file,       
28
// this file does not by itself cause the resulting work to be covered by   
29
// the GNU General Public License. However the source code for this file    
30
// must still be made available in accordance with section (3) of the GNU   
31
// General Public License v2.                                               
32
//
33
// This exception does not invalidate any other reasons why a work based    
34
// on this file might be covered by the GNU General Public License.         
35
// -------------------------------------------                              
36
// ####ECOSGPLCOPYRIGHTEND####                                              
37
// ####BSDALTCOPYRIGHTBEGIN####                                             
38
// -------------------------------------------                              
39
// Portions of this software may have been derived from FreeBSD, OpenBSD,   
40
// or other sources, and if so are covered by the appropriate copyright     
41
// and license included herein.                                             
42
// -------------------------------------------                              
43
// ####BSDALTCOPYRIGHTEND####                                               
44
//==========================================================================
45
 
46
/*
47
 * ccp.c - PPP Compression Control Protocol.
48
 *
49
 * Copyright (c) 1994 The Australian National University.
50
 * All rights reserved.
51
 *
52
 * Permission to use, copy, modify, and distribute this software and its
53
 * documentation is hereby granted, provided that the above copyright
54
 * notice appears in all copies.  This software is provided without any
55
 * warranty, express or implied. The Australian National University
56
 * makes no representations about the suitability of this software for
57
 * any purpose.
58
 *
59
 * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
60
 * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
61
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
62
 * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
63
 * OF SUCH DAMAGE.
64
 *
65
 * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
66
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
67
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
68
 * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
69
 * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
70
 * OR MODIFICATIONS.
71
 */
72
 
73
#ifndef lint
74
//static char rcsid[] = "$FreeBSD: src/usr.sbin/pppd/ccp.c,v 1.10 1999/08/28 01:19:00 peter Exp $";
75
#endif
76
 
77
#include <string.h>
78
#include <cyg/ppp/syslog.h>
79
#include <sys/ioctl.h>
80
#include <sys/types.h>
81
 
82
#include "cyg/ppp/pppd.h"
83
#include "cyg/ppp/fsm.h"
84
#include "cyg/ppp/ccp.h"
85
#include <cyg/ppp/net/ppp_comp.h>
86
 
87
/*
88
 * Protocol entry points from main code.
89
 */
90
static void ccp_init __P((int unit));
91
static void ccp_open __P((int unit));
92
static void ccp_close __P((int unit, char *));
93
static void ccp_lowerup __P((int unit));
94
static void ccp_lowerdown __P((int));
95
static void ccp_input __P((int unit, u_char *pkt, int len));
96
static void ccp_protrej __P((int unit));
97
static int  ccp_printpkt __P((u_char *pkt, int len,
98
                              void (*printer) __P((void *, char *, ...)),
99
                              void *arg));
100
static void ccp_datainput __P((int unit, u_char *pkt, int len));
101
 
102
struct protent ccp_protent = {
103
    PPP_CCP,
104
    ccp_init,
105
    ccp_input,
106
    ccp_protrej,
107
    ccp_lowerup,
108
    ccp_lowerdown,
109
    ccp_open,
110
    ccp_close,
111
    ccp_printpkt,
112
    ccp_datainput,
113
    1,
114
    "CCP",
115
    NULL,
116
    NULL,
117
    NULL
118
};
119
 
120
fsm ccp_fsm[NUM_PPP];
121
ccp_options ccp_wantoptions[NUM_PPP];   /* what to request the peer to use */
122
ccp_options ccp_gotoptions[NUM_PPP];    /* what the peer agreed to do */
123
ccp_options ccp_allowoptions[NUM_PPP];  /* what we'll agree to do */
124
ccp_options ccp_hisoptions[NUM_PPP];    /* what we agreed to do */
125
 
126
/*
127
 * Callbacks for fsm code.
128
 */
129
static void ccp_resetci __P((fsm *));
130
static int  ccp_cilen __P((fsm *));
131
static void ccp_addci __P((fsm *, u_char *, int *));
132
static int  ccp_ackci __P((fsm *, u_char *, int));
133
static int  ccp_nakci __P((fsm *, u_char *, int));
134
static int  ccp_rejci __P((fsm *, u_char *, int));
135
static int  ccp_reqci __P((fsm *, u_char *, int *, int));
136
static void ccp_up __P((fsm *));
137
static void ccp_down __P((fsm *));
138
static int  ccp_extcode __P((fsm *, int, int, u_char *, int));
139
static void ccp_rack_timeout __P((void *));
140
static char *method_name __P((ccp_options *, ccp_options *));
141
 
142
static fsm_callbacks ccp_callbacks = {
143
    ccp_resetci,
144
    ccp_cilen,
145
    ccp_addci,
146
    ccp_ackci,
147
    ccp_nakci,
148
    ccp_rejci,
149
    ccp_reqci,
150
    ccp_up,
151
    ccp_down,
152
    NULL,
153
    NULL,
154
    NULL,
155
    NULL,
156
    ccp_extcode,
157
    "CCP"
158
};
159
 
160
/*
161
 * Do we want / did we get any compression?
162
 */
163
#define ANY_COMPRESS(opt)       ((opt).deflate || (opt).bsd_compress \
164
                                 || (opt).predictor_1 || (opt).predictor_2)
165
 
166
/*
167
 * Local state (mainly for handling reset-reqs and reset-acks).
168
 */
169
static int ccp_localstate[NUM_PPP];
170
#define RACK_PENDING    1       /* waiting for reset-ack */
171
#define RREQ_REPEAT     2       /* send another reset-req if no reset-ack */
172
 
173
#define RACKTIMEOUT     1       /* second */
174
 
175
static int all_rejected[NUM_PPP];       /* we rejected all peer's options */
176
 
177
/*
178
 * ccp_init - initialize CCP.
179
 */
180
static void
181
ccp_init(unit)
182
    int unit;
183
{
184
    fsm *f = &ccp_fsm[unit];
185
 
186
    f->unit = unit;
187
    f->protocol = PPP_CCP;
188
    f->callbacks = &ccp_callbacks;
189
    fsm_init(f);
190
 
191
    memset(&ccp_wantoptions[unit],  0, sizeof(ccp_options));
192
    memset(&ccp_gotoptions[unit],   0, sizeof(ccp_options));
193
    memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
194
    memset(&ccp_hisoptions[unit],   0, sizeof(ccp_options));
195
 
196
    ccp_wantoptions[0].deflate = 1;
197
    ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
198
    ccp_wantoptions[0].deflate_correct = 1;
199
    ccp_wantoptions[0].deflate_draft = 1;
200
    ccp_allowoptions[0].deflate = 1;
201
    ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
202
    ccp_allowoptions[0].deflate_correct = 1;
203
    ccp_allowoptions[0].deflate_draft = 1;
204
 
205
    ccp_wantoptions[0].bsd_compress = 1;
206
    ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
207
    ccp_allowoptions[0].bsd_compress = 1;
208
    ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
209
 
210
    ccp_allowoptions[0].predictor_1 = 1;
211
}
212
 
213
/*
214
 * ccp_open - CCP is allowed to come up.
215
 */
216
static void
217
ccp_open(unit)
218
    int unit;
219
{
220
    fsm *f = &ccp_fsm[unit];
221
 
222
    if (f->state != OPENED)
223
        ccp_flags_set(unit, 1, 0);
224
 
225
    /*
226
     * Find out which compressors the kernel supports before
227
     * deciding whether to open in silent mode.
228
     */
229
    ccp_resetci(f);
230
    if (!ANY_COMPRESS(ccp_gotoptions[unit]))
231
        f->flags |= OPT_SILENT;
232
 
233
    fsm_open(f);
234
}
235
 
236
/*
237
 * ccp_close - Terminate CCP.
238
 */
239
static void
240
ccp_close(unit, reason)
241
    int unit;
242
    char *reason;
243
{
244
    ccp_flags_set(unit, 0, 0);
245
    fsm_close(&ccp_fsm[unit], reason);
246
}
247
 
248
/*
249
 * ccp_lowerup - we may now transmit CCP packets.
250
 */
251
static void
252
ccp_lowerup(unit)
253
    int unit;
254
{
255
    fsm_lowerup(&ccp_fsm[unit]);
256
}
257
 
258
/*
259
 * ccp_lowerdown - we may not transmit CCP packets.
260
 */
261
static void
262
ccp_lowerdown(unit)
263
    int unit;
264
{
265
    fsm_lowerdown(&ccp_fsm[unit]);
266
}
267
 
268
/*
269
 * ccp_input - process a received CCP packet.
270
 */
271
static void
272
ccp_input(unit, p, len)
273
    int unit;
274
    u_char *p;
275
    int len;
276
{
277
    fsm *f = &ccp_fsm[unit];
278
    int oldstate;
279
 
280
    /*
281
     * Check for a terminate-request so we can print a message.
282
     */
283
    oldstate = f->state;
284
    fsm_input(f, p, len);
285
    if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
286
        syslog(LOG_NOTICE, "Compression disabled by peer.");
287
 
288
    /*
289
     * If we get a terminate-ack and we're not asking for compression,
290
     * close CCP.
291
     */
292
    if (oldstate == REQSENT && p[0] == TERMACK
293
        && !ANY_COMPRESS(ccp_gotoptions[unit]))
294
        ccp_close(unit, "No compression negotiated");
295
}
296
 
297
/*
298
 * Handle a CCP-specific code.
299
 */
300
static int
301
ccp_extcode(f, code, id, p, len)
302
    fsm *f;
303
    int code, id;
304
    u_char *p;
305
    int len;
306
{
307
    switch (code) {
308
    case CCP_RESETREQ:
309
        if (f->state != OPENED)
310
            break;
311
        /* send a reset-ack, which the transmitter will see and
312
           reset its compression state. */
313
        fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
314
        break;
315
 
316
    case CCP_RESETACK:
317
        if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
318
            ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
319
            UNTIMEOUT(ccp_rack_timeout, f);
320
        }
321
        break;
322
 
323
    default:
324
        return 0;
325
    }
326
 
327
    return 1;
328
}
329
 
330
/*
331
 * ccp_protrej - peer doesn't talk CCP.
332
 */
333
static void
334
ccp_protrej(unit)
335
    int unit;
336
{
337
    ccp_flags_set(unit, 0, 0);
338
    fsm_lowerdown(&ccp_fsm[unit]);
339
}
340
 
341
/*
342
 * ccp_resetci - initialize at start of negotiation.
343
 */
344
static void
345
ccp_resetci(f)
346
    fsm *f;
347
{
348
    ccp_options *go = &ccp_gotoptions[f->unit];
349
    u_char opt_buf[16];
350
 
351
    *go = ccp_wantoptions[f->unit];
352
    all_rejected[f->unit] = 0;
353
 
354
    /*
355
     * Check whether the kernel knows about the various
356
     * compression methods we might request.
357
     */
358
    if (go->bsd_compress) {
359
        opt_buf[0] = CI_BSD_COMPRESS;
360
        opt_buf[1] = CILEN_BSD_COMPRESS;
361
        opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
362
        if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
363
            go->bsd_compress = 0;
364
    }
365
    if (go->deflate) {
366
        if (go->deflate_correct) {
367
            opt_buf[0] = CI_DEFLATE;
368
            opt_buf[1] = CILEN_DEFLATE;
369
            opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
370
            opt_buf[3] = DEFLATE_CHK_SEQUENCE;
371
            if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
372
                go->deflate_correct = 0;
373
        }
374
        if (go->deflate_draft) {
375
            opt_buf[0] = CI_DEFLATE_DRAFT;
376
            opt_buf[1] = CILEN_DEFLATE;
377
            opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
378
            opt_buf[3] = DEFLATE_CHK_SEQUENCE;
379
            if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
380
                go->deflate_draft = 0;
381
        }
382
        if (!go->deflate_correct && !go->deflate_draft)
383
            go->deflate = 0;
384
    }
385
    if (go->predictor_1) {
386
        opt_buf[0] = CI_PREDICTOR_1;
387
        opt_buf[1] = CILEN_PREDICTOR_1;
388
        if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
389
            go->predictor_1 = 0;
390
    }
391
    if (go->predictor_2) {
392
        opt_buf[0] = CI_PREDICTOR_2;
393
        opt_buf[1] = CILEN_PREDICTOR_2;
394
        if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
395
            go->predictor_2 = 0;
396
    }
397
}
398
 
399
/*
400
 * ccp_cilen - Return total length of our configuration info.
401
 */
402
static int
403
ccp_cilen(f)
404
    fsm *f;
405
{
406
    ccp_options *go = &ccp_gotoptions[f->unit];
407
 
408
    return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
409
        + (go->deflate? CILEN_DEFLATE: 0)
410
        + (go->predictor_1? CILEN_PREDICTOR_1: 0)
411
        + (go->predictor_2? CILEN_PREDICTOR_2: 0);
412
}
413
 
414
/*
415
 * ccp_addci - put our requests in a packet.
416
 */
417
static void
418
ccp_addci(f, p, lenp)
419
    fsm *f;
420
    u_char *p;
421
    int *lenp;
422
{
423
    int res;
424
    ccp_options *go = &ccp_gotoptions[f->unit];
425
    u_char *p0 = p;
426
 
427
    /*
428
     * Add the compression types that we can receive, in decreasing
429
     * preference order.  Get the kernel to allocate the first one
430
     * in case it gets Acked.
431
     */
432
    if (go->deflate) {
433
        p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
434
        p[1] = CILEN_DEFLATE;
435
        p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
436
        p[3] = DEFLATE_CHK_SEQUENCE;
437
        for (;;) {
438
            res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
439
            if (res > 0) {
440
                p += CILEN_DEFLATE;
441
                break;
442
            }
443
            if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE) {
444
                go->deflate = 0;
445
                break;
446
            }
447
            --go->deflate_size;
448
            p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
449
        }
450
        if (p != p0 && go->deflate_correct && go->deflate_draft) {
451
            p[0] = CI_DEFLATE_DRAFT;
452
            p[1] = CILEN_DEFLATE;
453
            p[2] = p[2 - CILEN_DEFLATE];
454
            p[3] = DEFLATE_CHK_SEQUENCE;
455
            p += CILEN_DEFLATE;
456
        }
457
    }
458
    if (go->bsd_compress) {
459
        p[0] = CI_BSD_COMPRESS;
460
        p[1] = CILEN_BSD_COMPRESS;
461
        p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
462
        if (p != p0) {
463
            p += CILEN_BSD_COMPRESS;    /* not the first option */
464
        } else {
465
            for (;;) {
466
                res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
467
                if (res > 0) {
468
                    p += CILEN_BSD_COMPRESS;
469
                    break;
470
                }
471
                if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
472
                    go->bsd_compress = 0;
473
                    break;
474
                }
475
                --go->bsd_bits;
476
                p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
477
            }
478
        }
479
    }
480
    /* XXX Should Predictor 2 be preferable to Predictor 1? */
481
    if (go->predictor_1) {
482
        p[0] = CI_PREDICTOR_1;
483
        p[1] = CILEN_PREDICTOR_1;
484
        if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
485
            go->predictor_1 = 0;
486
        } else {
487
            p += CILEN_PREDICTOR_1;
488
        }
489
    }
490
    if (go->predictor_2) {
491
        p[0] = CI_PREDICTOR_2;
492
        p[1] = CILEN_PREDICTOR_2;
493
        if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
494
            go->predictor_2 = 0;
495
        } else {
496
            p += CILEN_PREDICTOR_2;
497
        }
498
    }
499
 
500
    go->method = (p > p0)? p0[0]: -1;
501
 
502
    *lenp = p - p0;
503
}
504
 
505
/*
506
 * ccp_ackci - process a received configure-ack, and return
507
 * 1 iff the packet was OK.
508
 */
509
static int
510
ccp_ackci(f, p, len)
511
    fsm *f;
512
    u_char *p;
513
    int len;
514
{
515
    ccp_options *go = &ccp_gotoptions[f->unit];
516
    u_char *p0 = p;
517
 
518
    if (go->deflate) {
519
        if (len < CILEN_DEFLATE
520
            || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
521
            || p[1] != CILEN_DEFLATE
522
            || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
523
            || p[3] != DEFLATE_CHK_SEQUENCE)
524
            return 0;
525
        p += CILEN_DEFLATE;
526
        len -= CILEN_DEFLATE;
527
        /* XXX Cope with first/fast ack */
528
        if (len == 0)
529
            return 1;
530
        if (go->deflate_correct && go->deflate_draft) {
531
            if (len < CILEN_DEFLATE
532
                || p[0] != CI_DEFLATE_DRAFT
533
                || p[1] != CILEN_DEFLATE
534
                || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
535
                || p[3] != DEFLATE_CHK_SEQUENCE)
536
                return 0;
537
            p += CILEN_DEFLATE;
538
            len -= CILEN_DEFLATE;
539
        }
540
    }
541
    if (go->bsd_compress) {
542
        if (len < CILEN_BSD_COMPRESS
543
            || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
544
            || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
545
            return 0;
546
        p += CILEN_BSD_COMPRESS;
547
        len -= CILEN_BSD_COMPRESS;
548
        /* XXX Cope with first/fast ack */
549
        if (p == p0 && len == 0)
550
            return 1;
551
    }
552
    if (go->predictor_1) {
553
        if (len < CILEN_PREDICTOR_1
554
            || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
555
            return 0;
556
        p += CILEN_PREDICTOR_1;
557
        len -= CILEN_PREDICTOR_1;
558
        /* XXX Cope with first/fast ack */
559
        if (p == p0 && len == 0)
560
            return 1;
561
    }
562
    if (go->predictor_2) {
563
        if (len < CILEN_PREDICTOR_2
564
            || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
565
            return 0;
566
        p += CILEN_PREDICTOR_2;
567
        len -= CILEN_PREDICTOR_2;
568
        /* XXX Cope with first/fast ack */
569
        if (p == p0 && len == 0)
570
            return 1;
571
    }
572
 
573
    if (len != 0)
574
        return 0;
575
    return 1;
576
}
577
 
578
/*
579
 * ccp_nakci - process received configure-nak.
580
 * Returns 1 iff the nak was OK.
581
 */
582
static int
583
ccp_nakci(f, p, len)
584
    fsm *f;
585
    u_char *p;
586
    int len;
587
{
588
    ccp_options *go = &ccp_gotoptions[f->unit];
589
    ccp_options no;             /* options we've seen already */
590
    ccp_options try;            /* options to ask for next time */
591
 
592
    memset(&no, 0, sizeof(no));
593
    try = *go;
594
 
595
    if (go->deflate && len >= CILEN_DEFLATE
596
        && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
597
        && p[1] == CILEN_DEFLATE) {
598
        no.deflate = 1;
599
        /*
600
         * Peer wants us to use a different code size or something.
601
         * Stop asking for Deflate if we don't understand his suggestion.
602
         */
603
        if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
604
            || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_SIZE
605
            || p[3] != DEFLATE_CHK_SEQUENCE)
606
            try.deflate = 0;
607
        else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
608
            try.deflate_size = DEFLATE_SIZE(p[2]);
609
        p += CILEN_DEFLATE;
610
        len -= CILEN_DEFLATE;
611
        if (go->deflate_correct && go->deflate_draft
612
            && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
613
            && p[1] == CILEN_DEFLATE) {
614
            p += CILEN_DEFLATE;
615
            len -= CILEN_DEFLATE;
616
        }
617
    }
618
 
619
    if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
620
        && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
621
        no.bsd_compress = 1;
622
        /*
623
         * Peer wants us to use a different number of bits
624
         * or a different version.
625
         */
626
        if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
627
            try.bsd_compress = 0;
628
        else if (BSD_NBITS(p[2]) < go->bsd_bits)
629
            try.bsd_bits = BSD_NBITS(p[2]);
630
        p += CILEN_BSD_COMPRESS;
631
        len -= CILEN_BSD_COMPRESS;
632
    }
633
 
634
    /*
635
     * Predictor-1 and 2 have no options, so they can't be Naked.
636
     *
637
     * XXX What should we do with any remaining options?
638
     */
639
 
640
    if (len != 0)
641
        return 0;
642
 
643
    if (f->state != OPENED)
644
        *go = try;
645
    return 1;
646
}
647
 
648
/*
649
 * ccp_rejci - reject some of our suggested compression methods.
650
 */
651
static int
652
ccp_rejci(f, p, len)
653
    fsm *f;
654
    u_char *p;
655
    int len;
656
{
657
    ccp_options *go = &ccp_gotoptions[f->unit];
658
    ccp_options try;            /* options to request next time */
659
 
660
    try = *go;
661
 
662
    /*
663
     * Cope with empty configure-rejects by ceasing to send
664
     * configure-requests.
665
     */
666
    if (len == 0 && all_rejected[f->unit])
667
        return -1;
668
 
669
    if (go->deflate && len >= CILEN_DEFLATE
670
        && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
671
        && p[1] == CILEN_DEFLATE) {
672
        if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
673
            || p[3] != DEFLATE_CHK_SEQUENCE)
674
            return 0;            /* Rej is bad */
675
        if (go->deflate_correct)
676
            try.deflate_correct = 0;
677
        else
678
            try.deflate_draft = 0;
679
        p += CILEN_DEFLATE;
680
        len -= CILEN_DEFLATE;
681
        if (go->deflate_correct && go->deflate_draft
682
            && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
683
            && p[1] == CILEN_DEFLATE) {
684
            if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
685
                || p[3] != DEFLATE_CHK_SEQUENCE)
686
                return 0;                /* Rej is bad */
687
            try.deflate_draft = 0;
688
            p += CILEN_DEFLATE;
689
            len -= CILEN_DEFLATE;
690
        }
691
        if (!try.deflate_correct && !try.deflate_draft)
692
            try.deflate = 0;
693
    }
694
    if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
695
        && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
696
        if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
697
            return 0;
698
        try.bsd_compress = 0;
699
        p += CILEN_BSD_COMPRESS;
700
        len -= CILEN_BSD_COMPRESS;
701
    }
702
    if (go->predictor_1 && len >= CILEN_PREDICTOR_1
703
        && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
704
        try.predictor_1 = 0;
705
        p += CILEN_PREDICTOR_1;
706
        len -= CILEN_PREDICTOR_1;
707
    }
708
    if (go->predictor_2 && len >= CILEN_PREDICTOR_2
709
        && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
710
        try.predictor_2 = 0;
711
        p += CILEN_PREDICTOR_2;
712
        len -= CILEN_PREDICTOR_2;
713
    }
714
 
715
    if (len != 0)
716
        return 0;
717
 
718
    if (f->state != OPENED)
719
        *go = try;
720
 
721
    return 1;
722
}
723
 
724
/*
725
 * ccp_reqci - processed a received configure-request.
726
 * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
727
 * appropriately.
728
 */
729
static int
730
ccp_reqci(f, p, lenp, dont_nak)
731
    fsm *f;
732
    u_char *p;
733
    int *lenp;
734
    int dont_nak;
735
{
736
    int ret, newret, res;
737
    u_char *p0, *retp;
738
    int len, clen, type, nb;
739
    ccp_options *ho = &ccp_hisoptions[f->unit];
740
    ccp_options *ao = &ccp_allowoptions[f->unit];
741
 
742
    ret = CONFACK;
743
    retp = p0 = p;
744
    len = *lenp;
745
 
746
    memset(ho, 0, sizeof(ccp_options));
747
    ho->method = (len > 0)? p[0]: -1;
748
 
749
    while (len > 0) {
750
        newret = CONFACK;
751
        if (len < 2 || p[1] < 2 || p[1] > len) {
752
            /* length is bad */
753
            clen = len;
754
            newret = CONFREJ;
755
 
756
        } else {
757
            type = p[0];
758
            clen = p[1];
759
 
760
            switch (type) {
761
            case CI_DEFLATE:
762
            case CI_DEFLATE_DRAFT:
763
                if (!ao->deflate || clen != CILEN_DEFLATE
764
                    || (!ao->deflate_correct && type == CI_DEFLATE)
765
                    || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
766
                    newret = CONFREJ;
767
                    break;
768
                }
769
 
770
                ho->deflate = 1;
771
                ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
772
                if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
773
                    || p[3] != DEFLATE_CHK_SEQUENCE
774
                    || nb > ao->deflate_size || nb < DEFLATE_MIN_SIZE) {
775
                    newret = CONFNAK;
776
                    if (!dont_nak) {
777
                        p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
778
                        p[3] = DEFLATE_CHK_SEQUENCE;
779
                        /* fall through to test this #bits below */
780
                    } else
781
                        break;
782
                }
783
 
784
                /*
785
                 * Check whether we can do Deflate with the window
786
                 * size they want.  If the window is too big, reduce
787
                 * it until the kernel can cope and nak with that.
788
                 * We only check this for the first option.
789
                 */
790
                if (p == p0) {
791
                    for (;;) {
792
                        res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
793
                        if (res > 0)
794
                            break;              /* it's OK now */
795
                        if (res < 0 || nb == DEFLATE_MIN_SIZE || dont_nak) {
796
                            newret = CONFREJ;
797
                            p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
798
                            break;
799
                        }
800
                        newret = CONFNAK;
801
                        --nb;
802
                        p[2] = DEFLATE_MAKE_OPT(nb);
803
                    }
804
                }
805
                break;
806
 
807
            case CI_BSD_COMPRESS:
808
                if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
809
                    newret = CONFREJ;
810
                    break;
811
                }
812
 
813
                ho->bsd_compress = 1;
814
                ho->bsd_bits = nb = BSD_NBITS(p[2]);
815
                if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
816
                    || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
817
                    newret = CONFNAK;
818
                    if (!dont_nak) {
819
                        p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
820
                        /* fall through to test this #bits below */
821
                    } else
822
                        break;
823
                }
824
 
825
                /*
826
                 * Check whether we can do BSD-Compress with the code
827
                 * size they want.  If the code size is too big, reduce
828
                 * it until the kernel can cope and nak with that.
829
                 * We only check this for the first option.
830
                 */
831
                if (p == p0) {
832
                    for (;;) {
833
                        res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
834
                        if (res > 0)
835
                            break;
836
                        if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
837
                            newret = CONFREJ;
838
                            p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
839
                                                ho->bsd_bits);
840
                            break;
841
                        }
842
                        newret = CONFNAK;
843
                        --nb;
844
                        p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
845
                    }
846
                }
847
                break;
848
 
849
            case CI_PREDICTOR_1:
850
                if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
851
                    newret = CONFREJ;
852
                    break;
853
                }
854
 
855
                ho->predictor_1 = 1;
856
                if (p == p0
857
                    && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
858
                    newret = CONFREJ;
859
                }
860
                break;
861
 
862
            case CI_PREDICTOR_2:
863
                if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
864
                    newret = CONFREJ;
865
                    break;
866
                }
867
 
868
                ho->predictor_2 = 1;
869
                if (p == p0
870
                    && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
871
                    newret = CONFREJ;
872
                }
873
                break;
874
 
875
            default:
876
                newret = CONFREJ;
877
            }
878
        }
879
 
880
        if (newret == CONFNAK && dont_nak)
881
            newret = CONFREJ;
882
        if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
883
            /* we're returning this option */
884
            if (newret == CONFREJ && ret == CONFNAK)
885
                retp = p0;
886
            ret = newret;
887
            if (p != retp)
888
                BCOPY(p, retp, clen);
889
            retp += clen;
890
        }
891
 
892
        p += clen;
893
        len -= clen;
894
    }
895
 
896
    if (ret != CONFACK) {
897
        if (ret == CONFREJ && *lenp == retp - p0)
898
            all_rejected[f->unit] = 1;
899
        else
900
            *lenp = retp - p0;
901
    }
902
    return ret;
903
}
904
 
905
/*
906
 * Make a string name for a compression method (or 2).
907
 */
908
static char *
909
method_name(opt, opt2)
910
    ccp_options *opt, *opt2;
911
{
912
    static char result[64];
913
 
914
    if (!ANY_COMPRESS(*opt))
915
        return "(none)";
916
    switch (opt->method) {
917
    case CI_DEFLATE:
918
    case CI_DEFLATE_DRAFT:
919
        if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
920
            sprintf(result, "Deflate%s (%d/%d)",
921
                    (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
922
                    opt->deflate_size, opt2->deflate_size);
923
        else
924
            sprintf(result, "Deflate%s (%d)",
925
                    (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
926
                    opt->deflate_size);
927
        break;
928
    case CI_BSD_COMPRESS:
929
        if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
930
            sprintf(result, "BSD-Compress (%d/%d)", opt->bsd_bits,
931
                    opt2->bsd_bits);
932
        else
933
            sprintf(result, "BSD-Compress (%d)", opt->bsd_bits);
934
        break;
935
    case CI_PREDICTOR_1:
936
        return "Predictor 1";
937
    case CI_PREDICTOR_2:
938
        return "Predictor 2";
939
    default:
940
        sprintf(result, "Method %d", opt->method);
941
    }
942
    return result;
943
}
944
 
945
/*
946
 * CCP has come up - inform the kernel driver and log a message.
947
 */
948
static void
949
ccp_up(f)
950
    fsm *f;
951
{
952
    ccp_options *go = &ccp_gotoptions[f->unit];
953
    ccp_options *ho = &ccp_hisoptions[f->unit];
954
    char method1[64];
955
 
956
    ccp_flags_set(f->unit, 1, 1);
957
    if (ANY_COMPRESS(*go)) {
958
        if (ANY_COMPRESS(*ho)) {
959
            if (go->method == ho->method) {
960
                syslog(LOG_NOTICE, "%s compression enabled",
961
                       method_name(go, ho));
962
            } else {
963
                strcpy(method1, method_name(go, NULL));
964
                syslog(LOG_NOTICE, "%s / %s compression enabled",
965
                       method1, method_name(ho, NULL));
966
            }
967
        } else
968
            syslog(LOG_NOTICE, "%s receive compression enabled",
969
                   method_name(go, NULL));
970
    } else if (ANY_COMPRESS(*ho))
971
        syslog(LOG_NOTICE, "%s transmit compression enabled",
972
               method_name(ho, NULL));
973
}
974
 
975
/*
976
 * CCP has gone down - inform the kernel driver.
977
 */
978
static void
979
ccp_down(f)
980
    fsm *f;
981
{
982
    if (ccp_localstate[f->unit] & RACK_PENDING)
983
        UNTIMEOUT(ccp_rack_timeout, f);
984
    ccp_localstate[f->unit] = 0;
985
    ccp_flags_set(f->unit, 1, 0);
986
}
987
 
988
/*
989
 * Print the contents of a CCP packet.
990
 */
991
static char *ccp_codenames[] = {
992
    "ConfReq", "ConfAck", "ConfNak", "ConfRej",
993
    "TermReq", "TermAck", "CodeRej",
994
    NULL, NULL, NULL, NULL, NULL, NULL,
995
    "ResetReq", "ResetAck",
996
};
997
 
998
static int
999
ccp_printpkt(p, plen, printer, arg)
1000
    u_char *p;
1001
    int plen;
1002
    void (*printer) __P((void *, char *, ...));
1003
    void *arg;
1004
{
1005
    u_char *p0, *optend;
1006
    int code, id, len;
1007
    int optlen;
1008
 
1009
    p0 = p;
1010
    if (plen < HEADERLEN)
1011
        return 0;
1012
    code = p[0];
1013
    id = p[1];
1014
    len = (p[2] << 8) + p[3];
1015
    if (len < HEADERLEN || len > plen)
1016
        return 0;
1017
 
1018
    if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
1019
        && ccp_codenames[code-1] != NULL)
1020
        printer(arg, " %s", ccp_codenames[code-1]);
1021
    else
1022
        printer(arg, " code=0x%x", code);
1023
    printer(arg, " id=0x%x", id);
1024
    len -= HEADERLEN;
1025
    p += HEADERLEN;
1026
 
1027
    switch (code) {
1028
    case CONFREQ:
1029
    case CONFACK:
1030
    case CONFNAK:
1031
    case CONFREJ:
1032
        /* print list of possible compression methods */
1033
        while (len >= 2) {
1034
            code = p[0];
1035
            optlen = p[1];
1036
            if (optlen < 2 || optlen > len)
1037
                break;
1038
            printer(arg, " <");
1039
            len -= optlen;
1040
            optend = p + optlen;
1041
            switch (code) {
1042
            case CI_DEFLATE:
1043
            case CI_DEFLATE_DRAFT:
1044
                if (optlen >= CILEN_DEFLATE) {
1045
                    printer(arg, "deflate%s %d",
1046
                            (code == CI_DEFLATE_DRAFT? "(old#)": ""),
1047
                            DEFLATE_SIZE(p[2]));
1048
                    if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
1049
                        printer(arg, " method %d", DEFLATE_METHOD(p[2]));
1050
                    if (p[3] != DEFLATE_CHK_SEQUENCE)
1051
                        printer(arg, " check %d", p[3]);
1052
                    p += CILEN_DEFLATE;
1053
                }
1054
                break;
1055
            case CI_BSD_COMPRESS:
1056
                if (optlen >= CILEN_BSD_COMPRESS) {
1057
                    printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
1058
                            BSD_NBITS(p[2]));
1059
                    p += CILEN_BSD_COMPRESS;
1060
                }
1061
                break;
1062
            case CI_PREDICTOR_1:
1063
                if (optlen >= CILEN_PREDICTOR_1) {
1064
                    printer(arg, "predictor 1");
1065
                    p += CILEN_PREDICTOR_1;
1066
                }
1067
                break;
1068
            case CI_PREDICTOR_2:
1069
                if (optlen >= CILEN_PREDICTOR_2) {
1070
                    printer(arg, "predictor 2");
1071
                    p += CILEN_PREDICTOR_2;
1072
                }
1073
                break;
1074
            }
1075
            while (p < optend)
1076
                printer(arg, " %.2x", *p++);
1077
            printer(arg, ">");
1078
        }
1079
        break;
1080
 
1081
    case TERMACK:
1082
    case TERMREQ:
1083
        if (len > 0 && *p >= ' ' && *p < 0x7f) {
1084
            print_string(p, len, printer, arg);
1085
            p += len;
1086
            len = 0;
1087
        }
1088
        break;
1089
    }
1090
 
1091
    /* dump out the rest of the packet in hex */
1092
    while (--len >= 0)
1093
        printer(arg, " %.2x", *p++);
1094
 
1095
    return p - p0;
1096
}
1097
 
1098
/*
1099
 * We have received a packet that the decompressor failed to
1100
 * decompress.  Here we would expect to issue a reset-request, but
1101
 * Motorola has a patent on resetting the compressor as a result of
1102
 * detecting an error in the decompressed data after decompression.
1103
 * (See US patent 5,130,993; international patent publication number
1104
 * WO 91/10289; Australian patent 73296/91.)
1105
 *
1106
 * So we ask the kernel whether the error was detected after
1107
 * decompression; if it was, we take CCP down, thus disabling
1108
 * compression :-(, otherwise we issue the reset-request.
1109
 */
1110
static void
1111
ccp_datainput(unit, pkt, len)
1112
    int unit;
1113
    u_char *pkt;
1114
    int len;
1115
{
1116
    fsm *f;
1117
 
1118
    f = &ccp_fsm[unit];
1119
    if (f->state == OPENED) {
1120
        if (ccp_fatal_error(unit)) {
1121
            /*
1122
             * Disable compression by taking CCP down.
1123
             */
1124
            syslog(LOG_ERR, "Lost compression sync: disabling compression");
1125
            ccp_close(unit, "Lost compression sync");
1126
        } else {
1127
            /*
1128
             * Send a reset-request to reset the peer's compressor.
1129
             * We don't do that if we are still waiting for an
1130
             * acknowledgement to a previous reset-request.
1131
             */
1132
            if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
1133
                fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
1134
                TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1135
                ccp_localstate[f->unit] |= RACK_PENDING;
1136
            } else
1137
                ccp_localstate[f->unit] |= RREQ_REPEAT;
1138
        }
1139
    }
1140
}
1141
 
1142
/*
1143
 * Timeout waiting for reset-ack.
1144
 */
1145
static void
1146
ccp_rack_timeout(arg)
1147
    void *arg;
1148
{
1149
    fsm *f = arg;
1150
 
1151
    if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
1152
        fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
1153
        TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
1154
        ccp_localstate[f->unit] &= ~RREQ_REPEAT;
1155
    } else
1156
        ccp_localstate[f->unit] &= ~RACK_PENDING;
1157
}
1158
 

powered by: WebSVN 2.1.0

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