Blame view

net/ax25/ax25_iface.c 4.95 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
26
27
28
29
30
  #include <net/ax25.h>
  #include <linux/inet.h>
  #include <linux/netdevice.h>
  #include <linux/skbuff.h>
  #include <net/sock.h>
  #include <asm/uaccess.h>
  #include <asm/system.h>
  #include <linux/fcntl.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
31
  static struct ax25_protocol *protocol_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  static DEFINE_RWLOCK(protocol_list_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
33
  static HLIST_HEAD(ax25_linkfail_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
37
38
39
40
41
  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...
42
43
44
45
46
  /*
   * 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
47
  {
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
48
  	write_lock_bh(&protocol_list_lock);
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
49
50
  	ap->next = protocol_list;
  	protocol_list = ap;
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
51
  	write_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  }
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
53
  EXPORT_SYMBOL_GPL(ax25_register_pid);
70868eace   Ralf Baechle   [AX.25]: Move AX....
54

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

95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
59
  	write_lock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
  	protocol = protocol_list;
910d30b70   Ilpo Järvinen   ax25: more common...
61
62
  	if (protocol == NULL)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
  
  	if (protocol->pid == pid) {
  		protocol_list = protocol->next;
910d30b70   Ilpo Järvinen   ax25: more common...
66
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
  	}
  
  	while (protocol != NULL && protocol->next != NULL) {
  		if (protocol->next->pid == pid) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  			protocol->next = protocol->next->next;
910d30b70   Ilpo Järvinen   ax25: more common...
72
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
74
75
76
  		}
  
  		protocol = protocol->next;
  	}
910d30b70   Ilpo Järvinen   ax25: more common...
77
  out:
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
78
  	write_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
80
  EXPORT_SYMBOL(ax25_protocol_release);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
81
  void ax25_linkfail_register(struct ax25_linkfail *lf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
  	spin_lock_bh(&linkfail_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
84
  	hlist_add_head(&lf->lf_node, &ax25_linkfail_list);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  	spin_unlock_bh(&linkfail_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
87
  EXPORT_SYMBOL(ax25_linkfail_register);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
88
  void ax25_linkfail_release(struct ax25_linkfail *lf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
90
  	spin_lock_bh(&linkfail_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
91
  	hlist_del_init(&lf->lf_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
  	spin_unlock_bh(&linkfail_lock);
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
94
  EXPORT_SYMBOL(ax25_linkfail_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
99
100
101
102
  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...
103
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
105
106
107
108
109
110
111
  
  	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...
112
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  }
70868eace   Ralf Baechle   [AX.25]: Move AX....
114
  EXPORT_SYMBOL(ax25_listen_register);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
145
  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....
146
  EXPORT_SYMBOL(ax25_listen_release);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
149
  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...
150
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  
  	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...
169
170
  		if (ax25cmp(&listen->callsign, callsign) == 0 &&
  		    (listen->dev == dev || listen->dev == NULL)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
175
176
177
178
179
180
  			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...
181
182
  	struct ax25_linkfail *lf;
  	struct hlist_node *node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
  
  	spin_lock_bh(&linkfail_lock);
a4282717c   Ralf Baechle   [AX.25]: Fix unch...
185
186
  	hlist_for_each_entry(lf, node, &ax25_linkfail_list, lf_node)
  		lf->func(ax25, reason);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
191
  	spin_unlock_bh(&linkfail_lock);
  }
  
  int ax25_protocol_is_registered(unsigned int pid)
  {
8d5cf596d   Ralf Baechle   [AX.25]: Fix unch...
192
  	struct ax25_protocol *protocol;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  	int res = 0;
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
194
  	read_lock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
199
  	for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
  		if (protocol->pid == pid) {
  			res = 1;
  			break;
  		}
95ff9f4d3   Ralf Baechle   [AX.25]: Fix lock...
200
  	read_unlock_bh(&protocol_list_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
  
  	return res;
  }