2 * PPP async serial channel driver for Linux.
4 * Copyright 1999 Paul Mackerras.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
11 * This driver provides the encapsulation and framing for sending
12 * and receiving PPP frames over async serial lines. It relies on
13 * the generic PPP layer to give it frames to send and to process
14 * received frames. It implements the PPP line discipline.
16 * Part of the code in this driver was inspired by the old async-only
17 * PPP driver, written by Michael Callahan and Al Longyear, and
18 * subsequently hacked by Paul Mackerras.
20 * ==FILEVERSION 20000227==
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/skbuff.h>
26 #include <linux/tty.h>
27 #include <linux/netdevice.h>
28 #include <linux/poll.h>
29 #include <linux/ppp_defs.h>
30 #include <linux/if_ppp.h>
31 #include <linux/ppp_channel.h>
32 #include <linux/spinlock.h>
33 #include <linux/init.h>
34 #include <asm/uaccess.h>
36 #ifndef spin_trylock_bh
37 #define spin_trylock_bh(lock) ({ int __r; local_bh_disable(); \
38 __r = spin_trylock(lock); \
39 if (!__r) local_bh_enable(); \
43 #define PPP_VERSION "2.4.1"
47 /* Structure for storing local state. */
49 struct tty_struct
*tty
;
56 unsigned long xmit_flags
;
59 unsigned int bytes_sent
;
60 unsigned int bytes_rcvd
;
67 unsigned long last_xmit
;
72 struct ppp_channel chan
; /* interface to generic ppp layer */
73 unsigned char obuf
[OBUFSIZE
];
76 /* Bit numbers in xmit_flags */
81 #define SC_TOSS 0x20000000
82 #define SC_ESCAPE 0x40000000
85 #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
87 static int flag_time
= HZ
;
88 MODULE_PARM(flag_time
, "i");
93 static int ppp_async_encode(struct asyncppp
*ap
);
94 static int ppp_async_send(struct ppp_channel
*chan
, struct sk_buff
*skb
);
95 static int ppp_async_push(struct asyncppp
*ap
);
96 static void ppp_async_flush_output(struct asyncppp
*ap
);
97 static void ppp_async_input(struct asyncppp
*ap
, const unsigned char *buf
,
98 char *flags
, int count
);
99 static int ppp_async_ioctl(struct ppp_channel
*chan
, unsigned int cmd
,
101 static void async_lcp_peek(struct asyncppp
*ap
, unsigned char *data
,
102 int len
, int inbound
);
104 struct ppp_channel_ops async_ops
= {
110 * Routines implementing the PPP line discipline.
114 * Called when a tty is put into PPP line discipline.
117 ppp_asynctty_open(struct tty_struct
*tty
)
124 ap
= kmalloc(sizeof(*ap
), GFP_KERNEL
);
128 /* initialize the asyncppp structure */
129 memset(ap
, 0, sizeof(*ap
));
132 spin_lock_init(&ap
->xmit_lock
);
133 spin_lock_init(&ap
->recv_lock
);
135 ap
->xaccm
[3] = 0x60000000U
;
141 ap
->chan
.private = ap
;
142 ap
->chan
.ops
= &async_ops
;
143 ap
->chan
.mtu
= PPP_MRU
;
144 err
= ppp_register_channel(&ap
->chan
);
160 * Called when the tty is put into another line discipline
162 * We assume that while we are in this routine, the tty layer
163 * won't call any of the other line discipline entries for the
167 ppp_asynctty_close(struct tty_struct
*tty
)
169 struct asyncppp
*ap
= tty
->disc_data
;
174 ppp_unregister_channel(&ap
->chan
);
187 ppp_asynctty_read(struct tty_struct
*tty
, struct file
*file
,
188 unsigned char *buf
, size_t count
)
190 /* For now, do the same as the old 2.3.x code useta */
191 struct asyncppp
*ap
= tty
->disc_data
;
195 return ppp_channel_read(&ap
->chan
, file
, buf
, count
);
199 * Write on the tty does nothing, the packets all come in
200 * from the ppp generic stuff.
203 ppp_asynctty_write(struct tty_struct
*tty
, struct file
*file
,
204 const unsigned char *buf
, size_t count
)
206 /* For now, do the same as the old 2.3.x code useta */
207 struct asyncppp
*ap
= tty
->disc_data
;
211 return ppp_channel_write(&ap
->chan
, buf
, count
);
215 ppp_asynctty_ioctl(struct tty_struct
*tty
, struct file
*file
,
216 unsigned int cmd
, unsigned long arg
)
218 struct asyncppp
*ap
= tty
->disc_data
;
228 if (put_user(ppp_channel_index(&ap
->chan
), (int *) arg
))
238 if (put_user(ppp_unit_number(&ap
->chan
), (int *) arg
))
245 err
= n_tty_ioctl(tty
, file
, cmd
, arg
);
249 /* flush our buffers and the serial port's buffer */
250 if (arg
== TCIOFLUSH
|| arg
== TCOFLUSH
)
251 ppp_async_flush_output(ap
);
252 err
= n_tty_ioctl(tty
, file
, cmd
, arg
);
257 if (put_user(val
, (int *) arg
))
263 * For now, do the same as the old 2.3 driver useta
267 case PPPIOCGASYNCMAP
:
268 case PPPIOCSASYNCMAP
:
269 case PPPIOCGRASYNCMAP
:
270 case PPPIOCSRASYNCMAP
:
271 case PPPIOCGXASYNCMAP
:
272 case PPPIOCSXASYNCMAP
:
276 if (!capable(CAP_NET_ADMIN
))
278 err
= ppp_async_ioctl(&ap
->chan
, cmd
, arg
);
283 err
= ppp_channel_ioctl(&ap
->chan
, cmd
, arg
);
293 /* No kernel lock - fine */
295 ppp_asynctty_poll(struct tty_struct
*tty
, struct file
*file
, poll_table
*wait
)
298 struct asyncppp
*ap
= tty
->disc_data
;
300 mask
= POLLOUT
| POLLWRNORM
;
302 * For now, do the same as the old 2.3 driver useta
305 mask
|= ppp_channel_poll(&ap
->chan
, file
, wait
);
306 if (test_bit(TTY_OTHER_CLOSED
, &tty
->flags
) || tty_hung_up_p(file
))
312 ppp_asynctty_room(struct tty_struct
*tty
)
318 ppp_asynctty_receive(struct tty_struct
*tty
, const unsigned char *buf
,
319 char *flags
, int count
)
321 struct asyncppp
*ap
= tty
->disc_data
;
325 spin_lock_bh(&ap
->recv_lock
);
326 ppp_async_input(ap
, buf
, flags
, count
);
327 spin_unlock_bh(&ap
->recv_lock
);
328 if (test_and_clear_bit(TTY_THROTTLED
, &tty
->flags
)
329 && tty
->driver
.unthrottle
)
330 tty
->driver
.unthrottle(tty
);
334 ppp_asynctty_wakeup(struct tty_struct
*tty
)
336 struct asyncppp
*ap
= tty
->disc_data
;
338 clear_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
);
341 if (ppp_async_push(ap
))
342 ppp_output_wakeup(&ap
->chan
);
346 static struct tty_ldisc ppp_ldisc
= {
347 magic
: TTY_LDISC_MAGIC
,
349 open
: ppp_asynctty_open
,
350 close
: ppp_asynctty_close
,
351 read
: ppp_asynctty_read
,
352 write
: ppp_asynctty_write
,
353 ioctl
: ppp_asynctty_ioctl
,
354 poll
: ppp_asynctty_poll
,
355 receive_room
: ppp_asynctty_room
,
356 receive_buf
: ppp_asynctty_receive
,
357 write_wakeup
: ppp_asynctty_wakeup
,
365 err
= tty_register_ldisc(N_PPP
, &ppp_ldisc
);
367 printk(KERN_ERR
"PPP_async: error %d registering line disc.\n",
373 * The following routines provide the PPP channel interface.
376 ppp_async_ioctl(struct ppp_channel
*chan
, unsigned int cmd
, unsigned long arg
)
378 struct asyncppp
*ap
= chan
->private;
385 val
= ap
->flags
| ap
->rbits
;
386 if (put_user(val
, (int *) arg
))
391 if (get_user(val
, (int *) arg
))
393 ap
->flags
= val
& ~SC_RCV_BITS
;
394 spin_lock_bh(&ap
->recv_lock
);
395 ap
->rbits
= val
& SC_RCV_BITS
;
396 spin_unlock_bh(&ap
->recv_lock
);
400 case PPPIOCGASYNCMAP
:
401 if (put_user(ap
->xaccm
[0], (u32
*) arg
))
405 case PPPIOCSASYNCMAP
:
406 if (get_user(ap
->xaccm
[0], (u32
*) arg
))
411 case PPPIOCGRASYNCMAP
:
412 if (put_user(ap
->raccm
, (u32
*) arg
))
416 case PPPIOCSRASYNCMAP
:
417 if (get_user(ap
->raccm
, (u32
*) arg
))
422 case PPPIOCGXASYNCMAP
:
423 if (copy_to_user((void *) arg
, ap
->xaccm
, sizeof(ap
->xaccm
)))
427 case PPPIOCSXASYNCMAP
:
428 if (copy_from_user(accm
, (void *) arg
, sizeof(accm
)))
430 accm
[2] &= ~0x40000000U
; /* can't escape 0x5e */
431 accm
[3] |= 0x60000000U
; /* must escape 0x7d, 0x7e */
432 memcpy(ap
->xaccm
, accm
, sizeof(ap
->xaccm
));
437 if (put_user(ap
->mru
, (int *) arg
))
442 if (get_user(val
, (int *) arg
))
458 * Procedures for encapsulation and framing.
461 u16 ppp_crc16_table
[256] = {
462 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
463 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
464 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
465 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
466 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
467 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
468 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
469 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
470 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
471 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
472 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
473 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
474 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
475 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
476 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
477 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
478 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
479 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
480 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
481 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
482 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
483 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
484 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
485 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
486 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
487 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
488 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
489 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
490 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
491 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
492 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
493 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
495 EXPORT_SYMBOL(ppp_crc16_table
);
496 #define fcstab ppp_crc16_table /* for PPP_FCS macro */
499 * Procedure to encode the data for async serial transmission.
500 * Does octet stuffing (escaping), puts the address/control bytes
501 * on if A/C compression is disabled, and does protocol compression.
502 * Assumes ap->tpkt != 0 on entry.
503 * Returns 1 if we finished the current frame, 0 otherwise.
506 #define PUT_BYTE(ap, buf, c, islcp) do { \
507 if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\
508 *buf++ = PPP_ESCAPE; \
515 ppp_async_encode(struct asyncppp
*ap
)
517 int fcs
, i
, count
, c
, proto
;
518 unsigned char *buf
, *buflim
;
526 data
= ap
->tpkt
->data
;
527 count
= ap
->tpkt
->len
;
529 proto
= (data
[0] << 8) + data
[1];
532 * LCP packets with code values between 1 (configure-reqest)
533 * and 7 (code-reject) must be sent as though no options
534 * had been negotiated.
536 islcp
= proto
== PPP_LCP
&& 1 <= data
[2] && data
[2] <= 7;
540 async_lcp_peek(ap
, data
, count
, 0);
543 * Start of a new packet - insert the leading FLAG
544 * character if necessary.
546 if (islcp
|| flag_time
== 0
547 || jiffies
- ap
->last_xmit
>= flag_time
)
549 ap
->last_xmit
= jiffies
;
553 * Put in the address/control bytes if necessary
555 if ((ap
->flags
& SC_COMP_AC
) == 0 || islcp
) {
556 PUT_BYTE(ap
, buf
, 0xff, islcp
);
557 fcs
= PPP_FCS(fcs
, 0xff);
558 PUT_BYTE(ap
, buf
, 0x03, islcp
);
559 fcs
= PPP_FCS(fcs
, 0x03);
564 * Once we put in the last byte, we need to put in the FCS
565 * and closing flag, so make sure there is at least 7 bytes
566 * of free space in the output buffer.
568 buflim
= ap
->obuf
+ OBUFSIZE
- 6;
569 while (i
< count
&& buf
< buflim
) {
571 if (i
== 1 && c
== 0 && (ap
->flags
& SC_COMP_PROT
))
572 continue; /* compress protocol field */
573 fcs
= PPP_FCS(fcs
, c
);
574 PUT_BYTE(ap
, buf
, c
, islcp
);
579 * Remember where we are up to in this packet.
588 * We have finished the packet. Add the FCS and flag.
592 PUT_BYTE(ap
, buf
, c
, islcp
);
593 c
= (fcs
>> 8) & 0xff;
594 PUT_BYTE(ap
, buf
, c
, islcp
);
604 * Transmit-side routines.
608 * Send a packet to the peer over an async tty line.
609 * Returns 1 iff the packet was accepted.
610 * If the packet was not accepted, we will call ppp_output_wakeup
611 * at some later time.
614 ppp_async_send(struct ppp_channel
*chan
, struct sk_buff
*skb
)
616 struct asyncppp
*ap
= chan
->private;
620 if (test_and_set_bit(XMIT_FULL
, &ap
->xmit_flags
))
621 return 0; /* already full */
630 * Push as much data as possible out to the tty.
633 ppp_async_push(struct asyncppp
*ap
)
635 int avail
, sent
, done
= 0;
636 struct tty_struct
*tty
= ap
->tty
;
639 set_bit(XMIT_WAKEUP
, &ap
->xmit_flags
);
640 if (!spin_trylock_bh(&ap
->xmit_lock
))
643 if (test_and_clear_bit(XMIT_WAKEUP
, &ap
->xmit_flags
))
645 if (!tty_stuffed
&& ap
->optr
< ap
->olim
) {
646 avail
= ap
->olim
- ap
->optr
;
647 set_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
);
648 sent
= tty
->driver
.write(tty
, 0, ap
->optr
, avail
);
650 goto flush
; /* error, e.g. loss of CD */
656 if (ap
->optr
== ap
->olim
&& ap
->tpkt
!= 0) {
657 if (ppp_async_encode(ap
)) {
658 /* finished processing ap->tpkt */
659 clear_bit(XMIT_FULL
, &ap
->xmit_flags
);
664 /* haven't made any progress */
665 spin_unlock_bh(&ap
->xmit_lock
);
666 if (!(test_bit(XMIT_WAKEUP
, &ap
->xmit_flags
)
667 || (!tty_stuffed
&& ap
->tpkt
!= 0)))
669 if (!spin_trylock_bh(&ap
->xmit_lock
))
678 clear_bit(XMIT_FULL
, &ap
->xmit_flags
);
682 spin_unlock_bh(&ap
->xmit_lock
);
687 * Flush output from our internal buffers.
688 * Called for the TCFLSH ioctl.
691 ppp_async_flush_output(struct asyncppp
*ap
)
695 spin_lock_bh(&ap
->xmit_lock
);
697 if (ap
->tpkt
!= NULL
) {
700 clear_bit(XMIT_FULL
, &ap
->xmit_flags
);
703 spin_unlock_bh(&ap
->xmit_lock
);
705 ppp_output_wakeup(&ap
->chan
);
709 * Receive-side routines.
712 /* see how many ordinary chars there are at the start of buf */
714 scan_ordinary(struct asyncppp
*ap
, const unsigned char *buf
, int count
)
718 for (i
= 0; i
< count
; ++i
) {
720 if (c
== PPP_ESCAPE
|| c
== PPP_FLAG
721 || (c
< 0x20 && (ap
->raccm
& (1 << c
)) != 0))
727 /* called when a flag is seen - do end-of-packet processing */
729 process_input_packet(struct asyncppp
*ap
)
733 unsigned int len
, fcs
, proto
;
738 if ((ap
->state
& (SC_TOSS
| SC_ESCAPE
)) || skb
== 0) {
739 ap
->state
&= ~(SC_TOSS
| SC_ESCAPE
);
749 goto err
; /* too short */
751 for (; len
> 0; --len
)
752 fcs
= PPP_FCS(fcs
, *p
++);
753 if (fcs
!= PPP_GOODFCS
)
754 goto err
; /* bad FCS */
755 skb_trim(skb
, skb
->len
- 2);
757 /* check for address/control and protocol compression */
759 if (p
[0] == PPP_ALLSTATIONS
&& p
[1] == PPP_UI
) {
760 /* chop off address/control */
763 p
= skb_pull(skb
, 2);
767 /* protocol is compressed */
768 skb_push(skb
, 1)[0] = 0;
772 proto
= (proto
<< 8) + p
[1];
773 if (proto
== PPP_LCP
)
774 async_lcp_peek(ap
, p
, skb
->len
, 1);
777 /* all OK, give it to the generic layer */
778 ppp_input(&ap
->chan
, skb
);
783 ppp_input_error(&ap
->chan
, code
);
787 input_error(struct asyncppp
*ap
, int code
)
789 ap
->state
|= SC_TOSS
;
790 ppp_input_error(&ap
->chan
, code
);
793 /* called when the tty driver has data for us. */
795 ppp_async_input(struct asyncppp
*ap
, const unsigned char *buf
,
796 char *flags
, int count
)
799 int c
, i
, j
, n
, s
, f
;
802 /* update bits used for 8-bit cleanness detection */
803 if (~ap
->rbits
& SC_RCV_BITS
) {
805 for (i
= 0; i
< count
; ++i
) {
807 if (flags
!= 0 && flags
[i
] != 0)
809 s
|= (c
& 0x80)? SC_RCV_B7_1
: SC_RCV_B7_0
;
810 c
= ((c
>> 4) ^ c
) & 0xf;
811 s
|= (0x6996 & (1 << c
))? SC_RCV_ODDP
: SC_RCV_EVNP
;
817 /* scan through and see how many chars we can do in bulk */
818 if ((ap
->state
& SC_ESCAPE
) && buf
[0] == PPP_ESCAPE
)
821 n
= scan_ordinary(ap
, buf
, count
);
824 if (flags
!= 0 && (ap
->state
& SC_TOSS
) == 0) {
825 /* check the flags to see if any char had an error */
826 for (j
= 0; j
< n
; ++j
)
827 if ((f
= flags
[j
]) != 0)
834 } else if (n
> 0 && (ap
->state
& SC_TOSS
) == 0) {
835 /* stuff the chars in the skb */
838 skb
= dev_alloc_skb(ap
->mru
+ PPP_HDRLEN
+ 2);
841 /* Try to get the payload 4-byte aligned */
842 if (buf
[0] != PPP_ALLSTATIONS
)
843 skb_reserve(skb
, 2 + (buf
[0] & 1));
846 if (n
> skb_tailroom(skb
)) {
847 /* packet overflowed MRU */
850 sp
= skb_put(skb
, n
);
852 if (ap
->state
& SC_ESCAPE
) {
854 ap
->state
&= ~SC_ESCAPE
;
864 process_input_packet(ap
);
865 } else if (c
== PPP_ESCAPE
) {
866 ap
->state
|= SC_ESCAPE
;
868 /* otherwise it's a char in the recv ACCM */
879 printk(KERN_ERR
"PPPasync: no memory (input pkt)\n");
884 * We look at LCP frames going past so that we can notice
885 * and react to the LCP configure-ack from the peer.
886 * In the situation where the peer has been sent a configure-ack
887 * already, LCP is up once it has sent its configure-ack
888 * so the immediately following packet can be sent with the
889 * configured LCP options. This allows us to process the following
890 * packet correctly without pppd needing to respond quickly.
892 * We only respond to the received configure-ack if we have just
893 * sent a configure-request, and the configure-ack contains the
894 * same data (this is checked using a 16-bit crc of the data).
896 #define CONFREQ 1 /* LCP code field values */
898 #define LCP_MRU 1 /* LCP option numbers */
899 #define LCP_ASYNCMAP 2
901 static void async_lcp_peek(struct asyncppp
*ap
, unsigned char *data
,
902 int len
, int inbound
)
904 int dlen
, fcs
, i
, code
;
907 data
+= 2; /* skip protocol bytes */
909 if (len
< 4) /* 4 = code, ID, length */
912 if (code
!= CONFACK
&& code
!= CONFREQ
)
914 dlen
= (data
[2] << 8) + data
[3];
916 return; /* packet got truncated or length is bogus */
918 if (code
== (inbound
? CONFACK
: CONFREQ
)) {
920 * sent confreq or received confack:
921 * calculate the crc of the data from the ID field on.
924 for (i
= 1; i
< dlen
; ++i
)
925 fcs
= PPP_FCS(fcs
, data
[i
]);
928 /* outbound confreq - remember the crc for later */
933 /* received confack, check the crc */
939 return; /* not interested in received confreq */
941 /* process the options in the confack */
944 /* data[0] is code, data[1] is length */
945 while (dlen
>= 2 && dlen
>= data
[1]) {
948 val
= (data
[2] << 8) + data
[3];
955 val
= (data
[2] << 24) + (data
[3] << 16)
956 + (data
[4] << 8) + data
[5];
968 void __exit
ppp_async_cleanup(void)
970 if (tty_register_ldisc(N_PPP
, NULL
) != 0)
971 printk(KERN_ERR
"failed to unregister PPP line discipline\n");
974 module_init(ppp_async_init
);
975 module_exit(ppp_async_cleanup
);