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

x25_route.c (4285B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *	X.25 Packet Layer release 002
      4 *
      5 *	This is ALPHA test software. This code may break your machine,
      6 *	randomly fail to work with new releases, misbehave and/or generally
      7 *	screw up. It might even work.
      8 *
      9 *	This code REQUIRES 2.1.15 or higher
     10 *
     11 *	History
     12 *	X.25 001	Jonathan Naylor	Started coding.
     13 */
     14
     15#include <linux/if_arp.h>
     16#include <linux/init.h>
     17#include <linux/slab.h>
     18#include <net/x25.h>
     19
     20LIST_HEAD(x25_route_list);
     21DEFINE_RWLOCK(x25_route_list_lock);
     22
     23/*
     24 *	Add a new route.
     25 */
     26static int x25_add_route(struct x25_address *address, unsigned int sigdigits,
     27			 struct net_device *dev)
     28{
     29	struct x25_route *rt;
     30	int rc = -EINVAL;
     31
     32	write_lock_bh(&x25_route_list_lock);
     33
     34	list_for_each_entry(rt, &x25_route_list, node) {
     35		if (!memcmp(&rt->address, address, sigdigits) &&
     36		    rt->sigdigits == sigdigits)
     37			goto out;
     38	}
     39
     40	rt = kmalloc(sizeof(*rt), GFP_ATOMIC);
     41	rc = -ENOMEM;
     42	if (!rt)
     43		goto out;
     44
     45	strcpy(rt->address.x25_addr, "000000000000000");
     46	memcpy(rt->address.x25_addr, address->x25_addr, sigdigits);
     47
     48	rt->sigdigits = sigdigits;
     49	rt->dev       = dev;
     50	refcount_set(&rt->refcnt, 1);
     51
     52	list_add(&rt->node, &x25_route_list);
     53	rc = 0;
     54out:
     55	write_unlock_bh(&x25_route_list_lock);
     56	return rc;
     57}
     58
     59/**
     60 * __x25_remove_route - remove route from x25_route_list
     61 * @rt: route to remove
     62 *
     63 * Remove route from x25_route_list. If it was there.
     64 * Caller must hold x25_route_list_lock.
     65 */
     66static void __x25_remove_route(struct x25_route *rt)
     67{
     68	if (rt->node.next) {
     69		list_del(&rt->node);
     70		x25_route_put(rt);
     71	}
     72}
     73
     74static int x25_del_route(struct x25_address *address, unsigned int sigdigits,
     75			 struct net_device *dev)
     76{
     77	struct x25_route *rt;
     78	int rc = -EINVAL;
     79
     80	write_lock_bh(&x25_route_list_lock);
     81
     82	list_for_each_entry(rt, &x25_route_list, node) {
     83		if (!memcmp(&rt->address, address, sigdigits) &&
     84		    rt->sigdigits == sigdigits && rt->dev == dev) {
     85			__x25_remove_route(rt);
     86			rc = 0;
     87			break;
     88		}
     89	}
     90
     91	write_unlock_bh(&x25_route_list_lock);
     92	return rc;
     93}
     94
     95/*
     96 *	A device has been removed, remove its routes.
     97 */
     98void x25_route_device_down(struct net_device *dev)
     99{
    100	struct x25_route *rt;
    101	struct list_head *entry, *tmp;
    102
    103	write_lock_bh(&x25_route_list_lock);
    104
    105	list_for_each_safe(entry, tmp, &x25_route_list) {
    106		rt = list_entry(entry, struct x25_route, node);
    107
    108		if (rt->dev == dev)
    109			__x25_remove_route(rt);
    110	}
    111	write_unlock_bh(&x25_route_list_lock);
    112}
    113
    114/*
    115 *	Check that the device given is a valid X.25 interface that is "up".
    116 */
    117struct net_device *x25_dev_get(char *devname)
    118{
    119	struct net_device *dev = dev_get_by_name(&init_net, devname);
    120
    121	if (dev && (!(dev->flags & IFF_UP) || dev->type != ARPHRD_X25)) {
    122		dev_put(dev);
    123		dev = NULL;
    124	}
    125
    126	return dev;
    127}
    128
    129/**
    130 * 	x25_get_route -	Find a route given an X.25 address.
    131 *	@addr: - address to find a route for
    132 *
    133 * 	Find a route given an X.25 address.
    134 */
    135struct x25_route *x25_get_route(struct x25_address *addr)
    136{
    137	struct x25_route *rt, *use = NULL;
    138
    139	read_lock_bh(&x25_route_list_lock);
    140
    141	list_for_each_entry(rt, &x25_route_list, node) {
    142		if (!memcmp(&rt->address, addr, rt->sigdigits)) {
    143			if (!use)
    144				use = rt;
    145			else if (rt->sigdigits > use->sigdigits)
    146				use = rt;
    147		}
    148	}
    149
    150	if (use)
    151		x25_route_hold(use);
    152
    153	read_unlock_bh(&x25_route_list_lock);
    154	return use;
    155}
    156
    157/*
    158 *	Handle the ioctls that control the routing functions.
    159 */
    160int x25_route_ioctl(unsigned int cmd, void __user *arg)
    161{
    162	struct x25_route_struct rt;
    163	struct net_device *dev;
    164	int rc = -EINVAL;
    165
    166	if (cmd != SIOCADDRT && cmd != SIOCDELRT)
    167		goto out;
    168
    169	rc = -EFAULT;
    170	if (copy_from_user(&rt, arg, sizeof(rt)))
    171		goto out;
    172
    173	rc = -EINVAL;
    174	if (rt.sigdigits > 15)
    175		goto out;
    176
    177	dev = x25_dev_get(rt.device);
    178	if (!dev)
    179		goto out;
    180
    181	if (cmd == SIOCADDRT)
    182		rc = x25_add_route(&rt.address, rt.sigdigits, dev);
    183	else
    184		rc = x25_del_route(&rt.address, rt.sigdigits, dev);
    185	dev_put(dev);
    186out:
    187	return rc;
    188}
    189
    190/*
    191 *	Release all memory associated with X.25 routing structures.
    192 */
    193void __exit x25_route_free(void)
    194{
    195	struct x25_route *rt;
    196	struct list_head *entry, *tmp;
    197
    198	write_lock_bh(&x25_route_list_lock);
    199	list_for_each_safe(entry, tmp, &x25_route_list) {
    200		rt = list_entry(entry, struct x25_route, node);
    201		__x25_remove_route(rt);
    202	}
    203	write_unlock_bh(&x25_route_list_lock);
    204}