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

hdlc_x25.c (9060B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Generic HDLC support routines for Linux
      4 * X.25 support
      5 *
      6 * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
      7 */
      8
      9#include <linux/errno.h>
     10#include <linux/gfp.h>
     11#include <linux/hdlc.h>
     12#include <linux/if_arp.h>
     13#include <linux/inetdevice.h>
     14#include <linux/init.h>
     15#include <linux/kernel.h>
     16#include <linux/lapb.h>
     17#include <linux/module.h>
     18#include <linux/pkt_sched.h>
     19#include <linux/poll.h>
     20#include <linux/rtnetlink.h>
     21#include <linux/skbuff.h>
     22#include <net/x25device.h>
     23
     24struct x25_state {
     25	x25_hdlc_proto settings;
     26	bool up;
     27	spinlock_t up_lock; /* Protects "up" */
     28	struct sk_buff_head rx_queue;
     29	struct tasklet_struct rx_tasklet;
     30};
     31
     32static int x25_ioctl(struct net_device *dev, struct if_settings *ifs);
     33
     34static struct x25_state *state(hdlc_device *hdlc)
     35{
     36	return hdlc->state;
     37}
     38
     39static void x25_rx_queue_kick(struct tasklet_struct *t)
     40{
     41	struct x25_state *x25st = from_tasklet(x25st, t, rx_tasklet);
     42	struct sk_buff *skb = skb_dequeue(&x25st->rx_queue);
     43
     44	while (skb) {
     45		netif_receive_skb_core(skb);
     46		skb = skb_dequeue(&x25st->rx_queue);
     47	}
     48}
     49
     50/* These functions are callbacks called by LAPB layer */
     51
     52static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
     53{
     54	struct x25_state *x25st = state(dev_to_hdlc(dev));
     55	struct sk_buff *skb;
     56	unsigned char *ptr;
     57
     58	skb = __dev_alloc_skb(1, GFP_ATOMIC | __GFP_NOMEMALLOC);
     59	if (!skb)
     60		return;
     61
     62	ptr = skb_put(skb, 1);
     63	*ptr = code;
     64
     65	skb->protocol = x25_type_trans(skb, dev);
     66
     67	skb_queue_tail(&x25st->rx_queue, skb);
     68	tasklet_schedule(&x25st->rx_tasklet);
     69}
     70
     71static void x25_connected(struct net_device *dev, int reason)
     72{
     73	x25_connect_disconnect(dev, reason, X25_IFACE_CONNECT);
     74}
     75
     76static void x25_disconnected(struct net_device *dev, int reason)
     77{
     78	x25_connect_disconnect(dev, reason, X25_IFACE_DISCONNECT);
     79}
     80
     81static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
     82{
     83	struct x25_state *x25st = state(dev_to_hdlc(dev));
     84	unsigned char *ptr;
     85
     86	if (skb_cow(skb, 1)) {
     87		kfree_skb(skb);
     88		return NET_RX_DROP;
     89	}
     90
     91	skb_push(skb, 1);
     92
     93	ptr  = skb->data;
     94	*ptr = X25_IFACE_DATA;
     95
     96	skb->protocol = x25_type_trans(skb, dev);
     97
     98	skb_queue_tail(&x25st->rx_queue, skb);
     99	tasklet_schedule(&x25st->rx_tasklet);
    100	return NET_RX_SUCCESS;
    101}
    102
    103static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb)
    104{
    105	hdlc_device *hdlc = dev_to_hdlc(dev);
    106
    107	skb_reset_network_header(skb);
    108	skb->protocol = hdlc_type_trans(skb, dev);
    109
    110	if (dev_nit_active(dev))
    111		dev_queue_xmit_nit(skb, dev);
    112
    113	hdlc->xmit(skb, dev); /* Ignore return value :-( */
    114}
    115
    116static netdev_tx_t x25_xmit(struct sk_buff *skb, struct net_device *dev)
    117{
    118	hdlc_device *hdlc = dev_to_hdlc(dev);
    119	struct x25_state *x25st = state(hdlc);
    120	int result;
    121
    122	/* There should be a pseudo header of 1 byte added by upper layers.
    123	 * Check to make sure it is there before reading it.
    124	 */
    125	if (skb->len < 1) {
    126		kfree_skb(skb);
    127		return NETDEV_TX_OK;
    128	}
    129
    130	spin_lock_bh(&x25st->up_lock);
    131	if (!x25st->up) {
    132		spin_unlock_bh(&x25st->up_lock);
    133		kfree_skb(skb);
    134		return NETDEV_TX_OK;
    135	}
    136
    137	switch (skb->data[0]) {
    138	case X25_IFACE_DATA:	/* Data to be transmitted */
    139		skb_pull(skb, 1);
    140		result = lapb_data_request(dev, skb);
    141		if (result != LAPB_OK)
    142			dev_kfree_skb(skb);
    143		spin_unlock_bh(&x25st->up_lock);
    144		return NETDEV_TX_OK;
    145
    146	case X25_IFACE_CONNECT:
    147		result = lapb_connect_request(dev);
    148		if (result != LAPB_OK) {
    149			if (result == LAPB_CONNECTED)
    150				/* Send connect confirm. msg to level 3 */
    151				x25_connected(dev, 0);
    152			else
    153				netdev_err(dev, "LAPB connect request failed, error code = %i\n",
    154					   result);
    155		}
    156		break;
    157
    158	case X25_IFACE_DISCONNECT:
    159		result = lapb_disconnect_request(dev);
    160		if (result != LAPB_OK) {
    161			if (result == LAPB_NOTCONNECTED)
    162				/* Send disconnect confirm. msg to level 3 */
    163				x25_disconnected(dev, 0);
    164			else
    165				netdev_err(dev, "LAPB disconnect request failed, error code = %i\n",
    166					   result);
    167		}
    168		break;
    169
    170	default:		/* to be defined */
    171		break;
    172	}
    173
    174	spin_unlock_bh(&x25st->up_lock);
    175	dev_kfree_skb(skb);
    176	return NETDEV_TX_OK;
    177}
    178
    179static int x25_open(struct net_device *dev)
    180{
    181	static const struct lapb_register_struct cb = {
    182		.connect_confirmation = x25_connected,
    183		.connect_indication = x25_connected,
    184		.disconnect_confirmation = x25_disconnected,
    185		.disconnect_indication = x25_disconnected,
    186		.data_indication = x25_data_indication,
    187		.data_transmit = x25_data_transmit,
    188	};
    189	hdlc_device *hdlc = dev_to_hdlc(dev);
    190	struct x25_state *x25st = state(hdlc);
    191	struct lapb_parms_struct params;
    192	int result;
    193
    194	result = lapb_register(dev, &cb);
    195	if (result != LAPB_OK)
    196		return -ENOMEM;
    197
    198	result = lapb_getparms(dev, &params);
    199	if (result != LAPB_OK)
    200		return -EINVAL;
    201
    202	if (state(hdlc)->settings.dce)
    203		params.mode = params.mode | LAPB_DCE;
    204
    205	if (state(hdlc)->settings.modulo == 128)
    206		params.mode = params.mode | LAPB_EXTENDED;
    207
    208	params.window = state(hdlc)->settings.window;
    209	params.t1 = state(hdlc)->settings.t1;
    210	params.t2 = state(hdlc)->settings.t2;
    211	params.n2 = state(hdlc)->settings.n2;
    212
    213	result = lapb_setparms(dev, &params);
    214	if (result != LAPB_OK)
    215		return -EINVAL;
    216
    217	spin_lock_bh(&x25st->up_lock);
    218	x25st->up = true;
    219	spin_unlock_bh(&x25st->up_lock);
    220
    221	return 0;
    222}
    223
    224static void x25_close(struct net_device *dev)
    225{
    226	hdlc_device *hdlc = dev_to_hdlc(dev);
    227	struct x25_state *x25st = state(hdlc);
    228
    229	spin_lock_bh(&x25st->up_lock);
    230	x25st->up = false;
    231	spin_unlock_bh(&x25st->up_lock);
    232
    233	lapb_unregister(dev);
    234	tasklet_kill(&x25st->rx_tasklet);
    235}
    236
    237static int x25_rx(struct sk_buff *skb)
    238{
    239	struct net_device *dev = skb->dev;
    240	hdlc_device *hdlc = dev_to_hdlc(dev);
    241	struct x25_state *x25st = state(hdlc);
    242
    243	skb = skb_share_check(skb, GFP_ATOMIC);
    244	if (!skb) {
    245		dev->stats.rx_dropped++;
    246		return NET_RX_DROP;
    247	}
    248
    249	spin_lock_bh(&x25st->up_lock);
    250	if (!x25st->up) {
    251		spin_unlock_bh(&x25st->up_lock);
    252		kfree_skb(skb);
    253		dev->stats.rx_dropped++;
    254		return NET_RX_DROP;
    255	}
    256
    257	if (lapb_data_received(dev, skb) == LAPB_OK) {
    258		spin_unlock_bh(&x25st->up_lock);
    259		return NET_RX_SUCCESS;
    260	}
    261
    262	spin_unlock_bh(&x25st->up_lock);
    263	dev->stats.rx_errors++;
    264	dev_kfree_skb_any(skb);
    265	return NET_RX_DROP;
    266}
    267
    268static struct hdlc_proto proto = {
    269	.open		= x25_open,
    270	.close		= x25_close,
    271	.ioctl		= x25_ioctl,
    272	.netif_rx	= x25_rx,
    273	.xmit		= x25_xmit,
    274	.module		= THIS_MODULE,
    275};
    276
    277static int x25_ioctl(struct net_device *dev, struct if_settings *ifs)
    278{
    279	x25_hdlc_proto __user *x25_s = ifs->ifs_ifsu.x25;
    280	const size_t size = sizeof(x25_hdlc_proto);
    281	hdlc_device *hdlc = dev_to_hdlc(dev);
    282	x25_hdlc_proto new_settings;
    283	int result;
    284
    285	switch (ifs->type) {
    286	case IF_GET_PROTO:
    287		if (dev_to_hdlc(dev)->proto != &proto)
    288			return -EINVAL;
    289		ifs->type = IF_PROTO_X25;
    290		if (ifs->size < size) {
    291			ifs->size = size; /* data size wanted */
    292			return -ENOBUFS;
    293		}
    294		if (copy_to_user(x25_s, &state(hdlc)->settings, size))
    295			return -EFAULT;
    296		return 0;
    297
    298	case IF_PROTO_X25:
    299		if (!capable(CAP_NET_ADMIN))
    300			return -EPERM;
    301
    302		if (dev->flags & IFF_UP)
    303			return -EBUSY;
    304
    305		/* backward compatibility */
    306		if (ifs->size == 0) {
    307			new_settings.dce = 0;
    308			new_settings.modulo = 8;
    309			new_settings.window = 7;
    310			new_settings.t1 = 3;
    311			new_settings.t2 = 1;
    312			new_settings.n2 = 10;
    313		} else {
    314			if (copy_from_user(&new_settings, x25_s, size))
    315				return -EFAULT;
    316
    317			if ((new_settings.dce != 0 &&
    318			     new_settings.dce != 1) ||
    319			    (new_settings.modulo != 8 &&
    320			     new_settings.modulo != 128) ||
    321			    new_settings.window < 1 ||
    322			    (new_settings.modulo == 8 &&
    323			     new_settings.window > 7) ||
    324			    (new_settings.modulo == 128 &&
    325			     new_settings.window > 127) ||
    326			    new_settings.t1 < 1 ||
    327			    new_settings.t1 > 255 ||
    328			    new_settings.t2 < 1 ||
    329			    new_settings.t2 > 255 ||
    330			    new_settings.n2 < 1 ||
    331			    new_settings.n2 > 255)
    332				return -EINVAL;
    333		}
    334
    335		result = hdlc->attach(dev, ENCODING_NRZ,
    336				      PARITY_CRC16_PR1_CCITT);
    337		if (result)
    338			return result;
    339
    340		result = attach_hdlc_protocol(dev, &proto,
    341					      sizeof(struct x25_state));
    342		if (result)
    343			return result;
    344
    345		memcpy(&state(hdlc)->settings, &new_settings, size);
    346		state(hdlc)->up = false;
    347		spin_lock_init(&state(hdlc)->up_lock);
    348		skb_queue_head_init(&state(hdlc)->rx_queue);
    349		tasklet_setup(&state(hdlc)->rx_tasklet, x25_rx_queue_kick);
    350
    351		/* There's no header_ops so hard_header_len should be 0. */
    352		dev->hard_header_len = 0;
    353		/* When transmitting data:
    354		 * first we'll remove a pseudo header of 1 byte,
    355		 * then we'll prepend an LAPB header of at most 3 bytes.
    356		 */
    357		dev->needed_headroom = 3 - 1;
    358
    359		dev->type = ARPHRD_X25;
    360		call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
    361		netif_dormant_off(dev);
    362		return 0;
    363	}
    364
    365	return -EINVAL;
    366}
    367
    368static int __init hdlc_x25_init(void)
    369{
    370	register_hdlc_protocol(&proto);
    371	return 0;
    372}
    373
    374static void __exit hdlc_x25_exit(void)
    375{
    376	unregister_hdlc_protocol(&proto);
    377}
    378
    379module_init(hdlc_x25_init);
    380module_exit(hdlc_x25_exit);
    381
    382MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
    383MODULE_DESCRIPTION("X.25 protocol support for generic HDLC");
    384MODULE_LICENSE("GPL v2");