|
@@ -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;
|
|
|
|
|
|
/*
|
|
@@ -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;
|