2 * Implements the IPX routing routines.
3 * Code moved from af_ipx.c.
5 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>, 2003
7 * See net/ipx/ChangeLog.
10 #include <linux/list.h>
11 #include <linux/route.h>
12 #include <linux/slab.h>
13 #include <linux/spinlock.h>
18 LIST_HEAD(ipx_routes
);
19 DEFINE_RWLOCK(ipx_routes_lock
);
21 extern struct ipx_interface
*ipx_internal_net
;
23 extern __be16
ipx_cksum(struct ipxhdr
*packet
, int length
);
24 extern struct ipx_interface
*ipxitf_find_using_net(__be32 net
);
25 extern int ipxitf_demux_socket(struct ipx_interface
*intrfc
,
26 struct sk_buff
*skb
, int copy
);
27 extern int ipxitf_demux_socket(struct ipx_interface
*intrfc
,
28 struct sk_buff
*skb
, int copy
);
29 extern int ipxitf_send(struct ipx_interface
*intrfc
, struct sk_buff
*skb
,
31 extern struct ipx_interface
*ipxitf_find_using_net(__be32 net
);
33 struct ipx_route
*ipxrtr_lookup(__be32 net
)
37 read_lock_bh(&ipx_routes_lock
);
38 list_for_each_entry(r
, &ipx_routes
, node
)
39 if (r
->ir_net
== net
) {
45 read_unlock_bh(&ipx_routes_lock
);
50 * Caller must hold a reference to intrfc
52 int ipxrtr_add_route(__be32 network
, struct ipx_interface
*intrfc
,
58 /* Get a route structure; either existing or create */
59 rt
= ipxrtr_lookup(network
);
61 rt
= kmalloc(sizeof(*rt
), GFP_ATOMIC
);
66 atomic_set(&rt
->refcnt
, 1);
68 write_lock_bh(&ipx_routes_lock
);
69 list_add(&rt
->node
, &ipx_routes
);
70 write_unlock_bh(&ipx_routes_lock
);
73 if (intrfc
== ipx_internal_net
)
78 rt
->ir_intrfc
= intrfc
;
80 memset(rt
->ir_router_node
, '\0', IPX_NODE_LEN
);
83 memcpy(rt
->ir_router_node
, node
, IPX_NODE_LEN
);
94 void ipxrtr_del_routes(struct ipx_interface
*intrfc
)
96 struct ipx_route
*r
, *tmp
;
98 write_lock_bh(&ipx_routes_lock
);
99 list_for_each_entry_safe(r
, tmp
, &ipx_routes
, node
)
100 if (r
->ir_intrfc
== intrfc
) {
104 write_unlock_bh(&ipx_routes_lock
);
107 static int ipxrtr_create(struct ipx_route_definition
*rd
)
109 struct ipx_interface
*intrfc
;
110 int rc
= -ENETUNREACH
;
112 /* Find the appropriate interface */
113 intrfc
= ipxitf_find_using_net(rd
->ipx_router_network
);
116 rc
= ipxrtr_add_route(rd
->ipx_network
, intrfc
, rd
->ipx_router_node
);
122 static int ipxrtr_delete(__be32 net
)
124 struct ipx_route
*r
, *tmp
;
127 write_lock_bh(&ipx_routes_lock
);
128 list_for_each_entry_safe(r
, tmp
, &ipx_routes
, node
)
129 if (r
->ir_net
== net
) {
130 /* Directly connected; can't lose route */
141 write_unlock_bh(&ipx_routes_lock
);
146 * The skb has to be unshared, we'll end up calling ipxitf_send, that'll
149 int ipxrtr_route_skb(struct sk_buff
*skb
)
151 struct ipxhdr
*ipx
= ipx_hdr(skb
);
152 struct ipx_route
*r
= ipxrtr_lookup(IPX_SKB_CB(skb
)->ipx_dest_net
);
154 if (!r
) { /* no known route */
159 ipxitf_hold(r
->ir_intrfc
);
160 ipxitf_send(r
->ir_intrfc
, skb
, r
->ir_routed
?
161 r
->ir_router_node
: ipx
->ipx_dest
.node
);
162 ipxitf_put(r
->ir_intrfc
);
169 * Route an outgoing frame from a socket.
171 int ipxrtr_route_packet(struct sock
*sk
, struct sockaddr_ipx
*usipx
,
172 struct iovec
*iov
, size_t len
, int noblock
)
175 struct ipx_sock
*ipxs
= ipx_sk(sk
);
176 struct ipx_interface
*intrfc
;
180 struct ipx_route
*rt
= NULL
;
183 /* Find the appropriate interface on which to send packet */
184 if (!usipx
->sipx_network
&& ipx_primary_net
) {
185 usipx
->sipx_network
= ipx_primary_net
->if_netnum
;
186 intrfc
= ipx_primary_net
;
188 rt
= ipxrtr_lookup(usipx
->sipx_network
);
192 intrfc
= rt
->ir_intrfc
;
196 ipx_offset
= intrfc
->if_ipx_offset
;
197 size
= sizeof(struct ipxhdr
) + len
+ ipx_offset
;
199 skb
= sock_alloc_send_skb(sk
, size
, noblock
, &rc
);
203 skb_reserve(skb
, ipx_offset
);
206 /* Fill in IPX header */
207 skb_reset_network_header(skb
);
208 skb_reset_transport_header(skb
);
209 skb_put(skb
, sizeof(struct ipxhdr
));
211 ipx
->ipx_pktsize
= htons(len
+ sizeof(struct ipxhdr
));
212 IPX_SKB_CB(skb
)->ipx_tctrl
= 0;
213 ipx
->ipx_type
= usipx
->sipx_type
;
215 IPX_SKB_CB(skb
)->last_hop
.index
= -1;
216 #ifdef CONFIG_IPX_INTERN
217 IPX_SKB_CB(skb
)->ipx_source_net
= ipxs
->intrfc
->if_netnum
;
218 memcpy(ipx
->ipx_source
.node
, ipxs
->node
, IPX_NODE_LEN
);
220 rc
= ntohs(ipxs
->port
);
221 if (rc
== 0x453 || rc
== 0x452) {
222 /* RIP/SAP special handling for mars_nwe */
223 IPX_SKB_CB(skb
)->ipx_source_net
= intrfc
->if_netnum
;
224 memcpy(ipx
->ipx_source
.node
, intrfc
->if_node
, IPX_NODE_LEN
);
226 IPX_SKB_CB(skb
)->ipx_source_net
= ipxs
->intrfc
->if_netnum
;
227 memcpy(ipx
->ipx_source
.node
, ipxs
->intrfc
->if_node
,
230 #endif /* CONFIG_IPX_INTERN */
231 ipx
->ipx_source
.sock
= ipxs
->port
;
232 IPX_SKB_CB(skb
)->ipx_dest_net
= usipx
->sipx_network
;
233 memcpy(ipx
->ipx_dest
.node
, usipx
->sipx_node
, IPX_NODE_LEN
);
234 ipx
->ipx_dest
.sock
= usipx
->sipx_port
;
236 rc
= memcpy_fromiovec(skb_put(skb
, len
), iov
, len
);
242 /* Apply checksum. Not allowed on 802.3 links. */
243 if (sk
->sk_no_check
|| intrfc
->if_dlink_type
== htons(IPX_FRAME_8023
))
244 ipx
->ipx_checksum
= htons(0xFFFF);
246 ipx
->ipx_checksum
= ipx_cksum(ipx
, len
+ sizeof(struct ipxhdr
));
248 rc
= ipxitf_send(intrfc
, skb
, (rt
&& rt
->ir_routed
) ?
249 rt
->ir_router_node
: ipx
->ipx_dest
.node
);
259 * We use a normal struct rtentry for route handling
261 int ipxrtr_ioctl(unsigned int cmd
, void __user
*arg
)
263 struct rtentry rt
; /* Use these to behave like 'other' stacks */
264 struct sockaddr_ipx
*sg
, *st
;
267 if (copy_from_user(&rt
, arg
, sizeof(rt
)))
270 sg
= (struct sockaddr_ipx
*)&rt
.rt_gateway
;
271 st
= (struct sockaddr_ipx
*)&rt
.rt_dst
;
274 if (!(rt
.rt_flags
& RTF_GATEWAY
) || /* Direct routes are fixed */
275 sg
->sipx_family
!= AF_IPX
||
276 st
->sipx_family
!= AF_IPX
)
281 rc
= ipxrtr_delete(st
->sipx_network
);
284 struct ipx_route_definition f
;
285 f
.ipx_network
= st
->sipx_network
;
286 f
.ipx_router_network
= sg
->sipx_network
;
287 memcpy(f
.ipx_router_node
, sg
->sipx_node
, IPX_NODE_LEN
);
288 rc
= ipxrtr_create(&f
);