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 struct linkfail_struct { 36 struct linkfail_struct *next; 37 void (*func)(ax25_cb *, int); 38 } *linkfail_list = NULL; 39 static DEFINE_SPINLOCK(linkfail_lock); 40 41 static struct listen_struct { 42 struct listen_struct *next; 43 ax25_address callsign; 44 struct net_device *dev; 45 } *listen_list = NULL; 46 static DEFINE_SPINLOCK(listen_lock); 47 48 /* 49 * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT, 50 * AX25_P_IP or AX25_P_ARP ... 51 */ 52 void ax25_register_pid(struct ax25_protocol *ap) 53 { 54 write_lock_bh(&protocol_list_lock); 55 ap->next = protocol_list; 56 protocol_list = ap; 57 write_unlock_bh(&protocol_list_lock); 58 } 59 60 EXPORT_SYMBOL_GPL(ax25_register_pid); 61 62 void ax25_protocol_release(unsigned int pid) 63 { 64 struct ax25_protocol *s, *protocol; 65 66 write_lock_bh(&protocol_list_lock); 67 protocol = protocol_list; 68 if (protocol == NULL) { 69 write_unlock_bh(&protocol_list_lock); 70 return; 71 } 72 73 if (protocol->pid == pid) { 74 protocol_list = protocol->next; 75 write_unlock_bh(&protocol_list_lock); 76 kfree(protocol); 77 return; 78 } 79 80 while (protocol != NULL && protocol->next != NULL) { 81 if (protocol->next->pid == pid) { 82 s = protocol->next; 83 protocol->next = protocol->next->next; 84 write_unlock_bh(&protocol_list_lock); 85 kfree(s); 86 return; 87 } 88 89 protocol = protocol->next; 90 } 91 write_unlock_bh(&protocol_list_lock); 92 } 93 94 EXPORT_SYMBOL(ax25_protocol_release); 95 96 int ax25_linkfail_register(void (*func)(ax25_cb *, int)) 97 { 98 struct linkfail_struct *linkfail; 99 100 if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL) 101 return 0; 102 103 linkfail->func = func; 104 105 spin_lock_bh(&linkfail_lock); 106 linkfail->next = linkfail_list; 107 linkfail_list = linkfail; 108 spin_unlock_bh(&linkfail_lock); 109 110 return 1; 111 } 112 113 EXPORT_SYMBOL(ax25_linkfail_register); 114 115 void ax25_linkfail_release(void (*func)(ax25_cb *, int)) 116 { 117 struct linkfail_struct *s, *linkfail; 118 119 spin_lock_bh(&linkfail_lock); 120 linkfail = linkfail_list; 121 if (linkfail == NULL) { 122 spin_unlock_bh(&linkfail_lock); 123 return; 124 } 125 126 if (linkfail->func == func) { 127 linkfail_list = linkfail->next; 128 spin_unlock_bh(&linkfail_lock); 129 kfree(linkfail); 130 return; 131 } 132 133 while (linkfail != NULL && linkfail->next != NULL) { 134 if (linkfail->next->func == func) { 135 s = linkfail->next; 136 linkfail->next = linkfail->next->next; 137 spin_unlock_bh(&linkfail_lock); 138 kfree(s); 139 return; 140 } 141 142 linkfail = linkfail->next; 143 } 144 spin_unlock_bh(&linkfail_lock); 145 } 146 147 EXPORT_SYMBOL(ax25_linkfail_release); 148 149 int ax25_listen_register(ax25_address *callsign, struct net_device *dev) 150 { 151 struct listen_struct *listen; 152 153 if (ax25_listen_mine(callsign, dev)) 154 return 0; 155 156 if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL) 157 return 0; 158 159 listen->callsign = *callsign; 160 listen->dev = dev; 161 162 spin_lock_bh(&listen_lock); 163 listen->next = listen_list; 164 listen_list = listen; 165 spin_unlock_bh(&listen_lock); 166 167 return 1; 168 } 169 170 EXPORT_SYMBOL(ax25_listen_register); 171 172 void ax25_listen_release(ax25_address *callsign, struct net_device *dev) 173 { 174 struct listen_struct *s, *listen; 175 176 spin_lock_bh(&listen_lock); 177 listen = listen_list; 178 if (listen == NULL) { 179 spin_unlock_bh(&listen_lock); 180 return; 181 } 182 183 if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) { 184 listen_list = listen->next; 185 spin_unlock_bh(&listen_lock); 186 kfree(listen); 187 return; 188 } 189 190 while (listen != NULL && listen->next != NULL) { 191 if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) { 192 s = listen->next; 193 listen->next = listen->next->next; 194 spin_unlock_bh(&listen_lock); 195 kfree(s); 196 return; 197 } 198 199 listen = listen->next; 200 } 201 spin_unlock_bh(&listen_lock); 202 } 203 204 EXPORT_SYMBOL(ax25_listen_release); 205 206 int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *) 207 { 208 int (*res)(struct sk_buff *, ax25_cb *) = NULL; 209 struct ax25_protocol *protocol; 210 211 read_lock(&protocol_list_lock); 212 for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) 213 if (protocol->pid == pid) { 214 res = protocol->func; 215 break; 216 } 217 read_unlock(&protocol_list_lock); 218 219 return res; 220 } 221 222 int ax25_listen_mine(ax25_address *callsign, struct net_device *dev) 223 { 224 struct listen_struct *listen; 225 226 spin_lock_bh(&listen_lock); 227 for (listen = listen_list; listen != NULL; listen = listen->next) 228 if (ax25cmp(&listen->callsign, callsign) == 0 && (listen->dev == dev || listen->dev == NULL)) { 229 spin_unlock_bh(&listen_lock); 230 return 1; 231 } 232 spin_unlock_bh(&listen_lock); 233 234 return 0; 235 } 236 237 void ax25_link_failed(ax25_cb *ax25, int reason) 238 { 239 struct linkfail_struct *linkfail; 240 241 spin_lock_bh(&linkfail_lock); 242 for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next) 243 (linkfail->func)(ax25, reason); 244 spin_unlock_bh(&linkfail_lock); 245 } 246 247 int ax25_protocol_is_registered(unsigned int pid) 248 { 249 struct ax25_protocol *protocol; 250 int res = 0; 251 252 read_lock_bh(&protocol_list_lock); 253 for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) 254 if (protocol->pid == pid) { 255 res = 1; 256 break; 257 } 258 read_unlock_bh(&protocol_list_lock); 259 260 return res; 261 } 262