Blame view

net/ax25/ax25_iface.c 4.89 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
  /*
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/in.h>
  #include <linux/kernel.h>
70868eace   Ralf Baechle   [AX.25]: Move AX....
14
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
  #include <linux/spinlock.h>
  #include <linux/timer.h>
  #include <linux/string.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
22
23
24
25
  #include <net/ax25.h>
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
26
  #include <linux/uaccess.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
  #include <linux/fcntl.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
30
  static struct ax25_protocol *protocol_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
  static DEFINE_RWLOCK(protocol_list_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
32
  static HLIST_HEAD(ax25_linkfail_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
38
39
40
  static DEFINE_SPINLOCK(linkfail_lock);
  
  static struct listen_struct {
  	struct listen_struct *next;
  	ax25_address  callsign;
  	struct net_device *dev;
  } *listen_list = NULL;
  static DEFINE_SPINLOCK(listen_lock);
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
41
42
43
44
45
  /*
   * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT,
   * AX25_P_IP or AX25_P_ARP ...
   */
  void ax25_register_pid(struct ax25_protocol *ap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  {
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
47
  	write_lock_bh(&protocol_list_lock);
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
48
49
  	ap->next = protocol_list;
  	protocol_list = ap;
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
50
  	write_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  }
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
52
  EXPORT_SYMBOL_GPL(ax25_register_pid);
70868eace   Ralf Baechle   [AX.25]: Move AX....
53

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  void ax25_protocol_release(unsigned int pid)
  {
d8f969e60   David S. Miller   ax25: Fix set-but...
56
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57

95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
58
  	write_lock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  	protocol = protocol_list;
910d30b70   Ilpo Järvinen   ax25: more common...
60
61
  	if (protocol == NULL)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
64
  
  	if (protocol->pid == pid) {
  		protocol_list = protocol->next;
910d30b70   Ilpo Järvinen   ax25: more common...
65
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
  	}
  
  	while (protocol != NULL && protocol->next != NULL) {
  		if (protocol->next->pid == pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  			protocol->next = protocol->next->next;
910d30b70   Ilpo Järvinen   ax25: more common...
71
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
  		}
  
  		protocol = protocol->next;
  	}
910d30b70   Ilpo Järvinen   ax25: more common...
76
  out:
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
77
  	write_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
79
  EXPORT_SYMBOL(ax25_protocol_release);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
80
  void ax25_linkfail_register(struct ax25_linkfail *lf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  	spin_lock_bh(&linkfail_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
83
  	hlist_add_head(&lf->lf_node, &ax25_linkfail_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
  	spin_unlock_bh(&linkfail_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
86
  EXPORT_SYMBOL(ax25_linkfail_register);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
87
  void ax25_linkfail_release(struct ax25_linkfail *lf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  	spin_lock_bh(&linkfail_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
90
  	hlist_del_init(&lf->lf_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
  	spin_unlock_bh(&linkfail_lock);
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
93
  EXPORT_SYMBOL(ax25_linkfail_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
100
101
  int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
  {
  	struct listen_struct *listen;
  
  	if (ax25_listen_mine(callsign, dev))
  		return 0;
  
  	if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL)
81dcd1690   Ralf Baechle   [AX.25]: Fix unch...
102
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
106
107
108
109
110
  
  	listen->callsign = *callsign;
  	listen->dev      = dev;
  
  	spin_lock_bh(&listen_lock);
  	listen->next = listen_list;
  	listen_list  = listen;
  	spin_unlock_bh(&listen_lock);
81dcd1690   Ralf Baechle   [AX.25]: Fix unch...
111
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
113
  EXPORT_SYMBOL(ax25_listen_register);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
  {
  	struct listen_struct *s, *listen;
  
  	spin_lock_bh(&listen_lock);
  	listen = listen_list;
  	if (listen == NULL) {
  		spin_unlock_bh(&listen_lock);
  		return;
  	}
  
  	if (ax25cmp(&listen->callsign, callsign) == 0 && listen->dev == dev) {
  		listen_list = listen->next;
  		spin_unlock_bh(&listen_lock);
  		kfree(listen);
  		return;
  	}
  
  	while (listen != NULL && listen->next != NULL) {
  		if (ax25cmp(&listen->next->callsign, callsign) == 0 && listen->next->dev == dev) {
  			s = listen->next;
  			listen->next = listen->next->next;
  			spin_unlock_bh(&listen_lock);
  			kfree(s);
  			return;
  		}
  
  		listen = listen->next;
  	}
  	spin_unlock_bh(&listen_lock);
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
145
  EXPORT_SYMBOL(ax25_listen_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
  int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
  {
  	int (*res)(struct sk_buff *, ax25_cb *) = NULL;
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
149
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
  
  	read_lock(&protocol_list_lock);
  	for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
  		if (protocol->pid == pid) {
  			res = protocol->func;
  			break;
  		}
  	read_unlock(&protocol_list_lock);
  
  	return res;
  }
  
  int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
  {
  	struct listen_struct *listen;
  
  	spin_lock_bh(&listen_lock);
  	for (listen = listen_list; listen != NULL; listen = listen->next)
81dcd1690   Ralf Baechle   [AX.25]: Fix unch...
168
169
  		if (ax25cmp(&listen->callsign, callsign) == 0 &&
  		    (listen->dev == dev || listen->dev == NULL)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
175
176
177
178
179
  			spin_unlock_bh(&listen_lock);
  			return 1;
  	}
  	spin_unlock_bh(&listen_lock);
  
  	return 0;
  }
  
  void ax25_link_failed(ax25_cb *ax25, int reason)
  {
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
180
  	struct ax25_linkfail *lf;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
  
  	spin_lock_bh(&linkfail_lock);
b67bfe0d4   Sasha Levin   hlist: drop the n...
183
  	hlist_for_each_entry(lf, &ax25_linkfail_list, lf_node)
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
184
  		lf->func(ax25, reason);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
  	spin_unlock_bh(&linkfail_lock);
  }
  
  int ax25_protocol_is_registered(unsigned int pid)
  {
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
190
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  	int res = 0;
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
192
  	read_lock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
194
195
196
197
  	for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
  		if (protocol->pid == pid) {
  			res = 1;
  			break;
  		}
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
198
  	read_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
  
  	return res;
  }