~ubuntu-branches/debian/sid/ppp/sid

« back to all changes in this revision

Viewing changes to pppd/ccp.c

  • Committer: Bazaar Package Importer
  • Author(s): Eddy Petrișor
  • Date: 2007-03-17 22:31:45 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070317223145-felzh5yrmh8fwi8t
Tags: 2.4.4rel-8
* urgency high since fixes an RC bug
* make sure the /etc/resolv.conf file is world readable (Closes: #415077)

Show diffs side-by-side

added added

removed removed

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