Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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 async serial channel driver for Linux.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Copyright 1999 Paul Mackerras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  * This driver provides the encapsulation and framing for sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  * and receiving PPP frames over async serial lines.  It relies on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  * the generic PPP layer to give it frames to send and to process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  * received frames.  It implements the PPP line discipline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  * Part of the code in this driver was inspired by the old async-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  * PPP driver, written by Michael Callahan and Al Longyear, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  * subsequently hacked by Paul Mackerras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <linux/skbuff.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/crc-ccitt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/ppp_defs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/ppp-ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/ppp_channel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <asm/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #define PPP_VERSION	"2.4.2"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #define OBUFSIZE	4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) /* Structure for storing local state. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) struct asyncppp {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 	struct tty_struct *tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 	unsigned int	flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	unsigned int	state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 	unsigned int	rbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 	int		mru;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 	spinlock_t	xmit_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	spinlock_t	recv_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 	unsigned long	xmit_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	u32		xaccm[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	u32		raccm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	unsigned int	bytes_sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	unsigned int	bytes_rcvd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	struct sk_buff	*tpkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	int		tpkt_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 	u16		tfcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 	unsigned char	*optr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 	unsigned char	*olim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 	unsigned long	last_xmit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 	struct sk_buff	*rpkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	int		lcp_fcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	struct sk_buff_head rqueue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 	struct tasklet_struct tsk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 	refcount_t	refcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 	struct completion dead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	struct ppp_channel chan;	/* interface to generic ppp layer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	unsigned char	obuf[OBUFSIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) /* Bit numbers in xmit_flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #define XMIT_WAKEUP	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) #define XMIT_FULL	1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) #define XMIT_BUSY	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) /* State bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) #define SC_TOSS		1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) #define SC_ESCAPE	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) #define SC_PREV_ERROR	4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) /* Bits in rbits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) #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   86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) static int flag_time = HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) module_param(flag_time, int, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) MODULE_ALIAS_LDISC(N_PPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94)  * Prototypes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) static int ppp_async_encode(struct asyncppp *ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) static int ppp_async_push(struct asyncppp *ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static void ppp_async_flush_output(struct asyncppp *ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 			    char *flags, int count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 			   unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) static void ppp_async_process(unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 			   int len, int inbound);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) static const struct ppp_channel_ops async_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 	.start_xmit = ppp_async_send,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	.ioctl      = ppp_async_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115)  * Routines implementing the PPP line discipline.
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119)  * We have a potential race on dereferencing tty->disc_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120)  * because the tty layer provides no locking at all - thus one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121)  * cpu could be running ppp_asynctty_receive while another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122)  * calls ppp_asynctty_close, which zeroes tty->disc_data and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123)  * frees the memory that ppp_asynctty_receive is using.  The best
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124)  * 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  125)  * we use a single global rwlock for all ttys in ppp line discipline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127)  * FIXME: this is no longer true. The _close path for the ldisc is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128)  * now guaranteed to be sane.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) static DEFINE_RWLOCK(disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) static struct asyncppp *ap_get(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	struct asyncppp *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	read_lock(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 	ap = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	if (ap != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 		refcount_inc(&ap->refcnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	read_unlock(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	return ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) static void ap_put(struct asyncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	if (refcount_dec_and_test(&ap->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		complete(&ap->dead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151)  * Called when a tty is put into PPP line discipline. Called in process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152)  * context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) ppp_asynctty_open(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	struct asyncppp *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	int speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	if (tty->ops->write == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 		return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	err = -ENOMEM;
^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) 	if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	/* initialize the asyncppp structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 	ap->tty = tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	ap->mru = PPP_MRU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	spin_lock_init(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	spin_lock_init(&ap->recv_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	ap->xaccm[0] = ~0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	ap->xaccm[3] = 0x60000000U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	ap->raccm = ~0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	ap->optr = ap->obuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	ap->olim = ap->obuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 	ap->lcp_fcs = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 	skb_queue_head_init(&ap->rqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	refcount_set(&ap->refcnt, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	init_completion(&ap->dead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	ap->chan.private = ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	ap->chan.ops = &async_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 	ap->chan.mtu = PPP_MRU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	speed = tty_get_baud_rate(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 	ap->chan.speed = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 	err = ppp_register_channel(&ap->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 	if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 	tty->disc_data = ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	tty->receive_room = 65536;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200)  out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	kfree(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)  out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 	return err;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207)  * Called when the tty is put into another line discipline
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208)  * or it hangs up.  We have to wait for any cpu currently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209)  * executing in any of the other ppp_asynctty_* routines to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210)  * finish before we can call ppp_unregister_channel and free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211)  * the asyncppp struct.  This routine must be called from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212)  * process context, not interrupt or softirq context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) ppp_asynctty_close(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	struct asyncppp *ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	write_lock_irq(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	ap = tty->disc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	tty->disc_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	write_unlock_irq(&disc_data_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	 * We have now ensured that nobody can start using ap from now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	 * on, but we have to wait for all existing users to finish.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	 * Note that ppp_unregister_channel ensures that no calls to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	 * our channel ops (i.e. ppp_async_send/ioctl) are in progress
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	 * by the time it returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	if (!refcount_dec_and_test(&ap->refcnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		wait_for_completion(&ap->dead);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	tasklet_kill(&ap->tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	ppp_unregister_channel(&ap->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	kfree_skb(ap->rpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	skb_queue_purge(&ap->rqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 	kfree_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 	kfree(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245)  * Called on tty hangup in process context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247)  * Wait for I/O to driver to complete and unregister PPP channel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248)  * This is already done by the close routine, so just call that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) static int ppp_asynctty_hangup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	ppp_asynctty_close(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257)  * Read does nothing - no data is ever available this way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258)  * Pppd reads and writes packets via /dev/ppp instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) ppp_asynctty_read(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 		  unsigned char *buf, size_t count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 		  void **cookie, unsigned long offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269)  * Write on the tty does nothing, the packets all come in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270)  * from the ppp generic stuff.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) ppp_asynctty_write(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 		   const unsigned char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280)  * Called in process context only. May be re-entered by multiple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281)  * ioctl calling threads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 		   unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 	struct asyncppp *ap = ap_get(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 	int err, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	int __user *p = (int __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	case PPPIOCGCHAN:
^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_channel_index(&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 PPPIOCGUNIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 		err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 		if (put_user(ppp_unit_number(&ap->chan), p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 		err = 0;
^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 TCFLSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 		/* flush our buffers and the serial port's buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 		if (arg == TCIOFLUSH || arg == TCOFLUSH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 			ppp_async_flush_output(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 		err = n_tty_ioctl_helper(tty, file, cmd, arg);
^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) 	case FIONREAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 		val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) 		if (put_user(val, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 		/* Try the various mode ioctls */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 		err = tty_mode_ioctl(tty, file, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	ap_put(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	return err;
^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) /* No kernel lock - fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) static __poll_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) /* May sleep, don't call from interrupt level or with interrupts disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 		  char *cflags, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 	struct asyncppp *ap = ap_get(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	spin_lock_irqsave(&ap->recv_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	ppp_async_input(ap, buf, cflags, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	spin_unlock_irqrestore(&ap->recv_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	if (!skb_queue_empty(&ap->rqueue))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		tasklet_schedule(&ap->tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	ap_put(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	tty_unthrottle(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) ppp_asynctty_wakeup(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	struct asyncppp *ap = ap_get(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	if (!ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	set_bit(XMIT_WAKEUP, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	tasklet_schedule(&ap->tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	ap_put(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) static struct tty_ldisc_ops ppp_ldisc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 	.owner  = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 	.magic	= TTY_LDISC_MAGIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	.name	= "ppp",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	.open	= ppp_asynctty_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	.close	= ppp_asynctty_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	.hangup	= ppp_asynctty_hangup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	.read	= ppp_asynctty_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	.write	= ppp_asynctty_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	.ioctl	= ppp_asynctty_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	.poll	= ppp_asynctty_poll,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) 	.receive_buf = ppp_asynctty_receive,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 	.write_wakeup = ppp_asynctty_wakeup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) static int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) ppp_async_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	err = tty_register_ldisc(N_PPP, &ppp_ldisc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 		printk(KERN_ERR "PPP_async: error %d registering line disc.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		       err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401)  * The following routines provide the PPP channel interface.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	struct asyncppp *ap = chan->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	void __user *argp = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	int __user *p = argp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	int err, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	u32 accm[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	err = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	case PPPIOCGFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		val = ap->flags | ap->rbits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		if (put_user(val, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 	case PPPIOCSFLAGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 		if (get_user(val, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		ap->flags = val & ~SC_RCV_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		spin_lock_irq(&ap->recv_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 		ap->rbits = val & SC_RCV_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 		spin_unlock_irq(&ap->recv_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 	case PPPIOCGASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		if (put_user(ap->xaccm[0], (u32 __user *)argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	case PPPIOCSASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 		if (get_user(ap->xaccm[0], (u32 __user *)argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	case PPPIOCGRASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 		if (put_user(ap->raccm, (u32 __user *)argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 	case PPPIOCSRASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		if (get_user(ap->raccm, (u32 __user *)argp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 	case PPPIOCGXASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	case PPPIOCSXASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		if (copy_from_user(accm, argp, sizeof(accm)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		accm[3] |= 0x60000000U;		/* must escape 0x7d, 0x7e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	case PPPIOCGMRU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		if (put_user(ap->mru, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 	case PPPIOCSMRU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 		if (get_user(val, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		if (val < PPP_MRU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 			val = PPP_MRU;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		ap->mru = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 		err = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488)  * This is called at softirq level to deliver received packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489)  * to the ppp_generic code, and to tell the ppp_generic code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490)  * if we can accept more output now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) static void ppp_async_process(unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	struct asyncppp *ap = (struct asyncppp *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	/* process received packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 		if (skb->cb[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 			ppp_input_error(&ap->chan, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		ppp_input(&ap->chan, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 	/* try to push more stuff out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_async_push(ap))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		ppp_output_wakeup(&ap->chan);
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510)  * Procedures for encapsulation and framing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514)  * Procedure to encode the data for async serial transmission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515)  * Does octet stuffing (escaping), puts the address/control bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516)  * on if A/C compression is disabled, and does protocol compression.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517)  * Assumes ap->tpkt != 0 on entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518)  * Returns 1 if we finished the current frame, 0 otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) #define PUT_BYTE(ap, buf, c, islcp)	do {		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 	if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		*buf++ = PPP_ESCAPE;			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 		*buf++ = c ^ PPP_TRANS;			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	} else						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 		*buf++ = c;				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) ppp_async_encode(struct asyncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	int fcs, i, count, c, proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	unsigned char *buf, *buflim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	int islcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	buf = ap->obuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	ap->olim = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	ap->optr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	i = ap->tpkt_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	data = ap->tpkt->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	count = ap->tpkt->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	fcs = ap->tfcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	proto = get_unaligned_be16(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	 * LCP packets with code values between 1 (configure-reqest)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	 * and 7 (code-reject) must be sent as though no options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	 * had been negotiated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	if (i == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 		if (islcp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 			async_lcp_peek(ap, data, count, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 		 * Start of a new packet - insert the leading FLAG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 		 * character if necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 		if (islcp || flag_time == 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 		    time_after_eq(jiffies, ap->last_xmit + flag_time))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 			*buf++ = PPP_FLAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 		ap->last_xmit = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		fcs = PPP_INITFCS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 		 * Put in the address/control bytes if necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 			PUT_BYTE(ap, buf, 0xff, islcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 			fcs = PPP_FCS(fcs, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 			PUT_BYTE(ap, buf, 0x03, islcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 			fcs = PPP_FCS(fcs, 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	 * Once we put in the last byte, we need to put in the FCS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 	 * and closing flag, so make sure there is at least 7 bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	 * of free space in the output buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	buflim = ap->obuf + OBUFSIZE - 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	while (i < count && buf < buflim) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		c = data[i++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		if (i == 1 && c == 0 && (ap->flags & SC_COMP_PROT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 			continue;	/* compress protocol field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		fcs = PPP_FCS(fcs, c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		PUT_BYTE(ap, buf, c, islcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	if (i < count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 		 * Remember where we are up to in this packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 		ap->olim = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		ap->tpkt_pos = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 		ap->tfcs = fcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	 * We have finished the packet.  Add the FCS and flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	fcs = ~fcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	c = fcs & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	PUT_BYTE(ap, buf, c, islcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	c = (fcs >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	PUT_BYTE(ap, buf, c, islcp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	*buf++ = PPP_FLAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 	ap->olim = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	consume_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	ap->tpkt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619)  * Transmit-side routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623)  * Send a packet to the peer over an async tty line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624)  * Returns 1 iff the packet was accepted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625)  * If the packet was not accepted, we will call ppp_output_wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626)  * at some later time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	struct asyncppp *ap = chan->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	ppp_async_push(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	if (test_and_set_bit(XMIT_FULL, &ap->xmit_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		return 0;	/* already full */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	ap->tpkt = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	ap->tpkt_pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	ppp_async_push(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645)  * Push as much data as possible out to the tty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) ppp_async_push(struct asyncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	int avail, sent, done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	struct tty_struct *tty = ap->tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	int tty_stuffed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 	 * We can get called recursively here if the tty write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 	 * function calls our wakeup function.  This can happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 	 * for example on a pty with both the master and slave
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 	 * set to PPP line discipline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	 * We use the XMIT_BUSY bit to detect this and get out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	 * leaving the XMIT_WAKEUP bit set to tell the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	 * instance that it may now be able to write more now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 	if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 	spin_lock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 		if (test_and_clear_bit(XMIT_WAKEUP, &ap->xmit_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 			tty_stuffed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 		if (!tty_stuffed && ap->optr < ap->olim) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 			avail = ap->olim - ap->optr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 			set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 			sent = tty->ops->write(tty, ap->optr, avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 			if (sent < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 				goto flush;	/* error, e.g. loss of CD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 			ap->optr += sent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 			if (sent < avail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 				tty_stuffed = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 		if (ap->optr >= ap->olim && ap->tpkt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 			if (ppp_async_encode(ap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 				/* finished processing ap->tpkt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 				clear_bit(XMIT_FULL, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 				done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 		 * We haven't made any progress this time around.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 		 * Clear XMIT_BUSY to let other callers in, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 		 * after doing so we have to check if anyone set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 		 * XMIT_WAKEUP since we last checked it.  If they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 		 * did, we should try again to set XMIT_BUSY and go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		 * around again in case XMIT_BUSY was still set when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		 * the other caller tried.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		clear_bit(XMIT_BUSY, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 		/* any more work to do? if not, exit the loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		if (!(test_bit(XMIT_WAKEUP, &ap->xmit_flags) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 		      (!tty_stuffed && ap->tpkt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		/* more work to do, see if we can do it now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		if (test_and_set_bit(XMIT_BUSY, &ap->xmit_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	spin_unlock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	return done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) flush:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	clear_bit(XMIT_BUSY, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	if (ap->tpkt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		kfree_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		ap->tpkt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 		clear_bit(XMIT_FULL, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 		done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	ap->optr = ap->olim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	spin_unlock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	return done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723)  * Flush output from our internal buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724)  * Called for the TCFLSH ioctl. Can be entered in parallel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725)  * but this is covered by the xmit_lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) ppp_async_flush_output(struct asyncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	int done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 	spin_lock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 	ap->optr = ap->olim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 	if (ap->tpkt != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 		kfree_skb(ap->tpkt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		ap->tpkt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		clear_bit(XMIT_FULL, &ap->xmit_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 		done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	spin_unlock_bh(&ap->xmit_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 	if (done)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 		ppp_output_wakeup(&ap->chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746)  * Receive-side routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) /* see how many ordinary chars there are at the start of buf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) scan_ordinary(struct asyncppp *ap, const unsigned char *buf, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	int i, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	for (i = 0; i < count; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		c = buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 		if (c == PPP_ESCAPE || c == PPP_FLAG ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 		    (c < 0x20 && (ap->raccm & (1 << c)) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) /* called when a flag is seen - do end-of-packet processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) process_input_packet(struct asyncppp *ap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	unsigned char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	unsigned int len, fcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	skb = ap->rpkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	if (ap->state & (SC_TOSS | SC_ESCAPE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	if (skb == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 		return;		/* 0-length packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	/* check the FCS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	p = skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	len = skb->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 	if (len < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 		goto err;	/* too short */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 	fcs = PPP_INITFCS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	for (; len > 0; --len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 		fcs = PPP_FCS(fcs, *p++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	if (fcs != PPP_GOODFCS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 		goto err;	/* bad FCS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 	skb_trim(skb, skb->len - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 	/* check for address/control and protocol compression */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	p = skb->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	if (p[0] == PPP_ALLSTATIONS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 		/* chop off address/control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 		if (p[1] != PPP_UI || skb->len < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 		p = skb_pull(skb, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	/* If protocol field is not compressed, it can be LCP packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	if (!(p[0] & 0x01)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 		unsigned int proto;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 		if (skb->len < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 		proto = (p[0] << 8) + p[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		if (proto == PPP_LCP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 			async_lcp_peek(ap, p, skb->len, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	/* queue the frame to be processed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 	skb->cb[0] = ap->state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	skb_queue_tail(&ap->rqueue, skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 	ap->rpkt = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	ap->state = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818)  err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	/* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	ap->state = SC_PREV_ERROR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 	if (skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 		/* make skb appear as freshly allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 		skb_trim(skb, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		skb_reserve(skb, - skb_headroom(skb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) /* Called when the tty driver has data for us. Runs parallel with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829)    other ldisc functions but will not be re-entered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 		char *flags, int count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	struct sk_buff *skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 	int c, i, j, n, s, f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	unsigned char *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	/* update bits used for 8-bit cleanness detection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 	if (~ap->rbits & SC_RCV_BITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 		s = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		for (i = 0; i < count; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 			c = buf[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 			if (flags && flags[i] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 			s |= (c & 0x80)? SC_RCV_B7_1: SC_RCV_B7_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 			c = ((c >> 4) ^ c) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 			s |= (0x6996 & (1 << c))? SC_RCV_ODDP: SC_RCV_EVNP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		ap->rbits |= s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	while (count > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		/* scan through and see how many chars we can do in bulk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		if ((ap->state & SC_ESCAPE) && buf[0] == PPP_ESCAPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 			n = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			n = scan_ordinary(ap, buf, count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		f = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 		if (flags && (ap->state & SC_TOSS) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 			/* check the flags to see if any char had an error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 			for (j = 0; j < n; ++j)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 				if ((f = flags[j]) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		if (f != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 			/* start tossing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 			ap->state |= SC_TOSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		} else if (n > 0 && (ap->state & SC_TOSS) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 			/* stuff the chars in the skb */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 			skb = ap->rpkt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 			if (!skb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 				skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 				if (!skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 					goto nomem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 				ap->rpkt = skb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 			if (skb->len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 				/* Try to get the payload 4-byte aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 				 * This should match the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 				 * PPP_ALLSTATIONS/PPP_UI/compressed tests in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 				 * process_input_packet, but we do not have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 				 * enough chars here to test buf[1] and buf[2].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 				if (buf[0] != PPP_ALLSTATIONS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 					skb_reserve(skb, 2 + (buf[0] & 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 			if (n > skb_tailroom(skb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 				/* packet overflowed MRU */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 				ap->state |= SC_TOSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 				sp = skb_put_data(skb, buf, n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 				if (ap->state & SC_ESCAPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 					sp[0] ^= PPP_TRANS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 					ap->state &= ~SC_ESCAPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		if (n >= count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		c = buf[n];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		if (flags != NULL && flags[n] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 			ap->state |= SC_TOSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 		} else if (c == PPP_FLAG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 			process_input_packet(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		} else if (c == PPP_ESCAPE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 			ap->state |= SC_ESCAPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		} else if (I_IXON(ap->tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 			if (c == START_CHAR(ap->tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 				start_tty(ap->tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 			else if (c == STOP_CHAR(ap->tty))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 				stop_tty(ap->tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 		/* otherwise it's a char in the recv ACCM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 		++n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		buf += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 		if (flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 			flags += n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 		count -= n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928)  nomem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	printk(KERN_ERR "PPPasync: no memory (input pkt)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	ap->state |= SC_TOSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934)  * We look at LCP frames going past so that we can notice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935)  * and react to the LCP configure-ack from the peer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936)  * In the situation where the peer has been sent a configure-ack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937)  * already, LCP is up once it has sent its configure-ack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938)  * so the immediately following packet can be sent with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939)  * configured LCP options.  This allows us to process the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940)  * packet correctly without pppd needing to respond quickly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942)  * We only respond to the received configure-ack if we have just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943)  * sent a configure-request, and the configure-ack contains the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944)  * same data (this is checked using a 16-bit crc of the data).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) #define CONFREQ		1	/* LCP code field values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) #define CONFACK		2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) #define LCP_MRU		1	/* LCP option numbers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) #define LCP_ASYNCMAP	2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 			   int len, int inbound)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	int dlen, fcs, i, code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	data += 2;		/* skip protocol bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 	len -= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	if (len < 4)		/* 4 = code, ID, length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	code = data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	if (code != CONFACK && code != CONFREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	dlen = get_unaligned_be16(data + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	if (len < dlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		return;		/* packet got truncated or length is bogus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	if (code == (inbound? CONFACK: CONFREQ)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		 * sent confreq or received confack:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		 * calculate the crc of the data from the ID field on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 		fcs = PPP_INITFCS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		for (i = 1; i < dlen; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 			fcs = PPP_FCS(fcs, data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		if (!inbound) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 			/* outbound confreq - remember the crc for later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 			ap->lcp_fcs = fcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 		/* received confack, check the crc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		fcs ^= ap->lcp_fcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 		ap->lcp_fcs = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 		if (fcs != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 			return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	} else if (inbound)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 		return;	/* not interested in received confreq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	/* process the options in the confack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	data += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	dlen -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	/* data[0] is code, data[1] is length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		switch (data[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 		case LCP_MRU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 			val = get_unaligned_be16(data + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 			if (inbound)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 				ap->mru = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 				ap->chan.mtu = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		case LCP_ASYNCMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 			val = get_unaligned_be32(data + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			if (inbound)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 				ap->raccm = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 				ap->xaccm[0] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 		dlen -= data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 		data += data[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) static void __exit ppp_async_cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	if (tty_unregister_ldisc(N_PPP) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 		printk(KERN_ERR "failed to unregister PPP line discipline\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) module_init(ppp_async_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) module_exit(ppp_async_cleanup);