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