aboutsummaryrefslogtreecommitdiff
path: root/net/x25/af_x25.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r--net/x25/af_x25.c110
1 files changed, 81 insertions, 29 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 2a24b243b84..04bec047fa9 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -29,6 +29,10 @@
* 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>
@@ -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;
/*
@@ -845,19 +855,10 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
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;