]> err.no Git - linux-2.6/blobdiff - net/x25/af_x25.c
[PATCH] Clean up struct flock definitions
[linux-2.6] / net / x25 / af_x25.c
index 2a24b243b841aaae6e734c102aaae25f4cae762f..020d73cc8414916f6a0bf65b2fbe675ec5759ead 100644 (file)
  *     2000-11-14      Henner Eisen    Closing datalink from NETDEV_GOING_DOWN
  *     2002-10-06      Arnaldo C. Melo Get rid of cli/sti, move proc stuff to
  *                                     x25_proc.c, using seq_file
+ *     2005-04-02      Shaun Pereira   Selective sub address matching
+ *                                     with call user data
+ *     2005-04-15      Shaun Pereira   Fast select with no restriction on
+ *                                     response
  */
 
 #include <linux/config.h>
@@ -43,7 +47,7 @@
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
 #include <asm/uaccess.h>
 #include <linux/fcntl.h>
 #include <linux/termios.h>     /* For TIOCINQ/OUTQ */
@@ -219,7 +223,8 @@ static void x25_insert_socket(struct sock *sk)
  *     Note: if a listening socket has cud set it must only get calls
  *     with matching cud.
  */
-static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata)
+static struct sock *x25_find_listener(struct x25_address *addr,
+                                       struct sk_buff *skb)
 {
        struct sock *s;
        struct sock *next_best;
@@ -230,22 +235,23 @@ static struct sock *x25_find_listener(struct x25_address *addr, struct x25_callu
 
        sk_for_each(s, node, &x25_list)
                if ((!strcmp(addr->x25_addr,
-                            x25_sk(s)->source_addr.x25_addr) ||
-                    !strcmp(addr->x25_addr,
-                            null_x25_address.x25_addr)) &&
-                    s->sk_state == TCP_LISTEN) {
-
+                       x25_sk(s)->source_addr.x25_addr) ||
+                               !strcmp(addr->x25_addr,
+                                       null_x25_address.x25_addr)) &&
+                                       s->sk_state == TCP_LISTEN) {
                        /*
                         * Found a listening socket, now check the incoming
                         * call user data vs this sockets call user data
                         */
-                       if (x25_check_calluserdata(&x25_sk(s)->calluserdata, calluserdata)) {
-                               sock_hold(s);
-                               goto found;
-                       }
-                       if (x25_sk(s)->calluserdata.cudlength == 0) {
+                       if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) {
+                               if((memcmp(x25_sk(s)->calluserdata.cuddata,
+                                       skb->data,
+                                       x25_sk(s)->cudmatchlength)) == 0) {
+                                       sock_hold(s);
+                                       goto found;
+                                }
+                       } else
                                next_best = s;
-                       }
                }
        if (next_best) {
                s = next_best;
@@ -497,6 +503,9 @@ static int x25_create(struct socket *sock, int protocol)
        x25->t23   = sysctl_x25_clear_request_timeout;
        x25->t2    = sysctl_x25_ack_holdback_timeout;
        x25->state = X25_STATE_0;
+       x25->cudmatchlength = 0;
+       x25->accptapprv = X25_DENY_ACCPT_APPRV;         /* normally no cud  */
+                                                       /* on call accept   */
 
        x25->facilities.winsize_in  = X25_DEFAULT_WINDOW_SIZE;
        x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
@@ -545,6 +554,8 @@ static struct sock *x25_make_new(struct sock *osk)
        x25->t2         = ox25->t2;
        x25->facilities = ox25->facilities;
        x25->qbitincl   = ox25->qbitincl;
+       x25->cudmatchlength = ox25->cudmatchlength;
+       x25->accptapprv = ox25->accptapprv;
 
        x25_init_timers(sk);
 out:
@@ -822,7 +833,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        struct x25_sock *makex25;
        struct x25_address source_addr, dest_addr;
        struct x25_facilities facilities;
-       struct x25_calluserdata calluserdata;
        int len, rc;
 
        /*
@@ -844,20 +854,11 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        len = skb->data[0] + 1;
        skb_pull(skb,len);
 
-       /*
-        *      Incoming Call User Data.
-        */
-       if (skb->len >= 0) {
-               memcpy(calluserdata.cuddata, skb->data, skb->len);
-               calluserdata.cudlength = skb->len;
-       }
-
-       skb_push(skb,len);
-
        /*
         *      Find a listener for the particular address/cud pair.
         */
-       sk = x25_find_listener(&source_addr,&calluserdata);
+       sk = x25_find_listener(&source_addr,skb);
+       skb_push(skb,len);
 
        /*
         *      We can't accept the Call Request.
@@ -900,11 +901,23 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        makex25->neighbour     = nb;
        makex25->facilities    = facilities;
        makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
-       makex25->calluserdata  = calluserdata;
-
-       x25_write_internal(make, X25_CALL_ACCEPTED);
+       /* ensure no reverse facil on accept */
+       makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
+       makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
+
+       /* Normally all calls are accepted immediatly */
+       if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) {
+               x25_write_internal(make, X25_CALL_ACCEPTED);
+               makex25->state = X25_STATE_3;
+       }
 
-       makex25->state = X25_STATE_3;
+       /*
+        *      Incoming Call User Data.
+        */
+       if (skb->len >= 0) {
+               memcpy(makex25->calluserdata.cuddata, skb->data, skb->len);
+               makex25->calluserdata.cudlength = skb->len;
+       }
 
        sk->sk_ack_backlog++;
 
@@ -1288,7 +1301,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        if (facilities.throughput < 0x03 ||
                            facilities.throughput > 0xDD)
                                break;
-                       if (facilities.reverse && facilities.reverse != 1)
+                       if (facilities.reverse &&
+                               (facilities.reverse | 0x81)!= 0x81)
                                break;
                        x25->facilities = facilities;
                        rc = 0;
@@ -1325,6 +1339,44 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        break;
                }
 
+               case SIOCX25SCUDMATCHLEN: {
+                       struct x25_subaddr sub_addr;
+                       rc = -EINVAL;
+                       if(sk->sk_state != TCP_CLOSE)
+                               break;
+                       rc = -EFAULT;
+                       if (copy_from_user(&sub_addr, argp,
+                                       sizeof(sub_addr)))
+                               break;
+                       rc = -EINVAL;
+                       if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
+                               break;
+                       x25->cudmatchlength = sub_addr.cudmatchlength;
+                       rc = 0;
+                       break;
+               }
+
+               case SIOCX25CALLACCPTAPPRV: {
+                       rc = -EINVAL;
+                       if (sk->sk_state != TCP_CLOSE)
+                               break;
+                       x25->accptapprv = X25_ALLOW_ACCPT_APPRV;
+                       rc = 0;
+                       break;
+               }
+
+               case SIOCX25SENDCALLACCPT:  {
+                       rc = -EINVAL;
+                       if (sk->sk_state != TCP_ESTABLISHED)
+                               break;
+                       if (x25->accptapprv)    /* must call accptapprv above */
+                               break;
+                       x25_write_internal(sk, X25_CALL_ACCEPTED);
+                       x25->state = X25_STATE_3;
+                       rc = 0;
+                       break;
+               }
+
                default:
                        rc = dev_ioctl(cmd, argp);
                        break;