^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * PPP synchronous tty channel driver for Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This is a ppp channel driver that can be used with tty device drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * that are frame oriented, such as synchronous HDLC devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Complete PPP frames without encoding/decoding are exchanged between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * the channel driver and the device driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * The async map IOCTL codes are implemented to keep the user mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * applications happy if they call them. Synchronous PPP does not use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * the async maps.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Copyright 1999 Paul Mackerras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Also touched by the grubby hands of Paul Fulghum paulkf@microgate.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * This driver provides the encapsulation and framing for sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * and receiving PPP frames over sync serial lines. It relies on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * the generic PPP layer to give it frames to send and to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * received frames. It implements the PPP line discipline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Part of the code in this driver was inspired by the old async-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * PPP driver, written by Michael Callahan and Al Longyear, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * subsequently hacked by Paul Mackerras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * ==FILEVERSION 20040616==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/ppp_defs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/ppp-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/ppp_channel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #include <linux/refcount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define PPP_VERSION "2.4.2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* Structure for storing local state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct syncppp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct tty_struct *tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned int rbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int mru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) spinlock_t xmit_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) spinlock_t recv_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) unsigned long xmit_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) u32 xaccm[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 raccm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int bytes_sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int bytes_rcvd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct sk_buff *tpkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned long last_xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct sk_buff_head rqueue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct tasklet_struct tsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) refcount_t refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct completion dead_cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct ppp_channel chan; /* interface to generic ppp layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /* Bit numbers in xmit_flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define XMIT_WAKEUP 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define XMIT_FULL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Bits in rbits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define PPPSYNC_MAX_RQLEN 32 /* arbitrary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Prototypes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static void ppp_sync_process(unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int ppp_sync_push(struct syncppp *ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static void ppp_sync_flush_output(struct syncppp *ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) char *flags, int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static const struct ppp_channel_ops sync_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .start_xmit = ppp_sync_send,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .ioctl = ppp_sync_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * Utility procedure to print a buffer in hex/ascii
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ppp_print_buffer (const char *name, const __u8 *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (name != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) printk(KERN_DEBUG "ppp_synctty: %s, count = %d\n", name, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) print_hex_dump_bytes("", DUMP_PREFIX_NONE, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * Routines implementing the synchronous PPP line discipline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * We have a potential race on dereferencing tty->disc_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * because the tty layer provides no locking at all - thus one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * cpu could be running ppp_synctty_receive while another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * calls ppp_synctty_close, which zeroes tty->disc_data and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * frees the memory that ppp_synctty_receive is using. The best
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * way to fix this is to use a rwlock in the tty struct, but for now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * we use a single global rwlock for all ttys in ppp line discipline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * FIXME: Fixed in tty_io nowadays.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static DEFINE_RWLOCK(disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static struct syncppp *sp_get(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct syncppp *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) read_lock(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ap = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (ap != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) refcount_inc(&ap->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) read_unlock(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static void sp_put(struct syncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (refcount_dec_and_test(&ap->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) complete(&ap->dead_cmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Called when a tty is put into sync-PPP line discipline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ppp_sync_open(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct syncppp *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (tty->ops->write == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ap = kzalloc(sizeof(*ap), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* initialize the syncppp structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ap->tty = tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ap->mru = PPP_MRU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) spin_lock_init(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) spin_lock_init(&ap->recv_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ap->xaccm[0] = ~0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ap->xaccm[3] = 0x60000000U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ap->raccm = ~0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) skb_queue_head_init(&ap->rqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) refcount_set(&ap->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) init_completion(&ap->dead_cmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ap->chan.private = ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) ap->chan.ops = &sync_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ap->chan.mtu = PPP_MRU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ap->chan.hdrlen = 2; /* for A/C bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) speed = tty_get_baud_rate(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ap->chan.speed = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) err = ppp_register_channel(&ap->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) tty->disc_data = ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) tty->receive_room = 65536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) kfree(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * Called when the tty is put into another line discipline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * or it hangs up. We have to wait for any cpu currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * executing in any of the other ppp_synctty_* routines to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * finish before we can call ppp_unregister_channel and free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * the syncppp struct. This routine must be called from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * process context, not interrupt or softirq context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ppp_sync_close(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct syncppp *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) write_lock_irq(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ap = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) tty->disc_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) write_unlock_irq(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * We have now ensured that nobody can start using ap from now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * on, but we have to wait for all existing users to finish.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * Note that ppp_unregister_channel ensures that no calls to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * our channel ops (i.e. ppp_sync_send/ioctl) are in progress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * by the time it returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (!refcount_dec_and_test(&ap->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) wait_for_completion(&ap->dead_cmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) tasklet_kill(&ap->tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ppp_unregister_channel(&ap->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) skb_queue_purge(&ap->rqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) kfree_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) kfree(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * Called on tty hangup in process context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * Wait for I/O to driver to complete and unregister PPP channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * This is already done by the close routine, so just call that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static int ppp_sync_hangup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) ppp_sync_close(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * Read does nothing - no data is ever available this way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * Pppd reads and writes packets via /dev/ppp instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) ppp_sync_read(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) void **cookie, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * Write on the tty does nothing, the packets all come in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * from the ppp generic stuff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ppp_sync_write(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) const unsigned char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) struct syncppp *ap = sp_get(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) int __user *p = (int __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) int err, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) case PPPIOCGCHAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (put_user(ppp_channel_index(&ap->chan), p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case PPPIOCGUNIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (put_user(ppp_unit_number(&ap->chan), p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case TCFLSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* flush our buffers and the serial port's buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (arg == TCIOFLUSH || arg == TCOFLUSH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ppp_sync_flush_output(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) err = n_tty_ioctl_helper(tty, file, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) case FIONREAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (put_user(val, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) err = tty_mode_ioctl(tty, file, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) sp_put(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) /* No kernel lock - fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) static __poll_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) /* May sleep, don't call from interrupt level or with interrupts disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) char *cflags, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct syncppp *ap = sp_get(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) spin_lock_irqsave(&ap->recv_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ppp_sync_input(ap, buf, cflags, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) spin_unlock_irqrestore(&ap->recv_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (!skb_queue_empty(&ap->rqueue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) tasklet_schedule(&ap->tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) sp_put(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) tty_unthrottle(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ppp_sync_wakeup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct syncppp *ap = sp_get(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) set_bit(XMIT_WAKEUP, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) tasklet_schedule(&ap->tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) sp_put(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static struct tty_ldisc_ops ppp_sync_ldisc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .magic = TTY_LDISC_MAGIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) .name = "pppsync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) .open = ppp_sync_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) .close = ppp_sync_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .hangup = ppp_sync_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .read = ppp_sync_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .write = ppp_sync_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) .ioctl = ppp_synctty_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) .poll = ppp_sync_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) .receive_buf = ppp_sync_receive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) .write_wakeup = ppp_sync_wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ppp_sync_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) printk(KERN_ERR "PPP_sync: error %d registering line disc.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * The following routines provide the PPP channel interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct syncppp *ap = chan->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int err, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) u32 accm[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) u32 __user *p = argp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) case PPPIOCGFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) val = ap->flags | ap->rbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (put_user(val, (int __user *) argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) case PPPIOCSFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) if (get_user(val, (int __user *) argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ap->flags = val & ~SC_RCV_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) spin_lock_irq(&ap->recv_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ap->rbits = val & SC_RCV_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) spin_unlock_irq(&ap->recv_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) case PPPIOCGASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (put_user(ap->xaccm[0], p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case PPPIOCSASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (get_user(ap->xaccm[0], p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case PPPIOCGRASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (put_user(ap->raccm, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) case PPPIOCSRASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (get_user(ap->raccm, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case PPPIOCGXASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case PPPIOCSXASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (copy_from_user(accm, argp, sizeof(accm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) accm[2] &= ~0x40000000U; /* can't escape 0x5e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) case PPPIOCGMRU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (put_user(ap->mru, (int __user *) argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) case PPPIOCSMRU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (get_user(val, (int __user *) argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (val < PPP_MRU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) val = PPP_MRU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) ap->mru = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) err = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * This is called at softirq level to deliver received packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * to the ppp_generic code, and to tell the ppp_generic code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) * if we can accept more output now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static void ppp_sync_process(unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) struct syncppp *ap = (struct syncppp *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* process received packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if (skb->len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* zero length buffers indicate error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) ppp_input_error(&ap->chan, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ppp_input(&ap->chan, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) /* try to push more stuff out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_sync_push(ap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ppp_output_wakeup(&ap->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * Procedures for encapsulation and framing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static struct sk_buff*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) int proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) int islcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) data = skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) proto = get_unaligned_be16(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) /* LCP packets with codes between 1 (configure-request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * and 7 (code-reject) must be sent as though no options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * have been negotiated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* compress protocol field if option enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (data[0] == 0 && (ap->flags & SC_COMP_PROT) && !islcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) skb_pull(skb,1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) /* prepend address/control fields if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (skb_headroom(skb) < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) struct sk_buff *npkt = dev_alloc_skb(skb->len + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (npkt == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) kfree_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) skb_reserve(npkt,2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) skb_copy_from_linear_data(skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) skb_put(npkt, skb->len), skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) consume_skb(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) skb = npkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) skb_push(skb,2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) skb->data[0] = PPP_ALLSTATIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) skb->data[1] = PPP_UI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) ap->last_xmit = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (skb && ap->flags & SC_LOG_OUTPKT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) ppp_print_buffer ("send buffer", skb->data, skb->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * Transmit-side routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * Send a packet to the peer over an sync tty line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * Returns 1 iff the packet was accepted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) * If the packet was not accepted, we will call ppp_output_wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * at some later time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct syncppp *ap = chan->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) ppp_sync_push(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return 0; /* already full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) skb = ppp_sync_txmunge(ap, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (skb != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) ap->tpkt = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) clear_bit(XMIT_FULL, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ppp_sync_push(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * Push as much data as possible out to the tty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) ppp_sync_push(struct syncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) int sent, done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct tty_struct *tty = ap->tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) int tty_stuffed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!spin_trylock_bh(&ap->xmit_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) tty_stuffed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (!tty_stuffed && ap->tpkt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) sent = tty->ops->write(tty, ap->tpkt->data, ap->tpkt->len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (sent < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) goto flush; /* error, e.g. loss of CD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (sent < ap->tpkt->len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) tty_stuffed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) consume_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) ap->tpkt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) clear_bit(XMIT_FULL, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /* haven't made any progress */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) spin_unlock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) (!tty_stuffed && ap->tpkt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (!spin_trylock_bh(&ap->xmit_lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) return done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) flush:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (ap->tpkt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) kfree_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) ap->tpkt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) clear_bit(XMIT_FULL, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) spin_unlock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * Flush output from our internal buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * Called for the TCFLSH ioctl.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) ppp_sync_flush_output(struct syncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) spin_lock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (ap->tpkt != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) kfree_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) ap->tpkt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) clear_bit(XMIT_FULL, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) spin_unlock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) ppp_output_wakeup(&ap->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * Receive-side routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) /* called when the tty driver has data for us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * Data is frame oriented: each call to ppp_sync_input is considered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * a whole frame. If the 1st flag byte is non-zero then the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * frame is considered to be in error and is tossed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) char *flags, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) unsigned char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) if (ap->flags & SC_LOG_INPKT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ppp_print_buffer ("receive buffer", buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* stuff the chars in the skb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /* Try to get the payload 4-byte aligned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) if (buf[0] != PPP_ALLSTATIONS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) skb_reserve(skb, 2 + (buf[0] & 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (flags && *flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /* error flag set, ignore frame */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) } else if (count > skb_tailroom(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* packet overflowed MRU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) skb_put_data(skb, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* strip address/control field if present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) p = skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) /* chop off address/control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (skb->len < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) p = skb_pull(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* PPP packet length should be >= 2 bytes when protocol field is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) * compressed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (!(p[0] & 0x01) && skb->len < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /* queue the frame to be processed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) skb_queue_tail(&ap->rqueue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) /* queue zero length packet as error indication */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (skb || (skb = dev_alloc_skb(0))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) skb_trim(skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) skb_queue_tail(&ap->rqueue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static void __exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) ppp_sync_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (tty_unregister_ldisc(N_SYNC_PPP) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) printk(KERN_ERR "failed to unregister Sync PPP line discipline\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) module_init(ppp_sync_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) module_exit(ppp_sync_cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) MODULE_ALIAS_LDISC(N_SYNC_PPP);