diff options
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index b5c80b189902..0872025821c5 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -846,7 +846,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
846 | struct x25_address source_addr, dest_addr; | 846 | struct x25_address source_addr, dest_addr; |
847 | struct x25_facilities facilities; | 847 | struct x25_facilities facilities; |
848 | struct x25_dte_facilities dte_facilities; | 848 | struct x25_dte_facilities dte_facilities; |
849 | int len, rc; | 849 | int len, addr_len, rc; |
850 | 850 | ||
851 | /* | 851 | /* |
852 | * Remove the LCI and frame type. | 852 | * Remove the LCI and frame type. |
@@ -857,7 +857,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
857 | * Extract the X.25 addresses and convert them to ASCII strings, | 857 | * Extract the X.25 addresses and convert them to ASCII strings, |
858 | * and remove them. | 858 | * and remove them. |
859 | */ | 859 | */ |
860 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 860 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); |
861 | skb_pull(skb, addr_len); | ||
861 | 862 | ||
862 | /* | 863 | /* |
863 | * Get the length of the facilities, skip past them for the moment | 864 | * Get the length of the facilities, skip past them for the moment |
@@ -873,11 +874,27 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
873 | sk = x25_find_listener(&source_addr,skb); | 874 | sk = x25_find_listener(&source_addr,skb); |
874 | skb_push(skb,len); | 875 | skb_push(skb,len); |
875 | 876 | ||
877 | if (sk != NULL && sk_acceptq_is_full(sk)) { | ||
878 | goto out_sock_put; | ||
879 | } | ||
880 | |||
876 | /* | 881 | /* |
877 | * We can't accept the Call Request. | 882 | * We dont have any listeners for this incoming call. |
883 | * Try forwarding it. | ||
878 | */ | 884 | */ |
879 | if (sk == NULL || sk_acceptq_is_full(sk)) | 885 | if (sk == NULL) { |
880 | goto out_clear_request; | 886 | skb_push(skb, addr_len + X25_STD_MIN_LEN); |
887 | if (x25_forward_call(&dest_addr, nb, skb, lci) > 0) | ||
888 | { | ||
889 | /* Call was forwarded, dont process it any more */ | ||
890 | kfree_skb(skb); | ||
891 | rc = 1; | ||
892 | goto out; | ||
893 | } else { | ||
894 | /* No listeners, can't forward, clear the call */ | ||
895 | goto out_clear_request; | ||
896 | } | ||
897 | } | ||
881 | 898 | ||
882 | /* | 899 | /* |
883 | * Try to reach a compromise on the requested facilities. | 900 | * Try to reach a compromise on the requested facilities. |
@@ -1598,6 +1615,9 @@ void x25_kill_by_neigh(struct x25_neigh *nb) | |||
1598 | x25_disconnect(s, ENETUNREACH, 0, 0); | 1615 | x25_disconnect(s, ENETUNREACH, 0, 0); |
1599 | 1616 | ||
1600 | write_unlock_bh(&x25_list_lock); | 1617 | write_unlock_bh(&x25_list_lock); |
1618 | |||
1619 | /* Remove any related forwards */ | ||
1620 | x25_clear_forward_by_dev(nb->dev); | ||
1601 | } | 1621 | } |
1602 | 1622 | ||
1603 | static int __init x25_init(void) | 1623 | static int __init x25_init(void) |