Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.19-rc5 278 lines 6.3 kB view raw
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 32static struct protocol_struct { 33 struct protocol_struct *next; 34 unsigned int pid; 35 int (*func)(struct sk_buff *, ax25_cb *); 36} *protocol_list = NULL; 37static DEFINE_RWLOCK(protocol_list_lock); 38 39static struct linkfail_struct { 40 struct linkfail_struct *next; 41 void (*func)(ax25_cb *, int); 42} *linkfail_list = NULL; 43static DEFINE_SPINLOCK(linkfail_lock); 44 45static struct listen_struct { 46 struct listen_struct *next; 47 ax25_address callsign; 48 struct net_device *dev; 49} *listen_list = NULL; 50static DEFINE_SPINLOCK(listen_lock); 51 52int 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 77EXPORT_SYMBOL(ax25_protocol_register); 78 79void 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 111EXPORT_SYMBOL(ax25_protocol_release); 112 113int 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 130EXPORT_SYMBOL(ax25_linkfail_register); 131 132void 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 164EXPORT_SYMBOL(ax25_linkfail_release); 165 166int 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 187EXPORT_SYMBOL(ax25_listen_register); 188 189void 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 221EXPORT_SYMBOL(ax25_listen_release); 222 223int (*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 239int 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 254void 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 264int 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}