]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/x25/af_x25.c
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-tc
[mv-sheeva.git] / net / x25 / af_x25.c
index 52a2726d327fe68f6c7ea003894902b204f25e99..b37d894358ec28fb68e83d387a79b486024e40a2 100644 (file)
@@ -63,6 +63,7 @@ int sysctl_x25_call_request_timeout    = X25_DEFAULT_T21;
 int sysctl_x25_reset_request_timeout   = X25_DEFAULT_T22;
 int sysctl_x25_clear_request_timeout   = X25_DEFAULT_T23;
 int sysctl_x25_ack_holdback_timeout    = X25_DEFAULT_T2;
+int sysctl_x25_forward                 = 0;
 
 HLIST_HEAD(x25_list);
 DEFINE_RWLOCK(x25_list_lock);
@@ -484,8 +485,6 @@ out:
        return sk;
 }
 
-void x25_init_timers(struct sock *sk);
-
 static int x25_create(struct socket *sock, int protocol)
 {
        struct sock *sk;
@@ -848,7 +847,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        struct x25_address source_addr, dest_addr;
        struct x25_facilities facilities;
        struct x25_dte_facilities dte_facilities;
-       int len, rc;
+       int len, addr_len, rc;
 
        /*
         *      Remove the LCI and frame type.
@@ -859,7 +858,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
         *      Extract the X.25 addresses and convert them to ASCII strings,
         *      and remove them.
         */
-       skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
+       addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr);
+       skb_pull(skb, addr_len);
 
        /*
         *      Get the length of the facilities, skip past them for the moment
@@ -875,11 +875,28 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        sk = x25_find_listener(&source_addr,skb);
        skb_push(skb,len);
 
+       if (sk != NULL && sk_acceptq_is_full(sk)) {
+               goto out_sock_put;
+       }
+
        /*
-        *      We can't accept the Call Request.
+        *      We dont have any listeners for this incoming call.
+        *      Try forwarding it.
         */
-       if (sk == NULL || sk_acceptq_is_full(sk))
-               goto out_clear_request;
+       if (sk == NULL) {
+               skb_push(skb, addr_len + X25_STD_MIN_LEN);
+               if (sysctl_x25_forward &&
+                               x25_forward_call(&dest_addr, nb, skb, lci) > 0)
+               {
+                       /* Call was forwarded, dont process it any more */
+                       kfree_skb(skb);
+                       rc = 1;
+                       goto out;
+               } else {
+                       /* No listeners, can't forward, clear the call */
+                       goto out_clear_request;
+               }
+       }
 
        /*
         *      Try to reach a compromise on the requested facilities.
@@ -1600,6 +1617,9 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
                        x25_disconnect(s, ENETUNREACH, 0, 0);
 
        write_unlock_bh(&x25_list_lock);
+
+       /* Remove any related forwards */
+       x25_clear_forward_by_dev(nb->dev);
 }
 
 static int __init x25_init(void)