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