linux/drivers/net/ppp/ppp_synctty.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * PPP synchronous tty channel driver for Linux.
 *
 * This is a ppp channel driver that can be used with tty device drivers
 * that are frame oriented, such as synchronous HDLC devices.
 *
 * Complete PPP frames without encoding/decoding are exchanged between
 * the channel driver and the device driver.
 *
 * The async map IOCTL codes are implemented to keep the user mode
 * applications happy if they call them. Synchronous PPP does not use
 * the async maps.
 *
 * Copyright 1999 Paul Mackerras.
 *
 * Also touched by the grubby hands of Paul Fulghum [email protected]
 *
 * This driver provides the encapsulation and framing for sending
 * and receiving PPP frames over sync serial lines.  It relies on
 * the generic PPP layer to give it frames to send and to process
 * received frames.  It implements the PPP line discipline.
 *
 * Part of the code in this driver was inspired by the old async-only
 * PPP driver, written by Michael Callahan and Al Longyear, and
 * subsequently hacked by Paul Mackerras.
 *
 * ==FILEVERSION 20040616==
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/tty.h>
#include <linux/netdevice.h>
#include <linux/poll.h>
#include <linux/ppp_defs.h>
#include <linux/ppp-ioctl.h>
#include <linux/ppp_channel.h>
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/refcount.h>
#include <linux/unaligned.h>
#include <linux/uaccess.h>

#define PPP_VERSION

/* Structure for storing local state. */
struct syncppp {};

/* Bit numbers in xmit_flags */
#define XMIT_WAKEUP
#define XMIT_FULL

/* Bits in rbits */
#define SC_RCV_BITS

#define PPPSYNC_MAX_RQLEN

/*
 * Prototypes.
 */
static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *);
static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd,
			  unsigned long arg);
static void ppp_sync_process(struct tasklet_struct *t);
static int ppp_sync_push(struct syncppp *ap);
static void ppp_sync_flush_output(struct syncppp *ap);
static void ppp_sync_input(struct syncppp *ap, const u8 *buf, const u8 *flags,
			   int count);

static const struct ppp_channel_ops sync_ops =;

/*
 * Utility procedure to print a buffer in hex/ascii
 */
static void
ppp_print_buffer (const char *name, const __u8 *buf, int count)
{}


/*
 * Routines implementing the synchronous PPP line discipline.
 */

/*
 * We have a potential race on dereferencing tty->disc_data,
 * because the tty layer provides no locking at all - thus one
 * cpu could be running ppp_synctty_receive while another
 * calls ppp_synctty_close, which zeroes tty->disc_data and
 * frees the memory that ppp_synctty_receive is using.  The best
 * way to fix this is to use a rwlock in the tty struct, but for now
 * we use a single global rwlock for all ttys in ppp line discipline.
 *
 * FIXME: Fixed in tty_io nowadays.
 */
static DEFINE_RWLOCK(disc_data_lock);

static struct syncppp *sp_get(struct tty_struct *tty)
{}

static void sp_put(struct syncppp *ap)
{}

/*
 * Called when a tty is put into sync-PPP line discipline.
 */
static int
ppp_sync_open(struct tty_struct *tty)
{}

/*
 * Called when the tty is put into another line discipline
 * or it hangs up.  We have to wait for any cpu currently
 * executing in any of the other ppp_synctty_* routines to
 * finish before we can call ppp_unregister_channel and free
 * the syncppp struct.  This routine must be called from
 * process context, not interrupt or softirq context.
 */
static void
ppp_sync_close(struct tty_struct *tty)
{}

/*
 * Called on tty hangup in process context.
 *
 * Wait for I/O to driver to complete and unregister PPP channel.
 * This is already done by the close routine, so just call that.
 */
static void ppp_sync_hangup(struct tty_struct *tty)
{}

/*
 * Read does nothing - no data is ever available this way.
 * Pppd reads and writes packets via /dev/ppp instead.
 */
static ssize_t
ppp_sync_read(struct tty_struct *tty, struct file *file, u8 *buf, size_t count,
	      void **cookie, unsigned long offset)
{}

/*
 * Write on the tty does nothing, the packets all come in
 * from the ppp generic stuff.
 */
static ssize_t
ppp_sync_write(struct tty_struct *tty, struct file *file, const u8 *buf,
	       size_t count)
{}

static int
ppp_synctty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
{}

/* May sleep, don't call from interrupt level or with interrupts disabled */
static void
ppp_sync_receive(struct tty_struct *tty, const u8 *buf, const u8 *cflags,
		 size_t count)
{}

static void
ppp_sync_wakeup(struct tty_struct *tty)
{}


static struct tty_ldisc_ops ppp_sync_ldisc =;

static int __init
ppp_sync_init(void)
{}

/*
 * The following routines provide the PPP channel interface.
 */
static int
ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
{}

/*
 * This is called at softirq level to deliver received packets
 * to the ppp_generic code, and to tell the ppp_generic code
 * if we can accept more output now.
 */
static void ppp_sync_process(struct tasklet_struct *t)
{}

/*
 * Procedures for encapsulation and framing.
 */

static struct sk_buff*
ppp_sync_txmunge(struct syncppp *ap, struct sk_buff *skb)
{}

/*
 * Transmit-side routines.
 */

/*
 * Send a packet to the peer over an sync tty line.
 * Returns 1 iff the packet was accepted.
 * If the packet was not accepted, we will call ppp_output_wakeup
 * at some later time.
 */
static int
ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb)
{}

/*
 * Push as much data as possible out to the tty.
 */
static int
ppp_sync_push(struct syncppp *ap)
{}

/*
 * Flush output from our internal buffers.
 * Called for the TCFLSH ioctl.
 */
static void
ppp_sync_flush_output(struct syncppp *ap)
{}

/*
 * Receive-side routines.
 */

/* called when the tty driver has data for us.
 *
 * Data is frame oriented: each call to ppp_sync_input is considered
 * a whole frame. If the 1st flag byte is non-zero then the whole
 * frame is considered to be in error and is tossed.
 */
static void
ppp_sync_input(struct syncppp *ap, const u8 *buf, const u8 *flags, int count)
{}

static void __exit
ppp_sync_cleanup(void)
{}

module_init();
module_exit(ppp_sync_cleanup);
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS_LDISC();