0001
0002
0003
0004
0005
0006 #include <linux/errno.h>
0007 #include <linux/types.h>
0008 #include <linux/socket.h>
0009 #include <linux/slab.h>
0010 #include <linux/in.h>
0011 #include <linux/kernel.h>
0012 #include <linux/timer.h>
0013 #include <linux/string.h>
0014 #include <linux/sockios.h>
0015 #include <linux/net.h>
0016 #include <linux/spinlock.h>
0017 #include <net/ax25.h>
0018 #include <linux/inet.h>
0019 #include <linux/netdevice.h>
0020 #include <linux/if_arp.h>
0021 #include <linux/skbuff.h>
0022 #include <net/sock.h>
0023 #include <linux/uaccess.h>
0024 #include <linux/fcntl.h>
0025 #include <linux/mm.h>
0026 #include <linux/interrupt.h>
0027 #include <linux/init.h>
0028
0029 ax25_dev *ax25_dev_list;
0030 DEFINE_SPINLOCK(ax25_dev_lock);
0031
0032 ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
0033 {
0034 ax25_dev *ax25_dev, *res = NULL;
0035
0036 spin_lock_bh(&ax25_dev_lock);
0037 for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
0038 if (ax25cmp(addr, (const ax25_address *)ax25_dev->dev->dev_addr) == 0) {
0039 res = ax25_dev;
0040 ax25_dev_hold(ax25_dev);
0041 }
0042 spin_unlock_bh(&ax25_dev_lock);
0043
0044 return res;
0045 }
0046
0047
0048
0049
0050
0051 void ax25_dev_device_up(struct net_device *dev)
0052 {
0053 ax25_dev *ax25_dev;
0054
0055 ax25_dev = kzalloc(sizeof(*ax25_dev), GFP_KERNEL);
0056 if (!ax25_dev) {
0057 printk(KERN_ERR "AX.25: ax25_dev_device_up - out of memory\n");
0058 return;
0059 }
0060
0061 refcount_set(&ax25_dev->refcount, 1);
0062 dev->ax25_ptr = ax25_dev;
0063 ax25_dev->dev = dev;
0064 netdev_hold(dev, &ax25_dev->dev_tracker, GFP_KERNEL);
0065 ax25_dev->forward = NULL;
0066 ax25_dev->device_up = true;
0067
0068 ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE;
0069 ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE;
0070 ax25_dev->values[AX25_VALUES_BACKOFF] = AX25_DEF_BACKOFF;
0071 ax25_dev->values[AX25_VALUES_CONMODE] = AX25_DEF_CONMODE;
0072 ax25_dev->values[AX25_VALUES_WINDOW] = AX25_DEF_WINDOW;
0073 ax25_dev->values[AX25_VALUES_EWINDOW] = AX25_DEF_EWINDOW;
0074 ax25_dev->values[AX25_VALUES_T1] = AX25_DEF_T1;
0075 ax25_dev->values[AX25_VALUES_T2] = AX25_DEF_T2;
0076 ax25_dev->values[AX25_VALUES_T3] = AX25_DEF_T3;
0077 ax25_dev->values[AX25_VALUES_IDLE] = AX25_DEF_IDLE;
0078 ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2;
0079 ax25_dev->values[AX25_VALUES_PACLEN] = AX25_DEF_PACLEN;
0080 ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL;
0081 ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
0082
0083 #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER)
0084 ax25_ds_setup_timer(ax25_dev);
0085 #endif
0086
0087 spin_lock_bh(&ax25_dev_lock);
0088 ax25_dev->next = ax25_dev_list;
0089 ax25_dev_list = ax25_dev;
0090 spin_unlock_bh(&ax25_dev_lock);
0091 ax25_dev_hold(ax25_dev);
0092
0093 ax25_register_dev_sysctl(ax25_dev);
0094 }
0095
0096 void ax25_dev_device_down(struct net_device *dev)
0097 {
0098 ax25_dev *s, *ax25_dev;
0099
0100 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
0101 return;
0102
0103 ax25_unregister_dev_sysctl(ax25_dev);
0104
0105 spin_lock_bh(&ax25_dev_lock);
0106
0107 #ifdef CONFIG_AX25_DAMA_SLAVE
0108 ax25_ds_del_timer(ax25_dev);
0109 #endif
0110
0111
0112
0113
0114 for (s = ax25_dev_list; s != NULL; s = s->next)
0115 if (s->forward == dev)
0116 s->forward = NULL;
0117
0118 if ((s = ax25_dev_list) == ax25_dev) {
0119 ax25_dev_list = s->next;
0120 goto unlock_put;
0121 }
0122
0123 while (s != NULL && s->next != NULL) {
0124 if (s->next == ax25_dev) {
0125 s->next = ax25_dev->next;
0126 goto unlock_put;
0127 }
0128
0129 s = s->next;
0130 }
0131 spin_unlock_bh(&ax25_dev_lock);
0132 dev->ax25_ptr = NULL;
0133 ax25_dev_put(ax25_dev);
0134 return;
0135
0136 unlock_put:
0137 spin_unlock_bh(&ax25_dev_lock);
0138 ax25_dev_put(ax25_dev);
0139 dev->ax25_ptr = NULL;
0140 netdev_put(dev, &ax25_dev->dev_tracker);
0141 ax25_dev_put(ax25_dev);
0142 }
0143
0144 int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
0145 {
0146 ax25_dev *ax25_dev, *fwd_dev;
0147
0148 if ((ax25_dev = ax25_addr_ax25dev(&fwd->port_from)) == NULL)
0149 return -EINVAL;
0150
0151 switch (cmd) {
0152 case SIOCAX25ADDFWD:
0153 fwd_dev = ax25_addr_ax25dev(&fwd->port_to);
0154 if (!fwd_dev) {
0155 ax25_dev_put(ax25_dev);
0156 return -EINVAL;
0157 }
0158 if (ax25_dev->forward) {
0159 ax25_dev_put(fwd_dev);
0160 ax25_dev_put(ax25_dev);
0161 return -EINVAL;
0162 }
0163 ax25_dev->forward = fwd_dev->dev;
0164 ax25_dev_put(fwd_dev);
0165 ax25_dev_put(ax25_dev);
0166 break;
0167
0168 case SIOCAX25DELFWD:
0169 if (!ax25_dev->forward) {
0170 ax25_dev_put(ax25_dev);
0171 return -EINVAL;
0172 }
0173 ax25_dev->forward = NULL;
0174 ax25_dev_put(ax25_dev);
0175 break;
0176
0177 default:
0178 ax25_dev_put(ax25_dev);
0179 return -EINVAL;
0180 }
0181
0182 return 0;
0183 }
0184
0185 struct net_device *ax25_fwd_dev(struct net_device *dev)
0186 {
0187 ax25_dev *ax25_dev;
0188
0189 if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
0190 return dev;
0191
0192 if (ax25_dev->forward == NULL)
0193 return dev;
0194
0195 return ax25_dev->forward;
0196 }
0197
0198
0199
0200
0201 void __exit ax25_dev_free(void)
0202 {
0203 ax25_dev *s, *ax25_dev;
0204
0205 spin_lock_bh(&ax25_dev_lock);
0206 ax25_dev = ax25_dev_list;
0207 while (ax25_dev != NULL) {
0208 s = ax25_dev;
0209 netdev_put(ax25_dev->dev, &ax25_dev->dev_tracker);
0210 ax25_dev = ax25_dev->next;
0211 kfree(s);
0212 }
0213 ax25_dev_list = NULL;
0214 spin_unlock_bh(&ax25_dev_lock);
0215 }