Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
net
x25
x25_forward.c
Go to the documentation of this file.
1
/*
2
* This module:
3
* This module is free software; you can redistribute it and/or
4
* modify it under the terms of the GNU General Public License
5
* as published by the Free Software Foundation; either version
6
* 2 of the License, or (at your option) any later version.
7
*
8
* History
9
* 03-01-2007 Added forwarding for x.25 Andrew Hendry
10
*/
11
#include <linux/if_arp.h>
12
#include <
linux/init.h
>
13
#include <linux/slab.h>
14
#include <
net/x25.h
>
15
16
LIST_HEAD
(x25_forward_list);
17
DEFINE_RWLOCK
(x25_forward_list_lock);
18
19
int
x25_forward_call
(
struct
x25_address
*
dest_addr
,
struct
x25_neigh
*
from
,
20
struct
sk_buff
*
skb
,
int
lci)
21
{
22
struct
x25_route
*rt;
23
struct
x25_neigh
*neigh_new =
NULL
;
24
struct
list_head
*
entry
;
25
struct
x25_forward
*x25_frwd, *new_frwd;
26
struct
sk_buff
*skbn;
27
short
same_lci = 0;
28
int
rc
= 0;
29
30
if
((rt =
x25_get_route
(dest_addr)) ==
NULL
)
31
goto
out_no_route;
32
33
if
((neigh_new =
x25_get_neigh
(rt->
dev
)) ==
NULL
) {
34
/* This shouldn't happen, if it occurs somehow
35
* do something sensible
36
*/
37
goto
out_put_route;
38
}
39
40
/* Avoid a loop. This is the normal exit path for a
41
* system with only one x.25 iface and default route
42
*/
43
if
(rt->
dev
== from->
dev
) {
44
goto
out_put_nb;
45
}
46
47
/* Remote end sending a call request on an already
48
* established LCI? It shouldn't happen, just in case..
49
*/
50
read_lock_bh
(&
x25_forward_list_lock
);
51
list_for_each
(entry, &
x25_forward_list
) {
52
x25_frwd =
list_entry
(entry,
struct
x25_forward
,
node
);
53
if
(x25_frwd->
lci
== lci) {
54
printk
(
KERN_WARNING
"X.25: call request for lci which is already registered!, transmitting but not registering new pair\n"
);
55
same_lci = 1;
56
}
57
}
58
read_unlock_bh
(&
x25_forward_list_lock
);
59
60
/* Save the forwarding details for future traffic */
61
if
(!same_lci){
62
if
((new_frwd =
kmalloc
(
sizeof
(
struct
x25_forward
),
63
GFP_ATOMIC
)) ==
NULL
){
64
rc = -
ENOMEM
;
65
goto
out_put_nb;
66
}
67
new_frwd->
lci
= lci;
68
new_frwd->
dev1
= rt->
dev
;
69
new_frwd->
dev2
= from->
dev
;
70
write_lock_bh
(&
x25_forward_list_lock
);
71
list_add(&new_frwd->
node
, &
x25_forward_list
);
72
write_unlock_bh
(&
x25_forward_list_lock
);
73
}
74
75
/* Forward the call request */
76
if
( (skbn =
skb_clone
(skb,
GFP_ATOMIC
)) ==
NULL
){
77
goto
out_put_nb;
78
}
79
x25_transmit_link
(skbn, neigh_new);
80
rc = 1;
81
82
83
out_put_nb:
84
x25_neigh_put(neigh_new);
85
86
out_put_route:
87
x25_route_put(rt);
88
89
out_no_route:
90
return
rc
;
91
}
92
93
94
int
x25_forward_data
(
int
lci,
struct
x25_neigh
*
from
,
struct
sk_buff
*
skb
) {
95
96
struct
x25_forward
*frwd;
97
struct
list_head
*
entry
;
98
struct
net_device
*peer =
NULL
;
99
struct
x25_neigh
*nb;
100
struct
sk_buff
*skbn;
101
int
rc
= 0;
102
103
read_lock_bh
(&
x25_forward_list_lock
);
104
list_for_each
(entry, &
x25_forward_list
) {
105
frwd =
list_entry
(entry,
struct
x25_forward
,
node
);
106
if
(frwd->
lci
== lci) {
107
/* The call is established, either side can send */
108
if
(from->
dev
== frwd->
dev1
) {
109
peer = frwd->
dev2
;
110
}
else
{
111
peer = frwd->
dev1
;
112
}
113
break
;
114
}
115
}
116
read_unlock_bh
(&
x25_forward_list_lock
);
117
118
if
( (nb =
x25_get_neigh
(peer)) ==
NULL
)
119
goto
out
;
120
121
if
( (skbn = pskb_copy(skb,
GFP_ATOMIC
)) ==
NULL
){
122
goto
output
;
123
124
}
125
x25_transmit_link
(skbn, nb);
126
127
rc = 1;
128
output
:
129
x25_neigh_put(nb);
130
out
:
131
return
rc
;
132
}
133
134
void
x25_clear_forward_by_lci
(
unsigned
int
lci)
135
{
136
struct
x25_forward
*fwd;
137
struct
list_head
*
entry
, *
tmp
;
138
139
write_lock_bh
(&
x25_forward_list_lock
);
140
141
list_for_each_safe
(entry, tmp, &
x25_forward_list
) {
142
fwd =
list_entry
(entry,
struct
x25_forward
,
node
);
143
if
(fwd->
lci
== lci) {
144
list_del
(&fwd->
node
);
145
kfree
(fwd);
146
}
147
}
148
write_unlock_bh
(&
x25_forward_list_lock
);
149
}
150
151
152
void
x25_clear_forward_by_dev
(
struct
net_device
*
dev
)
153
{
154
struct
x25_forward
*fwd;
155
struct
list_head
*
entry
, *
tmp
;
156
157
write_lock_bh
(&
x25_forward_list_lock
);
158
159
list_for_each_safe
(entry, tmp, &
x25_forward_list
) {
160
fwd =
list_entry
(entry,
struct
x25_forward
,
node
);
161
if
((fwd->
dev1
== dev) || (fwd->
dev2
== dev)){
162
list_del
(&fwd->
node
);
163
kfree
(fwd);
164
}
165
}
166
write_unlock_bh
(&
x25_forward_list_lock
);
167
}
Generated on Thu Jan 10 2013 15:02:38 for Linux Kernel by
1.8.2