linux/net/ax25/ax25_dev.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/slab.h>
  10#include <linux/in.h>
  11#include <linux/kernel.h>
  12#include <linux/timer.h>
  13#include <linux/string.h>
  14#include <linux/sockios.h>
  15#include <linux/net.h>
  16#include <linux/spinlock.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/mm.h>
  26#include <linux/interrupt.h>
  27#include <linux/init.h>
  28
  29ax25_dev *ax25_dev_list;
  30DEFINE_SPINLOCK(ax25_dev_lock);
  31
  32ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
  33{
  34        ax25_dev *ax25_dev, *res = NULL;
  35
  36        spin_lock_bh(&ax25_dev_lock);
  37        for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
  38                if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
  39                        res = ax25_dev;
  40                }
  41        spin_unlock_bh(&ax25_dev_lock);
  42
  43        return res;
  44}
  45
  46/*
  47 *      This is called when an interface is brought up. These are
  48 *      reasonable defaults.
  49 */
  50void ax25_dev_device_up(struct net_device *dev)
  51{
  52        ax25_dev *ax25_dev;
  53
  54        if ((ax25_dev = kzalloc(sizeof(*ax25_dev), GFP_ATOMIC)) == NULL) {
  55                printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
  56                return;
  57        }
  58
  59        dev->ax25_ptr     = ax25_dev;
  60        ax25_dev->dev     = dev;
  61        dev_hold(dev);
  62        ax25_dev->forward = NULL;
  63
  64        ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
  65        ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
  66        ax25_dev->values[AX25_VALUES_BACKOFF]   = AX25_DEF_BACKOFF;
  67        ax25_dev->values[AX25_VALUES_CONMODE]   = AX25_DEF_CONMODE;
  68        ax25_dev->values[AX25_VALUES_WINDOW]    = AX25_DEF_WINDOW;
  69        ax25_dev->values[AX25_VALUES_EWINDOW]   = AX25_DEF_EWINDOW;
  70        ax25_dev->values[AX25_VALUES_T1]        = AX25_DEF_T1;
  71        ax25_dev->values[AX25_VALUES_T2]        = AX25_DEF_T2;
  72        ax25_dev->values[AX25_VALUES_T3]        = AX25_DEF_T3;
  73        ax25_dev->values[AX25_VALUES_IDLE]      = AX25_DEF_IDLE;
  74        ax25_dev->values[AX25_VALUES_N2]        = AX25_DEF_N2;
  75        ax25_dev->values[AX25_VALUES_PACLEN]    = AX25_DEF_PACLEN;
  76        ax25_dev->values[AX25_VALUES_PROTOCOL]  = AX25_DEF_PROTOCOL;
  77        ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
  78
  79#if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
  80        ax25_ds_setup_timer(ax25_dev);
  81#endif
  82
  83        spin_lock_bh(&ax25_dev_lock);
  84        ax25_dev->next = ax25_dev_list;
  85        ax25_dev_list  = ax25_dev;
  86        spin_unlock_bh(&ax25_dev_lock);
  87
  88        ax25_register_dev_sysctl(ax25_dev);
  89}
  90
  91void ax25_dev_device_down(struct net_device *dev)
  92{
  93        ax25_dev *s, *ax25_dev;
  94
  95        if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
  96                return;
  97
  98        ax25_unregister_dev_sysctl(ax25_dev);
  99
 100        spin_lock_bh(&ax25_dev_lock);
 101
 102#ifdef CONFIG_AX25_DAMA_SLAVE
 103        ax25_ds_del_timer(ax25_dev);
 104#endif
 105
 106        /*
 107         *      Remove any packet forwarding that points to this device.
 108         */
 109        for (s = ax25_dev_list; s != NULL; s = s->next)
 110                if (s->forward == dev)
 111                        s->forward = NULL;
 112
 113        if ((s = ax25_dev_list) == ax25_dev) {
 114                ax25_dev_list = s->next;
 115                spin_unlock_bh(&ax25_dev_lock);
 116                dev->ax25_ptr = NULL;
 117                dev_put(dev);
 118                kfree(ax25_dev);
 119                return;
 120        }
 121
 122        while (s != NULL && s->next != NULL) {
 123                if (s->next == ax25_dev) {
 124                        s->next = ax25_dev->next;
 125                        spin_unlock_bh(&ax25_dev_lock);
 126                        dev->ax25_ptr = NULL;
 127                        dev_put(dev);
 128                        kfree(ax25_dev);
 129                        return;
 130                }
 131
 132                s = s->next;
 133        }
 134        spin_unlock_bh(&ax25_dev_lock);
 135        dev->ax25_ptr = NULL;
 136}
 137
 138int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
 139{
 140        ax25_dev *ax25_dev, *fwd_dev;
 141
 142        if ((ax25_dev = ax25_addr_ax25dev(&fwd->port_from)) == NULL)
 143                return -EINVAL;
 144
 145        switch (cmd) {
 146        case SIOCAX25ADDFWD:
 147                if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL)
 148                        return -EINVAL;
 149                if (ax25_dev->forward != NULL)
 150                        return -EINVAL;
 151                ax25_dev->forward = fwd_dev->dev;
 152                break;
 153
 154        case SIOCAX25DELFWD:
 155                if (ax25_dev->forward == NULL)
 156                        return -EINVAL;
 157                ax25_dev->forward = NULL;
 158                break;
 159
 160        default:
 161                return -EINVAL;
 162        }
 163
 164        return 0;
 165}
 166
 167struct net_device *ax25_fwd_dev(struct net_device *dev)
 168{
 169        ax25_dev *ax25_dev;
 170
 171        if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
 172                return dev;
 173
 174        if (ax25_dev->forward == NULL)
 175                return dev;
 176
 177        return ax25_dev->forward;
 178}
 179
 180/*
 181 *      Free all memory associated with device structures.
 182 */
 183void __exit ax25_dev_free(void)
 184{
 185        ax25_dev *s, *ax25_dev;
 186
 187        spin_lock_bh(&ax25_dev_lock);
 188        ax25_dev = ax25_dev_list;
 189        while (ax25_dev != NULL) {
 190                s        = ax25_dev;
 191                dev_put(ax25_dev->dev);
 192                ax25_dev = ax25_dev->next;
 193                kfree(s);
 194        }
 195        ax25_dev_list = NULL;
 196        spin_unlock_bh(&ax25_dev_lock);
 197}
 198