1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License, or 5 * (at your option) any later version. 6 * 7 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk) 8 */ 9 #include <linux/errno.h> 10 #include <linux/types.h> 11 #include <linux/socket.h> 12 #include <linux/in.h> 13 #include <linux/kernel.h> 14 #include <linux/module.h> 15 #include <linux/sched.h> 16 #include <linux/spinlock.h> 17 #include <linux/timer.h> 18 #include <linux/string.h> 19 #include <linux/sockios.h> 20 #include <linux/net.h> 21 #include <net/ax25.h> 22 #include <linux/inet.h> 23 #include <linux/netdevice.h> 24 #include <linux/skbuff.h> 25 #include <net/sock.h> 26 #include <asm/uaccess.h> 27 #include <asm/system.h> 28 #include <linux/fcntl.h> 29 #include <linux/mm.h> 30 #include <linux/interrupt.h> 31 32 static struct ax25_protocol *protocol_list; 33 static DEFINE_RWLOCK(protocol_list_lock); 34 35 static HLIST_HEAD(ax25_linkfail_list); 36 static DEFINE_SPINLOCK(linkfail_lock); 37 38 static struct listen_struct { 39 struct listen_struct *next; 40 ax25_address callsign; 41 struct net_device *dev; 42 } *listen_list = NULL; 43 static DEFINE_SPINLOCK(listen_lock); 44 45 /* 46 * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT, 47 * AX25_P_IP or AX25_P_ARP ... 48 */ 49 void ax25_register_pid(struct ax25_protocol *ap) 50 { 51 write_lock_bh(&protocol_list_lock); 52 ap->next = protocol_list; 53 protocol_list = ap; 54 write_unlock_bh(&protocol_list_lock); 55 } 56 57 EXPORT_SYMBOL_GPL(ax25_register_pid); 58 59 void ax25_protocol_release(unsigned int pid) 60 { 61 struct ax25_protocol *s, *protocol; 62 63 write_lock_bh(&protocol_list_lock); 64 protocol = protocol_list; 65 if (protocol == NULL) { 66 write_unlock_bh(&protocol_list_lock); 67 return; 68 } 69 70 if (protocol->pid == pid) { 71 protocol_list = protocol->next; 72 write_unlock_bh(&protocol_list_lock); 73 kfree(protocol); 74 return; 75 } 76 77 while (protocol != NULL && protocol->next != NULL) { 78 if (protocol->next->pid == pid) { 79 s = protocol->next; 80 protocol->next = protocol->next->next; 81 write_unlock_bh(&protocol_list_lock); 82 kfree(s); 83 return; 84 } 85 86 protocol = protocol->next; 87 } 88 write_unlock_bh(&protocol_list_lock); 89 } 90 91 EXPORT_SYMBOL(ax25_protocol_release); 92 93 void ax25_linkfail_register(struct ax25_linkfail *lf) 94 { 95 spin_lock_bh(&linkfail_lock); 96 hlist_add_head(&lf->lf_node, &ax25_linkfail_list); 97 spin_unlock_bh(&linkfail_lock); 98 } 99 100 EXPORT_SYMBOL(ax25_linkfail_register); 101 102 void ax25_linkfail_release(struct ax25_linkfail *lf) 103 { 104 spin_lock_bh(&linkfail_lock); 105 hlist_del_init(&lf->lf_node); 106 spin_unlock_bh(&linkfail_lock); 107 } 108 109 EXPORT_SYMBOL(ax25_linkfail_release); 110 111 int ax25_listen_register(ax25_address *callsign, struct net_device *dev) 112 { 113 struct listen_struct *listen; 114 115 if (ax25_listen_mine(callsign, dev)) 116 return 0; 117 118 if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL) 119 return -ENOMEM; 120 121 listen->callsign = *callsign; 122 listen->dev = dev; 123 124 spin_lock_bh(&listen_lock); 125 listen->next = listen_list; 126 listen_list = listen; 127 spin_unlock_bh(&listen_lock); 128 129 return 0; 130 } 131 132 EXPORT_SYMBOL(ax25_listen_register); 133 134 void ax25_listen_release(ax25_address *callsign, struct net_device *dev) 135 { 136 struct listen_struct *s, *listen; 137 138 spin_lock_bh(&listen_lock); 139 listen = listen_list; 140 if (listen == NULL) { 141 spin_unlock_bh(&listen_lock); 142 return; 143 } 144 145 if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) { 146 listen_list = listen->next; 147 spin_unlock_bh(&listen_lock); 148 kfree(listen); 149 return; 150 } 151 152 while (listen != NULL && listen->next != NULL) { 153 if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) { 154 s = listen->next; 155 listen->next = listen->next->next; 156 spin_unlock_bh(&listen_lock); 157 kfree(s); 158 return; 159 } 160 161 listen = listen->next; 162 } 163 spin_unlock_bh(&listen_lock); 164 } 165 166 EXPORT_SYMBOL(ax25_listen_release); 167 168 int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *) 169 { 170 int (*res)(struct sk_buff *, ax25_cb *) = NULL; 171 struct ax25_protocol *protocol; 172 173 read_lock(&protocol_list_lock); 174 for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) 175 if (protocol->pid == pid) { 176 res = protocol->func; 177 break; 178 } 179 read_unlock(&protocol_list_lock); 180 181 return res; 182 } 183 184 int ax25_listen_mine(ax25_address *callsign, struct net_device *dev) 185 { 186 struct listen_struct *listen; 187 188 spin_lock_bh(&listen_lock); 189 for (listen = listen_list; listen != NULL; listen = listen->next) 190 if (ax25cmp(&listen->callsign, callsign) == 0 && 191 (listen->dev == dev || listen->dev == NULL)) { 192 spin_unlock_bh(&listen_lock); 193 return 1; 194 } 195 spin_unlock_bh(&listen_lock); 196 197 return 0; 198 } 199 200 void ax25_link_failed(ax25_cb *ax25, int reason) 201 { 202 struct ax25_linkfail *lf; 203 struct hlist_node *node; 204 205 spin_lock_bh(&linkfail_lock); 206 hlist_for_each_entry(lf, node, &ax25_linkfail_list, lf_node) 207 lf->func(ax25, reason); 208 spin_unlock_bh(&linkfail_lock); 209 } 210 211 int ax25_protocol_is_registered(unsigned int pid) 212 { 213 struct ax25_protocol *protocol; 214 int res = 0; 215 216 read_lock_bh(&protocol_list_lock); 217 for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) 218 if (protocol->pid == pid) { 219 res = 1; 220 break; 221 } 222 read_unlock_bh(&protocol_list_lock); 223 224 return res; 225 } 226