5b47a84f8114ba1e587908f1bf589e764835c47f
[ppp.git] / pppd / lcp.c
1 /*
2  * lcp.c - PPP Link Control Protocol.
3  *
4  * Copyright (c) 1989 Carnegie Mellon University.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by Carnegie Mellon University.  The name of the
13  * University may not be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 #ifndef lint
21 static char rcsid[] = "$Id: lcp.c,v 1.3 1994/04/18 04:00:25 paulus Exp $";
22 #endif
23
24 /*
25  * TODO:
26  * Option tracing.
27  * Test restart.
28  */
29
30 #include <stdio.h>
31 #include <syslog.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/time.h>
36
37 #include <net/if.h>
38 #include <net/if_ppp.h>
39 #include <netinet/in.h>
40
41 #include <string.h>
42
43 #include "pppd.h"
44 #include "ppp.h"
45 #include "fsm.h"
46 #include "lcp.h"
47 #include "magic.h"
48 #include "chap.h"
49 #include "upap.h"
50 #include "ipcp.h"
51
52 /* global vars */
53 fsm lcp_fsm[NPPP];                      /* LCP fsm structure (global)*/
54 lcp_options lcp_wantoptions[NPPP];      /* Options that we want to request */
55 lcp_options lcp_gotoptions[NPPP];       /* Options that peer ack'd */
56 lcp_options lcp_allowoptions[NPPP];     /* Options we allow peer to request */
57 lcp_options lcp_hisoptions[NPPP];       /* Options that we ack'd */
58 u_long xmit_accm[NPPP][8];              /* extended transmit ACCM */
59
60 /*
61  * Callbacks for fsm code.  (CI = Configuration Information)
62  */
63 static void lcp_resetci __ARGS((fsm *));        /* Reset our CI */
64 static int  lcp_cilen __ARGS((fsm *));          /* Return length of our CI */
65 static void lcp_addci __ARGS((fsm *, u_char *, int *)); /* Add our CI to pkt */
66 static int  lcp_ackci __ARGS((fsm *, u_char *, int)); /* Peer ack'd our CI */
67 static int  lcp_nakci __ARGS((fsm *, u_char *, int)); /* Peer nak'd our CI */
68 static int  lcp_rejci __ARGS((fsm *, u_char *, int)); /* Peer rej'd our CI */
69 static int  lcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv peer CI */
70 static void lcp_up __ARGS((fsm *));             /* We're UP */
71 static void lcp_down __ARGS((fsm *));           /* We're DOWN */
72 static void lcp_starting __ARGS((fsm *));       /* We need lower layer up */
73 static void lcp_finished __ARGS((fsm *));       /* We need lower layer down */
74 static int  lcp_extcode __ARGS((fsm *, int, int, u_char *, int));
75 static void lcp_rprotrej __ARGS((fsm *, u_char *, int));
76
77 static fsm_callbacks lcp_callbacks = {  /* LCP callback routines */
78     lcp_resetci,                /* Reset our Configuration Information */
79     lcp_cilen,                  /* Length of our Configuration Information */
80     lcp_addci,                  /* Add our Configuration Information */
81     lcp_ackci,                  /* ACK our Configuration Information */
82     lcp_nakci,                  /* NAK our Configuration Information */
83     lcp_rejci,                  /* Reject our Configuration Information */
84     lcp_reqci,                  /* Request peer's Configuration Information */
85     lcp_up,                     /* Called when fsm reaches OPENED state */
86     lcp_down,                   /* Called when fsm leaves OPENED state */
87     lcp_starting,               /* Called when we want the lower layer up */
88     lcp_finished,               /* Called when we want the lower layer down */
89     NULL,                       /* Called when Protocol-Reject received */
90     NULL,                       /* Retransmission is necessary */
91     lcp_extcode,                /* Called to handle LCP-specific codes */
92     "LCP"                       /* String name of protocol */
93 };
94
95 int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */
96
97 /*
98  * Length of each type of configuration option (in octets)
99  */
100 #define CILEN_VOID      2
101 #define CILEN_SHORT     4       /* CILEN_VOID + sizeof(short) */
102 #define CILEN_CHAP      5       /* CILEN_VOID + sizeof(short) + 1 */
103 #define CILEN_LONG      6       /* CILEN_VOID + sizeof(long) */
104 #define CILEN_LQR       8       /* CILEN_VOID + sizeof(short) + sizeof(long) */
105
106 #define CODENAME(x)     ((x) == CONFACK ? "ACK" : \
107                          (x) == CONFNAK ? "NAK" : "REJ")
108
109
110 /*
111  * lcp_init - Initialize LCP.
112  */
113 void
114 lcp_init(unit)
115     int unit;
116 {
117     fsm *f = &lcp_fsm[unit];
118     lcp_options *wo = &lcp_wantoptions[unit];
119     lcp_options *ao = &lcp_allowoptions[unit];
120
121     f->unit = unit;
122     f->protocol = LCP;
123     f->callbacks = &lcp_callbacks;
124
125     fsm_init(f);
126
127     wo->passive = 0;
128     wo->silent = 0;
129     wo->restart = 0;                    /* Set to 1 in kernels or multi-line
130                                            implementations */
131     wo->neg_mru = 1;
132     wo->mru = DEFMRU;
133     wo->neg_asyncmap = 0;
134     wo->asyncmap = 0;
135     wo->neg_chap = 0;                   /* Set to 1 on server */
136     wo->neg_upap = 0;                   /* Set to 1 on server */
137     wo->chap_mdtype = CHAP_DIGEST_MD5;
138     wo->neg_magicnumber = 1;
139     wo->neg_pcompression = 1;
140     wo->neg_accompression = 1;
141     wo->neg_lqr = 0;                    /* no LQR implementation yet */
142
143     ao->neg_mru = 1;
144     ao->mru = MAXMRU;
145     ao->neg_asyncmap = 1;
146     ao->asyncmap = 0;
147     ao->neg_chap = 1;
148     ao->chap_mdtype = CHAP_DIGEST_MD5;
149     ao->neg_upap = 1;
150     ao->neg_magicnumber = 1;
151     ao->neg_pcompression = 1;
152     ao->neg_accompression = 1;
153     ao->neg_lqr = 0;                    /* no LQR implementation yet */
154
155     memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
156     xmit_accm[unit][3] = 0x60000000;
157 }
158
159
160 /*
161  * lcp_open - LCP is allowed to come up.
162  */
163 void
164 lcp_open(unit)
165     int unit;
166 {
167     fsm *f = &lcp_fsm[unit];
168     lcp_options *wo = &lcp_wantoptions[unit];
169
170     f->flags = 0;
171     if (wo->passive)
172         f->flags |= OPT_PASSIVE;
173     if (wo->silent)
174         f->flags |= OPT_SILENT;
175     fsm_open(f);
176 }
177
178
179 /*
180  * lcp_close - Take LCP down.
181  */
182 void
183 lcp_close(unit)
184     int unit;
185 {
186     fsm_close(&lcp_fsm[unit]);
187 }
188
189
190 /*
191  * lcp_lowerup - The lower layer is up.
192  */
193 void
194 lcp_lowerup(unit)
195     int unit;
196 {
197     sifdown(unit);
198     ppp_set_xaccm(unit, xmit_accm[unit]);
199     ppp_send_config(unit, MTU, 0xffffffff, 0, 0);
200     ppp_recv_config(unit, MTU, 0, 0, 0);
201     peer_mru[unit] = MTU;
202     lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
203
204     fsm_lowerup(&lcp_fsm[unit]);
205 }
206
207
208 /*
209  * lcp_lowerdown - The lower layer is down.
210  */
211 void
212 lcp_lowerdown(unit)
213     int unit;
214 {
215     fsm_lowerdown(&lcp_fsm[unit]);
216 }
217
218
219 /*
220  * lcp_input - Input LCP packet.
221  */
222 void
223 lcp_input(unit, p, len)
224     int unit;
225     u_char *p;
226     int len;
227 {
228     fsm_input(&lcp_fsm[unit], p, len);
229 }
230
231
232 /*
233  * lcp_extcode - Handle a LCP-specific code.
234  */
235 static int
236 lcp_extcode(f, code, id, inp, len)
237     fsm *f;
238     int code, id;
239     u_char *inp;
240     int len;
241 {
242     switch( code ){
243     case PROTREJ:
244         lcp_rprotrej(f, inp, len);
245         break;
246     
247     case ECHOREQ:
248         if( f->state != OPENED )
249             break;
250         LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id));
251         fsm_sdata(f, ECHOREP, id, inp, len);
252         break;
253     
254     case ECHOREP:
255     case DISCREQ:
256         break;
257
258     default:
259         return 0;
260     }
261     return 1;
262 }
263
264     
265 /*
266  * lcp_rprotrej - Receive an Protocol-Reject.
267  *
268  * Figure out which protocol is rejected and inform it.
269  */
270 static void
271 lcp_rprotrej(f, inp, len)
272     fsm *f;
273     u_char *inp;
274     int len;
275 {
276     u_short prot;
277
278     LCPDEBUG((LOG_INFO, "lcp_rprotrej."));
279
280     if (len < sizeof (u_short)) {
281         LCPDEBUG((LOG_INFO,
282                   "lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
283         return;
284     }
285
286     GETSHORT(prot, inp);
287
288     LCPDEBUG((LOG_INFO,
289               "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!",
290               prot));
291
292     /*
293      * Protocol-Reject packets received in any state other than the LCP
294      * OPENED state SHOULD be silently discarded.
295      */
296     if( f->state != OPENED ){
297         LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d",
298                   f->state));
299         return;
300     }
301
302     DEMUXPROTREJ(f->unit, prot);        /* Inform protocol */
303 }
304
305
306 /*
307  * lcp_protrej - A Protocol-Reject was received.
308  */
309 /*ARGSUSED*/
310 void
311 lcp_protrej(unit)
312     int unit;
313 {
314     /*
315      * Can't reject LCP!
316      */
317     LCPDEBUG((LOG_WARNING,
318               "lcp_protrej: Received Protocol-Reject for LCP!"));
319     fsm_protreject(&lcp_fsm[unit]);
320 }
321
322
323 /*
324  * lcp_sprotrej - Send a Protocol-Reject for some protocol.
325  */
326 void
327 lcp_sprotrej(unit, p, len)
328     int unit;
329     u_char *p;
330     int len;
331 {
332     /*
333      * Send back the protocol and the information field of the
334      * rejected packet.  We only get here if LCP is in the OPENED state.
335      */
336     p += 2;
337     len -= 2;
338
339     fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
340               p, len);
341 }
342
343
344 /*
345  * lcp_resetci - Reset our CI.
346  */
347 static void
348   lcp_resetci(f)
349 fsm *f;
350 {
351     lcp_wantoptions[f->unit].magicnumber = magic();
352     lcp_wantoptions[f->unit].numloops = 0;
353     lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
354     peer_mru[f->unit] = MTU;
355 }
356
357
358 /*
359  * lcp_cilen - Return length of our CI.
360  */
361 static int
362 lcp_cilen(f)
363     fsm *f;
364 {
365     lcp_options *go = &lcp_gotoptions[f->unit];
366
367 #define LENCIVOID(neg)  (neg ? CILEN_VOID : 0)
368 #define LENCICHAP(neg)  (neg ? CILEN_CHAP : 0)
369 #define LENCISHORT(neg) (neg ? CILEN_SHORT : 0)
370 #define LENCILONG(neg)  (neg ? CILEN_LONG : 0)
371 #define LENCILQR(neg)   (neg ? CILEN_LQR: 0)
372     /*
373      * NB: we only ask for one of CHAP and UPAP, even if we will
374      * accept either.
375      */
376     return (LENCISHORT(go->neg_mru) +
377             LENCILONG(go->neg_asyncmap) +
378             LENCICHAP(go->neg_chap) +
379             LENCISHORT(!go->neg_chap && go->neg_upap) +
380             LENCILQR(go->neg_lqr) +
381             LENCILONG(go->neg_magicnumber) +
382             LENCIVOID(go->neg_pcompression) +
383             LENCIVOID(go->neg_accompression));
384 }
385
386
387 /*
388  * lcp_addci - Add our desired CIs to a packet.
389  */
390 static void
391 lcp_addci(f, ucp, lenp)
392     fsm *f;
393     u_char *ucp;
394     int *lenp;
395 {
396     lcp_options *go = &lcp_gotoptions[f->unit];
397     u_char *start_ucp = ucp;
398
399 #define ADDCIVOID(opt, neg) \
400     if (neg) { \
401         PUTCHAR(opt, ucp); \
402         PUTCHAR(CILEN_VOID, ucp); \
403     }
404 #define ADDCISHORT(opt, neg, val) \
405     if (neg) { \
406         PUTCHAR(opt, ucp); \
407         PUTCHAR(CILEN_SHORT, ucp); \
408         PUTSHORT(val, ucp); \
409     }
410 #define ADDCICHAP(opt, neg, val, digest) \
411     if (neg) { \
412         PUTCHAR(opt, ucp); \
413         PUTCHAR(CILEN_CHAP, ucp); \
414         PUTSHORT(val, ucp); \
415         PUTCHAR(digest, ucp); \
416     }
417 #define ADDCILONG(opt, neg, val) \
418     if (neg) { \
419         PUTCHAR(opt, ucp); \
420         PUTCHAR(CILEN_LONG, ucp); \
421         PUTLONG(val, ucp); \
422     }
423 #define ADDCILQR(opt, neg, val) \
424     if (neg) { \
425         PUTCHAR(opt, ucp); \
426         PUTCHAR(CILEN_LQR, ucp); \
427         PUTSHORT(LQR, ucp); \
428         PUTLONG(val, ucp); \
429     }
430
431     ADDCISHORT(CI_MRU, go->neg_mru, go->mru);
432     ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
433     ADDCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype);
434     ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP);
435     ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
436     ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
437     ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
438     ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
439
440     if (ucp - start_ucp != *lenp) {
441         /* this should never happen, because peer_mtu should be 1500 */
442         syslog(LOG_ERR, "Bug in lcp_addci: wrong length");
443     }
444 }
445
446
447 /*
448  * lcp_ackci - Ack our CIs.
449  * This should not modify any state if the Ack is bad.
450  *
451  * Returns:
452  *      0 - Ack was bad.
453  *      1 - Ack was good.
454  */
455 static int
456 lcp_ackci(f, p, len)
457     fsm *f;
458     u_char *p;
459     int len;
460 {
461     lcp_options *go = &lcp_gotoptions[f->unit];
462     u_char cilen, citype, cichar;
463     u_short cishort;
464     u_long cilong;
465
466     /*
467      * CIs must be in exactly the same order that we sent.
468      * Check packet length and CI length at each step.
469      * If we find any deviations, then this packet is bad.
470      */
471 #define ACKCIVOID(opt, neg) \
472     if (neg) { \
473         if ((len -= CILEN_VOID) < 0) \
474             goto bad; \
475         GETCHAR(citype, p); \
476         GETCHAR(cilen, p); \
477         if (cilen != CILEN_VOID || \
478             citype != opt) \
479             goto bad; \
480     }
481 #define ACKCISHORT(opt, neg, val) \
482     if (neg) { \
483         if ((len -= CILEN_SHORT) < 0) \
484             goto bad; \
485         GETCHAR(citype, p); \
486         GETCHAR(cilen, p); \
487         if (cilen != CILEN_SHORT || \
488             citype != opt) \
489             goto bad; \
490         GETSHORT(cishort, p); \
491         if (cishort != val) \
492             goto bad; \
493     }
494 #define ACKCICHAP(opt, neg, val, digest) \
495     if (neg) { \
496         if ((len -= CILEN_CHAP) < 0) \
497             goto bad; \
498         GETCHAR(citype, p); \
499         GETCHAR(cilen, p); \
500         if (cilen != CILEN_CHAP || \
501             citype != opt) \
502             goto bad; \
503         GETSHORT(cishort, p); \
504         if (cishort != val) \
505             goto bad; \
506         GETCHAR(cichar, p); \
507         if (cichar != digest) \
508           goto bad; \
509     }
510 #define ACKCILONG(opt, neg, val) \
511     if (neg) { \
512         if ((len -= CILEN_LONG) < 0) \
513             goto bad; \
514         GETCHAR(citype, p); \
515         GETCHAR(cilen, p); \
516         if (cilen != CILEN_LONG || \
517             citype != opt) \
518             goto bad; \
519         GETLONG(cilong, p); \
520         if (cilong != val) \
521             goto bad; \
522     }
523 #define ACKCILQR(opt, neg, val) \
524     if (neg) { \
525         if ((len -= CILEN_LQR) < 0) \
526             goto bad; \
527         GETCHAR(citype, p); \
528         GETCHAR(cilen, p); \
529         if (cilen != CILEN_LQR || \
530             citype != opt) \
531             goto bad; \
532         GETSHORT(cishort, p); \
533         if (cishort != LQR) \
534             goto bad; \
535         GETLONG(cilong, p); \
536         if (cilong != val) \
537           goto bad; \
538     }
539
540     ACKCISHORT(CI_MRU, go->neg_mru, go->mru);
541     ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap);
542     ACKCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype);
543     ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP);
544     ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
545     ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
546     ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
547     ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
548
549     /*
550      * If there are any remaining CIs, then this packet is bad.
551      */
552     if (len != 0)
553         goto bad;
554     return (1);
555 bad:
556     LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!"));
557     return (0);
558 }
559
560
561 /*
562  * lcp_nakci - Peer has sent a NAK for some of our CIs.
563  * This should not modify any state if the Nak is bad
564  * or if LCP is in the OPENED state.
565  *
566  * Returns:
567  *      0 - Nak was bad.
568  *      1 - Nak was good.
569  */
570 static int
571 lcp_nakci(f, p, len)
572     fsm *f;
573     u_char *p;
574     int len;
575 {
576     lcp_options *go = &lcp_gotoptions[f->unit];
577     lcp_options *wo = &lcp_wantoptions[f->unit];
578     u_char cilen, citype, cichar, *next;
579     u_short cishort;
580     u_long cilong;
581     lcp_options no;             /* options we've seen Naks for */
582     lcp_options try;            /* options to request next time */
583     int looped_back = 0;
584
585     BZERO(&no, sizeof(no));
586     try = *go;
587
588     /*
589      * Any Nak'd CIs must be in exactly the same order that we sent.
590      * Check packet length and CI length at each step.
591      * If we find any deviations, then this packet is bad.
592      */
593 #define NAKCIVOID(opt, neg, code) \
594     if (go->neg && \
595         len >= CILEN_VOID && \
596         p[1] == CILEN_VOID && \
597         p[0] == opt) { \
598         len -= CILEN_VOID; \
599         INCPTR(CILEN_VOID, p); \
600         no.neg = 1; \
601         code \
602     }
603 #define NAKCICHAP(opt, neg, code) \
604     if (go->neg && \
605         len >= CILEN_CHAP && \
606         p[1] == CILEN_CHAP && \
607         p[0] == opt) { \
608         len -= CILEN_CHAP; \
609         INCPTR(2, p); \
610         GETSHORT(cishort, p); \
611         GETCHAR(cichar, p); \
612         no.neg = 1; \
613         code \
614     }
615 #define NAKCISHORT(opt, neg, code) \
616     if (go->neg && \
617         len >= CILEN_SHORT && \
618         p[1] == CILEN_SHORT && \
619         p[0] == opt) { \
620         len -= CILEN_SHORT; \
621         INCPTR(2, p); \
622         GETSHORT(cishort, p); \
623         no.neg = 1; \
624         code \
625     }
626 #define NAKCILONG(opt, neg, code) \
627     if (go->neg && \
628         len >= CILEN_LONG && \
629         p[1] == CILEN_LONG && \
630         p[0] == opt) { \
631         len -= CILEN_LONG; \
632         INCPTR(2, p); \
633         GETLONG(cilong, p); \
634         no.neg = 1; \
635         code \
636     }
637 #define NAKCILQR(opt, neg, code) \
638     if (go->neg && \
639         len >= CILEN_LQR && \
640         p[1] == CILEN_LQR && \
641         p[0] == opt) { \
642         len -= CILEN_LQR; \
643         INCPTR(2, p); \
644         GETSHORT(cishort, p); \
645         GETLONG(cilong, p); \
646         no.neg = 1; \
647         code \
648     }
649
650     /*
651      * We don't care if they want to send us smaller packets than
652      * we want.  Therefore, accept any MRU less than what we asked for,
653      * but then ignore the new value when setting the MRU in the kernel.
654      * If they send us a bigger MRU than what we asked, accept it, up to
655      * the limit of the default MRU we'd get if we didn't negotiate.
656      */
657     NAKCISHORT(CI_MRU, neg_mru,
658                if (cishort <= wo->mru || cishort < DEFMRU)
659                    try.mru = cishort;
660                );
661     /*
662      * Add any characters they want to our (receive-side) asyncmap.
663      */
664     NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
665               try.asyncmap = go->asyncmap | cilong;
666               );
667     /*
668      * If they can't cope with our CHAP hash algorithm, we'll have
669      * to stop asking for CHAP.  We haven't got any other algorithm.
670      */
671     NAKCICHAP(CI_AUTHTYPE, neg_chap,
672               try.neg_chap = 0;
673               );
674     /*
675      * Peer shouldn't send Nak for UPAP, protocol compression or
676      * address/control compression requests; they should send
677      * a Reject instead.  If they send a Nak, treat it as a Reject.
678      */
679     if (!go->neg_chap ){
680         NAKCISHORT(CI_AUTHTYPE, neg_upap,
681                    try.neg_upap = 0;
682                    );
683     }
684     /*
685      * If they can't cope with our link quality protocol, we'll have
686      * to stop asking for LQR.  We haven't got any other protocol.
687      * If they Nak the reporting period, take their value XXX ?
688      */
689     NAKCILONG(CI_QUALITY, neg_lqr,
690               if (cishort != LQR)
691                   try.neg_lqr = 0;
692               else
693                   try.lqr_period = cilong;
694               );
695     /*
696      * Check for a looped-back line.
697      */
698     NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
699               try.magicnumber = magic();
700               ++try.numloops;
701               looped_back = 1;
702               );
703
704     NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
705               try.neg_pcompression = 0;
706               );
707     NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
708               try.neg_accompression = 0;
709               );
710
711     /*
712      * There may be remaining CIs, if the peer is requesting negotiation
713      * on an option that we didn't include in our request packet.
714      * If we see an option that we requested, or one we've already seen
715      * in this packet, then this packet is bad.
716      * If we wanted to respond by starting to negotiate on the requested
717      * option(s), we could, but we don't, because except for the
718      * authentication type and quality protocol, if we are not negotiating
719      * an option, it is because we were told not to.
720      * For the authentication type, the Nak from the peer means
721      * `let me authenticate myself with you' which is a bit pointless.
722      * For the quality protocol, the Nak means `ask me to send you quality
723      * reports', but if we didn't ask for them, we don't want them.
724      */
725     while (len > CILEN_VOID) {
726         GETCHAR(citype, p);
727         GETCHAR(cilen, p);
728         if( (len -= cilen) < 0 )
729             goto bad;
730         next = p + cilen - 2;
731
732         switch (citype) {
733         case CI_MRU:
734             if (go->neg_mru || no.neg_mru || cilen != CILEN_SHORT)
735                 goto bad;
736             break;
737         case CI_ASYNCMAP:
738             if (go->neg_asyncmap || no.neg_asyncmap || cilen != CILEN_LONG)
739                 goto bad;
740             break;
741         case CI_AUTHTYPE:
742             if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
743                 goto bad;
744             break;
745         case CI_MAGICNUMBER:
746             if (go->neg_magicnumber || no.neg_magicnumber ||
747                 cilen != CILEN_LONG)
748                 goto bad;
749             break;
750         case CI_PCOMPRESSION:
751             if (go->neg_pcompression || no.neg_pcompression
752                 || cilen != CILEN_VOID)
753                 goto bad;
754             break;
755         case CI_ACCOMPRESSION:
756             if (go->neg_accompression || no.neg_accompression
757                 || cilen != CILEN_VOID)
758                 goto bad;
759             break;
760         case CI_QUALITY:
761             if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
762                 goto bad;
763             break;
764         default:
765             goto bad;
766         }
767         p = next;
768     }
769
770     /* If there is still anything left, this packet is bad. */
771     if (len != 0)
772         goto bad;
773
774     /*
775      * OK, the Nak is good.  Now we can update state.
776      */
777     if (f->state != OPENED) {
778         *go = try;
779         if (looped_back && try.numloops % lcp_warnloops == 0)
780             LCPDEBUG((LOG_INFO, "The line appears to be looped back."));
781     }
782
783     return 1;
784
785 bad:
786     LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!"));
787     return 0;
788 }
789
790
791 /*
792  * lcp_rejci - Peer has Rejected some of our CIs.
793  * This should not modify any state if the Reject is bad
794  * or if LCP is in the OPENED state.
795  *
796  * Returns:
797  *      0 - Reject was bad.
798  *      1 - Reject was good.
799  */
800 static int
801 lcp_rejci(f, p, len)
802     fsm *f;
803     u_char *p;
804     int len;
805 {
806     lcp_options *go = &lcp_gotoptions[f->unit];
807     u_char cichar;
808     u_short cishort;
809     u_long cilong;
810     u_char *start = p;
811     int plen = len;
812     lcp_options try;            /* options to request next time */
813
814     try = *go;
815
816     /*
817      * Any Rejected CIs must be in exactly the same order that we sent.
818      * Check packet length and CI length at each step.
819      * If we find any deviations, then this packet is bad.
820      */
821 #define REJCIVOID(opt, neg) \
822     if (go->neg && \
823         len >= CILEN_VOID && \
824         p[1] == CILEN_VOID && \
825         p[0] == opt) { \
826         len -= CILEN_VOID; \
827         INCPTR(CILEN_VOID, p); \
828         try.neg = 0; \
829         LCPDEBUG((LOG_INFO, "lcp_rejci rejected void opt %d", opt)); \
830     }
831 #define REJCISHORT(opt, neg, val) \
832     if (go->neg && \
833         len >= CILEN_SHORT && \
834         p[1] == CILEN_SHORT && \
835         p[0] == opt) { \
836         len -= CILEN_SHORT; \
837         INCPTR(2, p); \
838         GETSHORT(cishort, p); \
839         /* Check rejected value. */ \
840         if (cishort != val) \
841             goto bad; \
842         try.neg = 0; \
843         LCPDEBUG((LOG_INFO,"lcp_rejci rejected short opt %d", opt)); \
844     }
845 #define REJCICHAP(opt, neg, val, digest) \
846     if (go->neg && \
847         len >= CILEN_CHAP && \
848         p[1] == CILEN_CHAP && \
849         p[0] == opt) { \
850         len -= CILEN_CHAP; \
851         INCPTR(2, p); \
852         GETSHORT(cishort, p); \
853         GETCHAR(cichar, p); \
854         /* Check rejected value. */ \
855         if (cishort != val || cichar != digest) \
856             goto bad; \
857         try.neg = 0; \
858         LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \
859     }
860 #define REJCILONG(opt, neg, val) \
861     if (go->neg && \
862         len >= CILEN_LONG && \
863         p[1] == CILEN_LONG && \
864         p[0] == opt) { \
865         len -= CILEN_LONG; \
866         INCPTR(2, p); \
867         GETLONG(cilong, p); \
868         /* Check rejected value. */ \
869         if (cilong != val) \
870             goto bad; \
871         try.neg = 0; \
872         LCPDEBUG((LOG_INFO,"lcp_rejci rejected long opt %d", opt)); \
873     }
874 #define REJCILQR(opt, neg, val) \
875     if (go->neg && \
876         len >= CILEN_LQR && \
877         p[1] == CILEN_LQR && \
878         p[0] == opt) { \
879         len -= CILEN_LQR; \
880         INCPTR(2, p); \
881         GETSHORT(cishort, p); \
882         GETLONG(cilong, p); \
883         /* Check rejected value. */ \
884         if (cishort != LQR || cichar != val) \
885             goto bad; \
886         try.neg = 0; \
887         LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \
888     }
889
890     REJCISHORT(CI_MRU, neg_mru, go->mru);
891     REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
892     REJCICHAP(CI_AUTHTYPE, neg_chap, CHAP, go->chap_mdtype);
893     if (!go->neg_chap) {
894         REJCISHORT(CI_AUTHTYPE, neg_upap, UPAP);
895     }
896     REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
897     REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
898     REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
899     REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
900
901     /*
902      * If there are any remaining CIs, then this packet is bad.
903      */
904     if (len != 0)
905         goto bad;
906     /*
907      * Now we can update state.
908      */
909     if (f->state != OPENED)
910         *go = try;
911     return 1;
912
913 bad:
914     LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!"));
915     LCPDEBUG((LOG_WARNING, "lcp_rejci: plen %d len %d off %d",
916               plen, len, p - start));
917     return 0;
918 }
919
920
921 /*
922  * lcp_reqci - Check the peer's requested CIs and send appropriate response.
923  *
924  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
925  * appropriately.  If reject_if_disagree is non-zero, doesn't return
926  * CONFNAK; returns CONFREJ if it can't return CONFACK.
927  */
928 static int
929 lcp_reqci(f, inp, lenp, reject_if_disagree)
930     fsm *f;
931     u_char *inp;                /* Requested CIs */
932     int *lenp;                  /* Length of requested CIs */
933     int reject_if_disagree;
934 {
935     lcp_options *go = &lcp_gotoptions[f->unit];
936     lcp_options *ho = &lcp_hisoptions[f->unit];
937     lcp_options *ao = &lcp_allowoptions[f->unit];
938     u_char *cip, *next;         /* Pointer to current and next CIs */
939     u_char cilen, citype, cichar;/* Parsed len, type, char value */
940     u_short cishort;            /* Parsed short value */
941     u_long cilong;              /* Parse long value */
942     int rc = CONFACK;           /* Final packet return code */
943     int orc;                    /* Individual option return code */
944     u_char *p;                  /* Pointer to next char to parse */
945     u_char *ucp = inp;          /* Pointer to current output char */
946     int l = *lenp;              /* Length left */
947
948     /*
949      * Reset all his options.
950      */
951     BZERO(ho, sizeof(*ho));
952
953     /*
954      * Process all his options.
955      */
956     next = inp;
957     while (l) {
958         orc = CONFACK;                  /* Assume success */
959         cip = p = next;                 /* Remember begining of CI */
960         if (l < 2 ||                    /* Not enough data for CI header or */
961             p[1] < 2 ||                 /*  CI length too small or */
962             p[1] > l) {                 /*  CI length too big? */
963             LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!"));
964             orc = CONFREJ;              /* Reject bad CI */
965             cilen = l;                  /* Reject till end of packet */
966             l = 0;                      /* Don't loop again */
967             goto endswitch;
968         }
969         GETCHAR(citype, p);             /* Parse CI type */
970         GETCHAR(cilen, p);              /* Parse CI length */
971         l -= cilen;                     /* Adjust remaining length */
972         next += cilen;                  /* Step to next CI */
973
974         switch (citype) {               /* Check CI type */
975         case CI_MRU:
976             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MRU"));
977             if (!ao->neg_mru ||         /* Allow option? */
978                 cilen != CILEN_SHORT) { /* Check CI length */
979                 orc = CONFREJ;          /* Reject CI */
980                 break;
981             }
982             GETSHORT(cishort, p);       /* Parse MRU */
983             LCPDEBUG((LOG_INFO, "(%d)", cishort));
984
985             /*
986              * He must be able to receive at least our minimum.
987              * No need to check a maximum.  If he sends a large number,
988              * we'll just ignore it.
989              */
990             if (cishort < MINMRU) {
991                 orc = CONFNAK;          /* Nak CI */
992                 if( !reject_if_disagree ){
993                     DECPTR(sizeof (short), p);  /* Backup */
994                     PUTSHORT(MINMRU, p);        /* Give him a hint */
995                 }
996                 break;
997             }
998             ho->neg_mru = 1;            /* Remember he sent MRU */
999             ho->mru = cishort;          /* And remember value */
1000             break;
1001
1002         case CI_ASYNCMAP:
1003             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ASYNCMAP"));
1004             if (!ao->neg_asyncmap ||
1005                 cilen != CILEN_LONG) {
1006                 orc = CONFREJ;
1007                 break;
1008             }
1009             GETLONG(cilong, p);
1010             LCPDEBUG((LOG_INFO, "(%lx)", cilong));
1011
1012             /*
1013              * Asyncmap must have set at least the bits
1014              * which are set in lcp_allowoptions[unit].asyncmap.
1015              */
1016             if ((ao->asyncmap & ~cilong) != 0) {
1017                 orc = CONFNAK;
1018                 if( !reject_if_disagree ){
1019                     DECPTR(sizeof (long), p);
1020                     PUTLONG(ao->asyncmap | cilong, p);
1021                 }
1022                 break;
1023             }
1024             ho->neg_asyncmap = 1;
1025             ho->asyncmap = cilong;
1026             break;
1027
1028         case CI_AUTHTYPE:
1029             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE"));
1030             if (cilen < CILEN_SHORT ||
1031                 !(ao->neg_upap || ao->neg_chap)) {
1032                 orc = CONFREJ;
1033                 break;
1034             }
1035             GETSHORT(cishort, p);
1036             LCPDEBUG((LOG_INFO, "(%x)", cishort));
1037
1038             /*
1039              * Authtype must be UPAP or CHAP.
1040              *
1041              * Note: if both ao->neg_upap and ao->neg_chap are set,
1042              * and the peer sends a Configure-Request with two
1043              * authenticate-protocol requests, one for CHAP and one
1044              * for UPAP, then we will reject the second request.
1045              * Whether we end up doing CHAP or UPAP depends then on
1046              * the ordering of the CIs in the peer's Configure-Request.
1047              */
1048
1049             if (cishort == UPAP) {
1050                 if (!ao->neg_upap ||    /* we don't want to do PAP */
1051                     ho->neg_chap ||     /* or we've already accepted CHAP */
1052                     cilen != CILEN_SHORT) {
1053                     LCPDEBUG((LOG_WARNING,
1054                               "lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
1055                     orc = CONFREJ;
1056                     break;
1057                 }
1058                 ho->neg_upap = 1;
1059                 break;
1060             }
1061             if (cishort == CHAP) {
1062                 if (!ao->neg_chap ||    /* we don't want to do CHAP */
1063                     ho->neg_upap ||     /* or we've already accepted UPAP */
1064                     cilen != CILEN_CHAP) {
1065                     LCPDEBUG((LOG_INFO,
1066                               "lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
1067                     orc = CONFREJ;
1068                     break;
1069                 }
1070                 GETCHAR(cichar, p);     /* get digest type*/
1071                 if (cichar != ao->chap_mdtype) {
1072                     orc = CONFNAK;
1073                     if( !reject_if_disagree ){
1074                         DECPTR(sizeof (u_char), p);
1075                         PUTCHAR(ao->chap_mdtype, p);
1076                     }
1077                     break;
1078                 }
1079                 ho->chap_mdtype = cichar; /* save md type */
1080                 ho->neg_chap = 1;
1081                 break;
1082             }
1083
1084             /*
1085              * We don't recognize the protocol they're asking for.
1086              * Reject it.
1087              */
1088             orc = CONFREJ;
1089             break;
1090
1091         case CI_QUALITY:
1092             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY"));
1093             if (!ao->neg_lqr ||
1094                 cilen != CILEN_LQR) {
1095                 orc = CONFREJ;
1096                 break;
1097             }
1098
1099             GETSHORT(cishort, p);
1100             GETLONG(cilong, p);
1101             LCPDEBUG((LOG_INFO, "(%x %lx)", cishort, cilong));
1102             if (cishort != LQR) {
1103                 orc = CONFREJ;
1104                 break;
1105             }
1106
1107             /*
1108              * Check the reporting period.
1109              * XXX When should we Nak this, and what with?
1110              */
1111             break;
1112
1113         case CI_MAGICNUMBER:
1114             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MAGICNUMBER"));
1115             if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
1116                 cilen != CILEN_LONG) {
1117                 orc = CONFREJ;
1118                 break;
1119             }
1120             GETLONG(cilong, p);
1121             LCPDEBUG((LOG_INFO, "(%lx)", cilong));
1122
1123             /*
1124              * He must have a different magic number.
1125              */
1126             if (go->neg_magicnumber &&
1127                 cilong == go->magicnumber) {
1128                 orc = CONFNAK;
1129                 DECPTR(sizeof (long), p);
1130                 cilong = magic();       /* Don't put magic() inside macro! */
1131                 PUTLONG(cilong, p);
1132                 break;
1133             }
1134             ho->neg_magicnumber = 1;
1135             ho->magicnumber = cilong;
1136             break;
1137
1138
1139         case CI_PCOMPRESSION:
1140             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION"));
1141             if (!ao->neg_pcompression ||
1142                 cilen != CILEN_VOID) {
1143                 orc = CONFREJ;
1144                 break;
1145             }
1146             ho->neg_pcompression = 1;
1147             break;
1148
1149         case CI_ACCOMPRESSION:
1150             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION"));
1151             if (!ao->neg_accompression ||
1152                 cilen != CILEN_VOID) {
1153                 orc = CONFREJ;
1154                 break;
1155             }
1156             ho->neg_accompression = 1;
1157             break;
1158
1159         default:
1160             LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d",
1161                       citype));
1162             orc = CONFREJ;
1163             break;
1164         }
1165
1166 endswitch:
1167         LCPDEBUG((LOG_INFO, " (%s)", CODENAME(orc)));
1168         if (orc == CONFACK &&           /* Good CI */
1169             rc != CONFACK)              /*  but prior CI wasnt? */
1170             continue;                   /* Don't send this one */
1171
1172         if (orc == CONFNAK) {           /* Nak this CI? */
1173             if (reject_if_disagree)     /* Getting fed up with sending NAKs? */
1174                 orc = CONFREJ;          /* Get tough if so */
1175             else {
1176                 if (rc == CONFREJ)      /* Rejecting prior CI? */
1177                     continue;           /* Don't send this one */
1178                 if (rc == CONFACK) {    /* Ack'd all prior CIs? */
1179                     rc = CONFNAK;       /* Not anymore... */
1180                     ucp = inp;          /* Backup */
1181                 }
1182             }
1183         }
1184         if (orc == CONFREJ &&           /* Reject this CI */
1185             rc != CONFREJ) {            /*  but no prior ones? */
1186             rc = CONFREJ;
1187             ucp = inp;                  /* Backup */
1188         }
1189         if (ucp != cip)                 /* Need to move CI? */
1190             BCOPY(cip, ucp, cilen);     /* Move it */
1191         INCPTR(cilen, ucp);             /* Update output pointer */
1192     }
1193
1194     /*
1195      * If we wanted to send additional NAKs (for unsent CIs), the
1196      * code would go here.  This must be done with care since it might
1197      * require a longer packet than we received.  At present there
1198      * are no cases where we want to ask the peer to negotiate an option.
1199      */
1200
1201     *lenp = ucp - inp;                  /* Compute output length */
1202     LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc)));
1203     return (rc);                        /* Return final code */
1204 }
1205
1206
1207 /*
1208  * lcp_up - LCP has come UP.
1209  *
1210  * Start UPAP, IPCP, etc.
1211  */
1212 static void
1213 lcp_up(f)
1214     fsm *f;
1215 {
1216     lcp_options *wo = &lcp_wantoptions[f->unit];
1217     lcp_options *ho = &lcp_hisoptions[f->unit];
1218     lcp_options *go = &lcp_gotoptions[f->unit];
1219     lcp_options *ao = &lcp_allowoptions[f->unit];
1220
1221     /*
1222      * Set our MTU to the smaller of the MTU we wanted and
1223      * the MRU our peer wanted.  If we negotiated an MRU,
1224      * set our MRU to the larger of value we wanted and
1225      * the value we got in the negotiation.
1226      */
1227     ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: MTU)),
1228                     (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
1229                     ho->neg_pcompression, ho->neg_accompression);
1230     ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): MTU),
1231                     (go->neg_asyncmap? go->asyncmap: 0xffffffff),
1232                     go->neg_pcompression, go->neg_accompression);
1233
1234     if (ho->neg_mru)
1235         peer_mru[f->unit] = ho->mru;
1236
1237     ChapLowerUp(f->unit);       /* Enable CHAP */
1238     upap_lowerup(f->unit);      /* Enable UPAP */
1239     ipcp_lowerup(f->unit);      /* Enable IPCP */
1240
1241     link_established(f->unit);
1242 }
1243
1244
1245 /*
1246  * lcp_down - LCP has gone DOWN.
1247  *
1248  * Alert other protocols.
1249  */
1250 static void
1251 lcp_down(f)
1252     fsm *f;
1253 {
1254     ipcp_lowerdown(f->unit);
1255     ChapLowerDown(f->unit);
1256     upap_lowerdown(f->unit);
1257
1258     sifdown(f->unit);
1259     ppp_send_config(f->unit, MTU, 0xffffffff, 0, 0);
1260     ppp_recv_config(f->unit, MTU, 0, 0, 0);
1261     peer_mru[f->unit] = MTU;
1262
1263     link_down(f->unit);
1264 }
1265
1266
1267 /*
1268  * lcp_starting - LCP needs the lower layer up.
1269  */
1270 static void
1271 lcp_starting(f)
1272     fsm *f;
1273 {
1274     link_required(f->unit);
1275 }
1276
1277
1278 /*
1279  * lcp_finished - LCP has finished with the lower layer.
1280  */
1281 static void
1282 lcp_finished(f)
1283     fsm *f;
1284 {
1285     link_terminated(f->unit);
1286 }
1287
1288
1289 /*
1290  * lcp_printpkt - print the contents of an LCP packet.
1291  */
1292 char *lcp_codenames[] = {
1293     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1294     "TermReq", "TermAck", "CodeRej", "ProtRej",
1295     "EchoReq", "EchoRep", "DiscReq"
1296 };
1297
1298 int
1299 lcp_printpkt(p, plen, printer, arg)
1300     u_char *p;
1301     int plen;
1302     void (*printer) __ARGS((void *, char *, ...));
1303     void *arg;
1304 {
1305     int code, id, len, olen;
1306     u_char *pstart, *optend;
1307     u_short cishort;
1308     u_long cilong;
1309
1310     if (plen < HEADERLEN)
1311         return 0;
1312     pstart = p;
1313     GETCHAR(code, p);
1314     GETCHAR(id, p);
1315     GETSHORT(len, p);
1316     if (len < HEADERLEN || len > plen)
1317         return 0;
1318
1319     if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
1320         printer(arg, " %s", lcp_codenames[code-1]);
1321     else
1322         printer(arg, " code=0x%x", code);
1323     printer(arg, " id=0x%x", id);
1324     len -= HEADERLEN;
1325     switch (code) {
1326     case CONFREQ:
1327     case CONFACK:
1328     case CONFNAK:
1329     case CONFREJ:
1330         /* print option list */
1331         while (len >= 2) {
1332             GETCHAR(code, p);
1333             GETCHAR(olen, p);
1334             p -= 2;
1335             if (olen < 2 || olen > len) {
1336                 break;
1337             }
1338             printer(arg, " <");
1339             len -= olen;
1340             optend = p + olen;
1341             switch (code) {
1342             case CI_MRU:
1343                 if (olen == CILEN_SHORT) {
1344                     p += 2;
1345                     GETSHORT(cishort, p);
1346                     printer(arg, "mru %d", cishort);
1347                 }
1348                 break;
1349             case CI_ASYNCMAP:
1350                 if (olen == CILEN_LONG) {
1351                     p += 2;
1352                     GETLONG(cilong, p);
1353                     printer(arg, "asyncmap 0x%x", cilong);
1354                 }
1355                 break;
1356             case CI_AUTHTYPE:
1357                 if (olen >= CILEN_SHORT) {
1358                     p += 2;
1359                     printer(arg, "auth ");
1360                     GETSHORT(cishort, p);
1361                     switch (cishort) {
1362                     case UPAP:
1363                         printer(arg, "upap");
1364                         break;
1365                     case CHAP:
1366                         printer(arg, "chap");
1367                         break;
1368                     default:
1369                         printer(arg, "0x%x", cishort);
1370                     }
1371                 }
1372                 break;
1373             case CI_QUALITY:
1374                 if (olen >= CILEN_SHORT) {
1375                     p += 2;
1376                     printer(arg, "quality ");
1377                     GETSHORT(cishort, p);
1378                     switch (cishort) {
1379                     case LQR:
1380                         printer(arg, "lqr");
1381                         break;
1382                     default:
1383                         printer(arg, "0x%x", cishort);
1384                     }
1385                 }
1386                 break;
1387             case CI_MAGICNUMBER:
1388                 if (olen == CILEN_LONG) {
1389                     p += 2;
1390                     GETLONG(cilong, p);
1391                     printer(arg, "magic 0x%x", cilong);
1392                 }
1393                 break;
1394             case CI_PCOMPRESSION:
1395                 if (olen == CILEN_VOID) {
1396                     p += 2;
1397                     printer(arg, "pcomp");
1398                 }
1399                 break;
1400             case CI_ACCOMPRESSION:
1401                 if (olen == CILEN_VOID) {
1402                     p += 2;
1403                     printer(arg, "accomp");
1404                 }
1405                 break;
1406             }
1407             while (p < optend) {
1408                 GETCHAR(code, p);
1409                 printer(arg, " %.2x", code);
1410             }
1411             printer(arg, ">");
1412         }
1413         break;
1414     }
1415
1416     /* print the rest of the bytes in the packet */
1417     for (; len > 0; --len) {
1418         GETCHAR(code, p);
1419         printer(arg, " %.2x", code);
1420     }
1421
1422     return p - pstart;
1423 }