diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/x25/x25_forward.c | 88 |
1 files changed, 45 insertions, 43 deletions
diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index d339e0c810a8..8738ec7ce693 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c | |||
@@ -26,64 +26,66 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
26 | short same_lci = 0; | 26 | short same_lci = 0; |
27 | int rc = 0; | 27 | int rc = 0; |
28 | 28 | ||
29 | if ((rt = x25_get_route(dest_addr)) != NULL) { | 29 | if ((rt = x25_get_route(dest_addr)) == NULL) |
30 | goto out_no_route; | ||
30 | 31 | ||
31 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { | 32 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { |
32 | /* This shouldnt happen, if it occurs somehow | 33 | /* This shouldnt happen, if it occurs somehow |
33 | * do something sensible | 34 | * do something sensible |
34 | */ | ||
35 | goto out_put_route; | ||
36 | } | ||
37 | |||
38 | /* Avoid a loop. This is the normal exit path for a | ||
39 | * system with only one x.25 iface and default route | ||
40 | */ | 35 | */ |
41 | if (rt->dev == from->dev) { | 36 | goto out_put_route; |
42 | goto out_put_nb; | 37 | } |
43 | } | ||
44 | 38 | ||
45 | /* Remote end sending a call request on an already | 39 | /* Avoid a loop. This is the normal exit path for a |
46 | * established LCI? It shouldnt happen, just in case.. | 40 | * system with only one x.25 iface and default route |
47 | */ | 41 | */ |
48 | read_lock_bh(&x25_forward_list_lock); | 42 | if (rt->dev == from->dev) { |
49 | list_for_each(entry, &x25_forward_list) { | 43 | goto out_put_nb; |
50 | x25_frwd = list_entry(entry, struct x25_forward, node); | 44 | } |
51 | if (x25_frwd->lci == lci) { | 45 | |
52 | printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n"); | 46 | /* Remote end sending a call request on an already |
53 | same_lci = 1; | 47 | * established LCI? It shouldnt happen, just in case.. |
54 | } | 48 | */ |
55 | } | 49 | read_lock_bh(&x25_forward_list_lock); |
56 | read_unlock_bh(&x25_forward_list_lock); | 50 | list_for_each(entry, &x25_forward_list) { |
57 | 51 | x25_frwd = list_entry(entry, struct x25_forward, node); | |
58 | /* Save the forwarding details for future traffic */ | 52 | if (x25_frwd->lci == lci) { |
59 | if (!same_lci){ | 53 | printk(KERN_WARNING "X.25: call request for lci which is already registered!, transmitting but not registering new pair\n"); |
60 | if ((new_frwd = kmalloc(sizeof(struct x25_forward), | 54 | same_lci = 1; |
61 | GFP_ATOMIC)) == NULL){ | ||
62 | rc = -ENOMEM; | ||
63 | goto out_put_nb; | ||
64 | } | ||
65 | new_frwd->lci = lci; | ||
66 | new_frwd->dev1 = rt->dev; | ||
67 | new_frwd->dev2 = from->dev; | ||
68 | write_lock_bh(&x25_forward_list_lock); | ||
69 | list_add(&new_frwd->node, &x25_forward_list); | ||
70 | write_unlock_bh(&x25_forward_list_lock); | ||
71 | } | 55 | } |
56 | } | ||
57 | read_unlock_bh(&x25_forward_list_lock); | ||
72 | 58 | ||
73 | /* Forward the call request */ | 59 | /* Save the forwarding details for future traffic */ |
74 | if ( (skbn = skb_clone(skb, GFP_ATOMIC)) == NULL){ | 60 | if (!same_lci){ |
61 | if ((new_frwd = kmalloc(sizeof(struct x25_forward), | ||
62 | GFP_ATOMIC)) == NULL){ | ||
63 | rc = -ENOMEM; | ||
75 | goto out_put_nb; | 64 | goto out_put_nb; |
76 | } | 65 | } |
77 | x25_transmit_link(skbn, neigh_new); | 66 | new_frwd->lci = lci; |
78 | rc = 1; | 67 | new_frwd->dev1 = rt->dev; |
68 | new_frwd->dev2 = from->dev; | ||
69 | write_lock_bh(&x25_forward_list_lock); | ||
70 | list_add(&new_frwd->node, &x25_forward_list); | ||
71 | write_unlock_bh(&x25_forward_list_lock); | ||
79 | } | 72 | } |
80 | 73 | ||
74 | /* Forward the call request */ | ||
75 | if ( (skbn = skb_clone(skb, GFP_ATOMIC)) == NULL){ | ||
76 | goto out_put_nb; | ||
77 | } | ||
78 | x25_transmit_link(skbn, neigh_new); | ||
79 | rc = 1; | ||
80 | |||
81 | 81 | ||
82 | out_put_nb: | 82 | out_put_nb: |
83 | x25_neigh_put(neigh_new); | 83 | x25_neigh_put(neigh_new); |
84 | 84 | ||
85 | out_put_route: | 85 | out_put_route: |
86 | x25_route_put(rt); | 86 | x25_route_put(rt); |
87 | |||
88 | out_no_route: | ||
87 | return rc; | 89 | return rc; |
88 | } | 90 | } |
89 | 91 | ||