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

ax25_ip.c (5400B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *
      4 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
      5 */
      6#include <linux/errno.h>
      7#include <linux/types.h>
      8#include <linux/socket.h>
      9#include <linux/in.h>
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/timer.h>
     13#include <linux/string.h>
     14#include <linux/sockios.h>
     15#include <linux/net.h>
     16#include <linux/slab.h>
     17#include <net/ax25.h>
     18#include <linux/inet.h>
     19#include <linux/netdevice.h>
     20#include <linux/if_arp.h>
     21#include <linux/skbuff.h>
     22#include <net/sock.h>
     23#include <linux/uaccess.h>
     24#include <linux/fcntl.h>
     25#include <linux/termios.h>	/* For TIOCINQ/OUTQ */
     26#include <linux/mm.h>
     27#include <linux/interrupt.h>
     28#include <linux/notifier.h>
     29#include <linux/proc_fs.h>
     30#include <linux/stat.h>
     31#include <linux/sysctl.h>
     32#include <net/ip.h>
     33#include <net/arp.h>
     34
     35/*
     36 *	IP over AX.25 encapsulation.
     37 */
     38
     39/*
     40 *	Shove an AX.25 UI header on an IP packet and handle ARP
     41 */
     42
     43#ifdef CONFIG_INET
     44
     45static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
     46			    unsigned short type, const void *daddr,
     47			    const void *saddr, unsigned int len)
     48{
     49	unsigned char *buff;
     50
     51	/* they sometimes come back to us... */
     52	if (type == ETH_P_AX25)
     53		return 0;
     54
     55	/* header is an AX.25 UI frame from us to them */
     56	buff = skb_push(skb, AX25_HEADER_LEN);
     57	*buff++ = 0x00;	/* KISS DATA */
     58
     59	if (daddr != NULL)
     60		memcpy(buff, daddr, dev->addr_len);	/* Address specified */
     61
     62	buff[6] &= ~AX25_CBIT;
     63	buff[6] &= ~AX25_EBIT;
     64	buff[6] |= AX25_SSSID_SPARE;
     65	buff    += AX25_ADDR_LEN;
     66
     67	if (saddr != NULL)
     68		memcpy(buff, saddr, dev->addr_len);
     69	else
     70		memcpy(buff, dev->dev_addr, dev->addr_len);
     71
     72	buff[6] &= ~AX25_CBIT;
     73	buff[6] |= AX25_EBIT;
     74	buff[6] |= AX25_SSSID_SPARE;
     75	buff    += AX25_ADDR_LEN;
     76
     77	*buff++  = AX25_UI;	/* UI */
     78
     79	/* Append a suitable AX.25 PID */
     80	switch (type) {
     81	case ETH_P_IP:
     82		*buff++ = AX25_P_IP;
     83		break;
     84	case ETH_P_ARP:
     85		*buff++ = AX25_P_ARP;
     86		break;
     87	default:
     88		printk(KERN_ERR "AX.25: ax25_hard_header - wrong protocol type 0x%2.2x\n", type);
     89		*buff++ = 0;
     90		break;
     91	}
     92
     93	if (daddr != NULL)
     94		return AX25_HEADER_LEN;
     95
     96	return -AX25_HEADER_LEN;	/* Unfinished header */
     97}
     98
     99netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
    100{
    101	struct sk_buff *ourskb;
    102	unsigned char *bp  = skb->data;
    103	ax25_route *route;
    104	struct net_device *dev = NULL;
    105	ax25_address *src, *dst;
    106	ax25_digi *digipeat = NULL;
    107	ax25_dev *ax25_dev;
    108	ax25_cb *ax25;
    109	char ip_mode = ' ';
    110
    111	dst = (ax25_address *)(bp + 1);
    112	src = (ax25_address *)(bp + 8);
    113
    114	ax25_route_lock_use();
    115	route = ax25_get_route(dst, NULL);
    116	if (route) {
    117		digipeat = route->digipeat;
    118		dev = route->dev;
    119		ip_mode = route->ip_mode;
    120	}
    121
    122	if (dev == NULL)
    123		dev = skb->dev;
    124
    125	if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
    126		kfree_skb(skb);
    127		goto put;
    128	}
    129
    130	if (bp[16] == AX25_P_IP) {
    131		if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) {
    132			/*
    133			 *	We copy the buffer and release the original thereby
    134			 *	keeping it straight
    135			 *
    136			 *	Note: we report 1 back so the caller will
    137			 *	not feed the frame direct to the physical device
    138			 *	We don't want that to happen. (It won't be upset
    139			 *	as we have pulled the frame from the queue by
    140			 *	freeing it).
    141			 *
    142			 *	NB: TCP modifies buffers that are still
    143			 *	on a device queue, thus we use skb_copy()
    144			 *      instead of using skb_clone() unless this
    145			 *	gets fixed.
    146			 */
    147
    148			ax25_address src_c;
    149			ax25_address dst_c;
    150
    151			if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) {
    152				kfree_skb(skb);
    153				goto put;
    154			}
    155
    156			if (skb->sk != NULL)
    157				skb_set_owner_w(ourskb, skb->sk);
    158
    159			kfree_skb(skb);
    160			/* dl9sau: bugfix
    161			 * after kfree_skb(), dst and src which were pointer
    162			 * to bp which is part of skb->data would not be valid
    163			 * anymore hope that after skb_pull(ourskb, ..) our
    164			 * dsc_c and src_c will not become invalid
    165			 */
    166			bp  = ourskb->data;
    167			dst_c = *(ax25_address *)(bp + 1);
    168			src_c = *(ax25_address *)(bp + 8);
    169
    170			skb_pull(ourskb, AX25_HEADER_LEN - 1);	/* Keep PID */
    171			skb_reset_network_header(ourskb);
    172
    173			ax25=ax25_send_frame(
    174			    ourskb,
    175			    ax25_dev->values[AX25_VALUES_PACLEN],
    176			    &src_c,
    177			    &dst_c, digipeat, dev);
    178			if (ax25) {
    179				ax25_cb_put(ax25);
    180			}
    181			goto put;
    182		}
    183	}
    184
    185	bp[7]  &= ~AX25_CBIT;
    186	bp[7]  &= ~AX25_EBIT;
    187	bp[7]  |= AX25_SSSID_SPARE;
    188
    189	bp[14] &= ~AX25_CBIT;
    190	bp[14] |= AX25_EBIT;
    191	bp[14] |= AX25_SSSID_SPARE;
    192
    193	skb_pull(skb, AX25_KISS_HEADER_LEN);
    194
    195	if (digipeat != NULL) {
    196		if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL)
    197			goto put;
    198
    199		skb = ourskb;
    200	}
    201
    202	ax25_queue_xmit(skb, dev);
    203
    204put:
    205
    206	ax25_route_lock_unuse();
    207	return NETDEV_TX_OK;
    208}
    209
    210#else	/* INET */
    211
    212static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
    213			    unsigned short type, const void *daddr,
    214			    const void *saddr, unsigned int len)
    215{
    216	return -AX25_HEADER_LEN;
    217}
    218
    219netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
    220{
    221	kfree_skb(skb);
    222	return NETDEV_TX_OK;
    223}
    224#endif
    225
    226static bool ax25_validate_header(const char *header, unsigned int len)
    227{
    228	ax25_digi digi;
    229
    230	if (!len)
    231		return false;
    232
    233	if (header[0])
    234		return true;
    235
    236	return ax25_addr_parse(header + 1, len - 1, NULL, NULL, &digi, NULL,
    237			       NULL);
    238}
    239
    240const struct header_ops ax25_header_ops = {
    241	.create = ax25_hard_header,
    242	.validate = ax25_validate_header,
    243};
    244
    245EXPORT_SYMBOL(ax25_header_ops);
    246EXPORT_SYMBOL(ax25_ip_xmit);