cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

network.c (12919B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * IPWireless 3G PCMCIA Network Driver
      4 *
      5 * Original code
      6 *   by Stephen Blackheath <stephen@blacksapphire.com>,
      7 *      Ben Martel <benm@symmetric.co.nz>
      8 *
      9 * Copyrighted as follows:
     10 *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
     11 *
     12 * Various driver changes and rewrites, port to new kernels
     13 *   Copyright (C) 2006-2007 Jiri Kosina
     14 *
     15 * Misc code cleanups and updates
     16 *   Copyright (C) 2007 David Sterba
     17 */
     18
     19#include <linux/interrupt.h>
     20#include <linux/kernel.h>
     21#include <linux/mutex.h>
     22#include <linux/netdevice.h>
     23#include <linux/ppp_channel.h>
     24#include <linux/ppp_defs.h>
     25#include <linux/slab.h>
     26#include <linux/ppp-ioctl.h>
     27#include <linux/skbuff.h>
     28
     29#include "network.h"
     30#include "hardware.h"
     31#include "main.h"
     32#include "tty.h"
     33
     34#define MAX_ASSOCIATED_TTYS 2
     35
     36#define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
     37
     38struct ipw_network {
     39	/* Hardware context, used for calls to hardware layer. */
     40	struct ipw_hardware *hardware;
     41	/* Context for kernel 'generic_ppp' functionality */
     42	struct ppp_channel *ppp_channel;
     43	/* tty context connected with IPW console */
     44	struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
     45	/* True if ppp needs waking up once we're ready to xmit */
     46	int ppp_blocked;
     47	/* Number of packets queued up in hardware module. */
     48	int outgoing_packets_queued;
     49	/* Spinlock to avoid interrupts during shutdown */
     50	spinlock_t lock;
     51	struct mutex close_lock;
     52
     53	/* PPP ioctl data, not actually used anywere */
     54	unsigned int flags;
     55	unsigned int rbits;
     56	u32 xaccm[8];
     57	u32 raccm;
     58	int mru;
     59
     60	int shutting_down;
     61	unsigned int ras_control_lines;
     62
     63	struct work_struct work_go_online;
     64	struct work_struct work_go_offline;
     65};
     66
     67static void notify_packet_sent(void *callback_data, unsigned int packet_length)
     68{
     69	struct ipw_network *network = callback_data;
     70	unsigned long flags;
     71
     72	spin_lock_irqsave(&network->lock, flags);
     73	network->outgoing_packets_queued--;
     74	if (network->ppp_channel != NULL) {
     75		if (network->ppp_blocked) {
     76			network->ppp_blocked = 0;
     77			spin_unlock_irqrestore(&network->lock, flags);
     78			ppp_output_wakeup(network->ppp_channel);
     79			if (ipwireless_debug)
     80				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
     81				       ": ppp unblocked\n");
     82		} else
     83			spin_unlock_irqrestore(&network->lock, flags);
     84	} else
     85		spin_unlock_irqrestore(&network->lock, flags);
     86}
     87
     88/*
     89 * Called by the ppp system when it has a packet to send to the hardware.
     90 */
     91static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
     92				     struct sk_buff *skb)
     93{
     94	struct ipw_network *network = ppp_channel->private;
     95	unsigned long flags;
     96
     97	spin_lock_irqsave(&network->lock, flags);
     98	if (network->outgoing_packets_queued < ipwireless_out_queue) {
     99		unsigned char *buf;
    100		static unsigned char header[] = {
    101			PPP_ALLSTATIONS, /* 0xff */
    102			PPP_UI,		 /* 0x03 */
    103		};
    104		int ret;
    105
    106		network->outgoing_packets_queued++;
    107		spin_unlock_irqrestore(&network->lock, flags);
    108
    109		/*
    110		 * If we have the requested amount of headroom in the skb we
    111		 * were handed, then we can add the header efficiently.
    112		 */
    113		if (skb_headroom(skb) >= 2) {
    114			memcpy(skb_push(skb, 2), header, 2);
    115			ret = ipwireless_send_packet(network->hardware,
    116					       IPW_CHANNEL_RAS, skb->data,
    117					       skb->len,
    118					       notify_packet_sent,
    119					       network);
    120			if (ret < 0) {
    121				skb_pull(skb, 2);
    122				return 0;
    123			}
    124		} else {
    125			/* Otherwise (rarely) we do it inefficiently. */
    126			buf = kmalloc(skb->len + 2, GFP_ATOMIC);
    127			if (!buf)
    128				return 0;
    129			memcpy(buf + 2, skb->data, skb->len);
    130			memcpy(buf, header, 2);
    131			ret = ipwireless_send_packet(network->hardware,
    132					       IPW_CHANNEL_RAS, buf,
    133					       skb->len + 2,
    134					       notify_packet_sent,
    135					       network);
    136			kfree(buf);
    137			if (ret < 0)
    138				return 0;
    139		}
    140		kfree_skb(skb);
    141		return 1;
    142	} else {
    143		/*
    144		 * Otherwise reject the packet, and flag that the ppp system
    145		 * needs to be unblocked once we are ready to send.
    146		 */
    147		network->ppp_blocked = 1;
    148		spin_unlock_irqrestore(&network->lock, flags);
    149		if (ipwireless_debug)
    150			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
    151		return 0;
    152	}
    153}
    154
    155/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */
    156static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
    157				unsigned int cmd, unsigned long arg)
    158{
    159	struct ipw_network *network = ppp_channel->private;
    160	int err, val;
    161	u32 accm[8];
    162	int __user *user_arg = (int __user *) arg;
    163
    164	err = -EFAULT;
    165	switch (cmd) {
    166	case PPPIOCGFLAGS:
    167		val = network->flags | network->rbits;
    168		if (put_user(val, user_arg))
    169			break;
    170		err = 0;
    171		break;
    172
    173	case PPPIOCSFLAGS:
    174		if (get_user(val, user_arg))
    175			break;
    176		network->flags = val & ~SC_RCV_BITS;
    177		network->rbits = val & SC_RCV_BITS;
    178		err = 0;
    179		break;
    180
    181	case PPPIOCGASYNCMAP:
    182		if (put_user(network->xaccm[0], user_arg))
    183			break;
    184		err = 0;
    185		break;
    186
    187	case PPPIOCSASYNCMAP:
    188		if (get_user(network->xaccm[0], user_arg))
    189			break;
    190		err = 0;
    191		break;
    192
    193	case PPPIOCGRASYNCMAP:
    194		if (put_user(network->raccm, user_arg))
    195			break;
    196		err = 0;
    197		break;
    198
    199	case PPPIOCSRASYNCMAP:
    200		if (get_user(network->raccm, user_arg))
    201			break;
    202		err = 0;
    203		break;
    204
    205	case PPPIOCGXASYNCMAP:
    206		if (copy_to_user((void __user *) arg, network->xaccm,
    207					sizeof(network->xaccm)))
    208			break;
    209		err = 0;
    210		break;
    211
    212	case PPPIOCSXASYNCMAP:
    213		if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
    214			break;
    215		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
    216		accm[3] |= 0x60000000U;	/* must escape 0x7d, 0x7e */
    217		memcpy(network->xaccm, accm, sizeof(network->xaccm));
    218		err = 0;
    219		break;
    220
    221	case PPPIOCGMRU:
    222		if (put_user(network->mru, user_arg))
    223			break;
    224		err = 0;
    225		break;
    226
    227	case PPPIOCSMRU:
    228		if (get_user(val, user_arg))
    229			break;
    230		if (val < PPP_MRU)
    231			val = PPP_MRU;
    232		network->mru = val;
    233		err = 0;
    234		break;
    235
    236	default:
    237		err = -ENOTTY;
    238	}
    239
    240	return err;
    241}
    242
    243static const struct ppp_channel_ops ipwireless_ppp_channel_ops = {
    244	.start_xmit = ipwireless_ppp_start_xmit,
    245	.ioctl      = ipwireless_ppp_ioctl
    246};
    247
    248static void do_go_online(struct work_struct *work_go_online)
    249{
    250	struct ipw_network *network =
    251		container_of(work_go_online, struct ipw_network,
    252				work_go_online);
    253	unsigned long flags;
    254
    255	spin_lock_irqsave(&network->lock, flags);
    256	if (!network->ppp_channel) {
    257		struct ppp_channel *channel;
    258
    259		spin_unlock_irqrestore(&network->lock, flags);
    260		channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
    261		if (!channel) {
    262			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
    263					": unable to allocate PPP channel\n");
    264			return;
    265		}
    266		channel->private = network;
    267		channel->mtu = 16384;	/* Wild guess */
    268		channel->hdrlen = 2;
    269		channel->ops = &ipwireless_ppp_channel_ops;
    270
    271		network->flags = 0;
    272		network->rbits = 0;
    273		network->mru = PPP_MRU;
    274		memset(network->xaccm, 0, sizeof(network->xaccm));
    275		network->xaccm[0] = ~0U;
    276		network->xaccm[3] = 0x60000000U;
    277		network->raccm = ~0U;
    278		if (ppp_register_channel(channel) < 0) {
    279			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
    280					": unable to register PPP channel\n");
    281			kfree(channel);
    282			return;
    283		}
    284		spin_lock_irqsave(&network->lock, flags);
    285		network->ppp_channel = channel;
    286	}
    287	spin_unlock_irqrestore(&network->lock, flags);
    288}
    289
    290static void do_go_offline(struct work_struct *work_go_offline)
    291{
    292	struct ipw_network *network =
    293		container_of(work_go_offline, struct ipw_network,
    294				work_go_offline);
    295	unsigned long flags;
    296
    297	mutex_lock(&network->close_lock);
    298	spin_lock_irqsave(&network->lock, flags);
    299	if (network->ppp_channel != NULL) {
    300		struct ppp_channel *channel = network->ppp_channel;
    301
    302		network->ppp_channel = NULL;
    303		spin_unlock_irqrestore(&network->lock, flags);
    304		mutex_unlock(&network->close_lock);
    305		ppp_unregister_channel(channel);
    306	} else {
    307		spin_unlock_irqrestore(&network->lock, flags);
    308		mutex_unlock(&network->close_lock);
    309	}
    310}
    311
    312void ipwireless_network_notify_control_line_change(struct ipw_network *network,
    313						   unsigned int channel_idx,
    314						   unsigned int control_lines,
    315						   unsigned int changed_mask)
    316{
    317	int i;
    318
    319	if (channel_idx == IPW_CHANNEL_RAS)
    320		network->ras_control_lines = control_lines;
    321
    322	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
    323		struct ipw_tty *tty =
    324			network->associated_ttys[channel_idx][i];
    325
    326		/*
    327		 * If it's associated with a tty (other than the RAS channel
    328		 * when we're online), then send the data to that tty.  The RAS
    329		 * channel's data is handled above - it always goes through
    330		 * ppp_generic.
    331		 */
    332		if (tty)
    333			ipwireless_tty_notify_control_line_change(tty,
    334								  channel_idx,
    335								  control_lines,
    336								  changed_mask);
    337	}
    338}
    339
    340/*
    341 * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI)
    342 * bytes, which are required on sent packet, but not always present on received
    343 * packets
    344 */
    345static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
    346					       unsigned int length)
    347{
    348	struct sk_buff *skb;
    349
    350	if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
    351		length -= 2;
    352		data += 2;
    353	}
    354
    355	skb = dev_alloc_skb(length + 4);
    356	if (skb == NULL)
    357		return NULL;
    358	skb_reserve(skb, 2);
    359	skb_put_data(skb, data, length);
    360
    361	return skb;
    362}
    363
    364void ipwireless_network_packet_received(struct ipw_network *network,
    365					unsigned int channel_idx,
    366					unsigned char *data,
    367					unsigned int length)
    368{
    369	int i;
    370	unsigned long flags;
    371
    372	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
    373		struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
    374
    375		if (!tty)
    376			continue;
    377
    378		/*
    379		 * If it's associated with a tty (other than the RAS channel
    380		 * when we're online), then send the data to that tty.  The RAS
    381		 * channel's data is handled above - it always goes through
    382		 * ppp_generic.
    383		 */
    384		if (channel_idx == IPW_CHANNEL_RAS
    385				&& (network->ras_control_lines &
    386					IPW_CONTROL_LINE_DCD) != 0
    387				&& ipwireless_tty_is_modem(tty)) {
    388			/*
    389			 * If data came in on the RAS channel and this tty is
    390			 * the modem tty, and we are online, then we send it to
    391			 * the PPP layer.
    392			 */
    393			mutex_lock(&network->close_lock);
    394			spin_lock_irqsave(&network->lock, flags);
    395			if (network->ppp_channel != NULL) {
    396				struct sk_buff *skb;
    397
    398				spin_unlock_irqrestore(&network->lock,
    399						flags);
    400
    401				/* Send the data to the ppp_generic module. */
    402				skb = ipw_packet_received_skb(data, length);
    403				if (skb)
    404					ppp_input(network->ppp_channel, skb);
    405			} else
    406				spin_unlock_irqrestore(&network->lock,
    407						flags);
    408			mutex_unlock(&network->close_lock);
    409		}
    410		/* Otherwise we send it out the tty. */
    411		else
    412			ipwireless_tty_received(tty, data, length);
    413	}
    414}
    415
    416struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
    417{
    418	struct ipw_network *network =
    419		kzalloc(sizeof(struct ipw_network), GFP_KERNEL);
    420
    421	if (!network)
    422		return NULL;
    423
    424	spin_lock_init(&network->lock);
    425	mutex_init(&network->close_lock);
    426
    427	network->hardware = hw;
    428
    429	INIT_WORK(&network->work_go_online, do_go_online);
    430	INIT_WORK(&network->work_go_offline, do_go_offline);
    431
    432	ipwireless_associate_network(hw, network);
    433
    434	return network;
    435}
    436
    437void ipwireless_network_free(struct ipw_network *network)
    438{
    439	network->shutting_down = 1;
    440
    441	ipwireless_ppp_close(network);
    442	flush_work(&network->work_go_online);
    443	flush_work(&network->work_go_offline);
    444
    445	ipwireless_stop_interrupts(network->hardware);
    446	ipwireless_associate_network(network->hardware, NULL);
    447
    448	kfree(network);
    449}
    450
    451void ipwireless_associate_network_tty(struct ipw_network *network,
    452				      unsigned int channel_idx,
    453				      struct ipw_tty *tty)
    454{
    455	int i;
    456
    457	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
    458		if (network->associated_ttys[channel_idx][i] == NULL) {
    459			network->associated_ttys[channel_idx][i] = tty;
    460			break;
    461		}
    462}
    463
    464void ipwireless_disassociate_network_ttys(struct ipw_network *network,
    465					  unsigned int channel_idx)
    466{
    467	int i;
    468
    469	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
    470		network->associated_ttys[channel_idx][i] = NULL;
    471}
    472
    473void ipwireless_ppp_open(struct ipw_network *network)
    474{
    475	if (ipwireless_debug)
    476		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
    477	schedule_work(&network->work_go_online);
    478}
    479
    480void ipwireless_ppp_close(struct ipw_network *network)
    481{
    482	/* Disconnect from the wireless network. */
    483	if (ipwireless_debug)
    484		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
    485	schedule_work(&network->work_go_offline);
    486}
    487
    488int ipwireless_ppp_channel_index(struct ipw_network *network)
    489{
    490	int ret = -1;
    491	unsigned long flags;
    492
    493	spin_lock_irqsave(&network->lock, flags);
    494	if (network->ppp_channel != NULL)
    495		ret = ppp_channel_index(network->ppp_channel);
    496	spin_unlock_irqrestore(&network->lock, flags);
    497
    498	return ret;
    499}
    500
    501int ipwireless_ppp_unit_number(struct ipw_network *network)
    502{
    503	int ret = -1;
    504	unsigned long flags;
    505
    506	spin_lock_irqsave(&network->lock, flags);
    507	if (network->ppp_channel != NULL)
    508		ret = ppp_unit_number(network->ppp_channel);
    509	spin_unlock_irqrestore(&network->lock, flags);
    510
    511	return ret;
    512}
    513
    514int ipwireless_ppp_mru(const struct ipw_network *network)
    515{
    516	return network->mru;
    517}