linux/net/ax25/ax25_ip.c
<<
>>
Prefs
   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                        kfree_skb(skb);
 198                        goto put;
 199                }
 200
 201                skb = ourskb;
 202        }
 203
 204        ax25_queue_xmit(skb, dev);
 205
 206put:
 207
 208        ax25_route_lock_unuse();
 209        return NETDEV_TX_OK;
 210}
 211
 212#else   /* INET */
 213
 214static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
 215                            unsigned short type, const void *daddr,
 216                            const void *saddr, unsigned int len)
 217{
 218        return -AX25_HEADER_LEN;
 219}
 220
 221netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
 222{
 223        kfree_skb(skb);
 224        return NETDEV_TX_OK;
 225}
 226#endif
 227
 228static bool ax25_validate_header(const char *header, unsigned int len)
 229{
 230        ax25_digi digi;
 231
 232        if (!len)
 233                return false;
 234
 235        if (header[0])
 236                return true;
 237
 238        return ax25_addr_parse(header + 1, len - 1, NULL, NULL, &digi, NULL,
 239                               NULL);
 240}
 241
 242const struct header_ops ax25_header_ops = {
 243        .create = ax25_hard_header,
 244        .validate = ax25_validate_header,
 245};
 246
 247EXPORT_SYMBOL(ax25_header_ops);
 248EXPORT_SYMBOL(ax25_ip_xmit);
 249