aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/x25.h10
-rw-r--r--include/net/x25.h3
-rw-r--r--net/x25/af_x25.c73
-rw-r--r--net/x25/x25_subr.c18
4 files changed, 59 insertions, 45 deletions
diff --git a/include/linux/x25.h b/include/linux/x25.h
index 7531cfed5885..6f43b3d20248 100644
--- a/include/linux/x25.h
+++ b/include/linux/x25.h
@@ -4,6 +4,8 @@
4 * History 4 * History
5 * mar/20/00 Daniela Squassoni Disabling/enabling of facilities 5 * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
6 * negotiation. 6 * negotiation.
7 * apr/02/05 Shaun Pereira Selective sub address matching with
8 * call user data
7 */ 9 */
8 10
9#ifndef X25_KERNEL_H 11#ifndef X25_KERNEL_H
@@ -16,6 +18,7 @@
16#define SIOCX25GCALLUSERDATA (SIOCPROTOPRIVATE + 4) 18#define SIOCX25GCALLUSERDATA (SIOCPROTOPRIVATE + 4)
17#define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5) 19#define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5)
18#define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6) 20#define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6)
21#define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7)
19 22
20/* 23/*
21 * Values for {get,set}sockopt. 24 * Values for {get,set}sockopt.
@@ -109,4 +112,11 @@ struct x25_causediag {
109 unsigned char diagnostic; 112 unsigned char diagnostic;
110}; 113};
111 114
115/*
116 * Further optional call user data match length selection
117 */
118struct x25_subaddr {
119 unsigned int cudmatchlength;
120};
121
112#endif 122#endif
diff --git a/include/net/x25.h b/include/net/x25.h
index 7a1ba5bbb868..9dd70dd4a9b7 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -134,7 +134,7 @@ struct x25_sock {
134 struct sock sk; 134 struct sock sk;
135 struct x25_address source_addr, dest_addr; 135 struct x25_address source_addr, dest_addr;
136 struct x25_neigh *neighbour; 136 struct x25_neigh *neighbour;
137 unsigned int lci; 137 unsigned int lci, cudmatchlength;
138 unsigned char state, condition, qbitincl, intflag; 138 unsigned char state, condition, qbitincl, intflag;
139 unsigned short vs, vr, va, vl; 139 unsigned short vs, vr, va, vl;
140 unsigned long t2, t21, t22, t23; 140 unsigned long t2, t21, t22, t23;
@@ -242,7 +242,6 @@ extern int x25_validate_nr(struct sock *, unsigned short);
242extern void x25_write_internal(struct sock *, int); 242extern void x25_write_internal(struct sock *, int);
243extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *); 243extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
244extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char); 244extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
245extern int x25_check_calluserdata(struct x25_calluserdata *,struct x25_calluserdata *);
246 245
247/* x25_timer.c */ 246/* x25_timer.c */
248extern void x25_start_heartbeat(struct sock *); 247extern void x25_start_heartbeat(struct sock *);
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 2a24b243b841..e17d84a55d5e 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -29,6 +29,8 @@
29 * 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN 29 * 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN
30 * 2002-10-06 Arnaldo C. Melo Get rid of cli/sti, move proc stuff to 30 * 2002-10-06 Arnaldo C. Melo Get rid of cli/sti, move proc stuff to
31 * x25_proc.c, using seq_file 31 * x25_proc.c, using seq_file
32 * 2005-04-02 Shaun Pereira Selective sub address matching
33 * with call user data
32 */ 34 */
33 35
34#include <linux/config.h> 36#include <linux/config.h>
@@ -219,7 +221,8 @@ static void x25_insert_socket(struct sock *sk)
219 * Note: if a listening socket has cud set it must only get calls 221 * Note: if a listening socket has cud set it must only get calls
220 * with matching cud. 222 * with matching cud.
221 */ 223 */
222static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata) 224static struct sock *x25_find_listener(struct x25_address *addr,
225 struct sk_buff *skb)
223{ 226{
224 struct sock *s; 227 struct sock *s;
225 struct sock *next_best; 228 struct sock *next_best;
@@ -230,22 +233,23 @@ static struct sock *x25_find_listener(struct x25_address *addr, struct x25_callu
230 233
231 sk_for_each(s, node, &x25_list) 234 sk_for_each(s, node, &x25_list)
232 if ((!strcmp(addr->x25_addr, 235 if ((!strcmp(addr->x25_addr,
233 x25_sk(s)->source_addr.x25_addr) || 236 x25_sk(s)->source_addr.x25_addr) ||
234 !strcmp(addr->x25_addr, 237 !strcmp(addr->x25_addr,
235 null_x25_address.x25_addr)) && 238 null_x25_address.x25_addr)) &&
236 s->sk_state == TCP_LISTEN) { 239 s->sk_state == TCP_LISTEN) {
237
238 /* 240 /*
239 * Found a listening socket, now check the incoming 241 * Found a listening socket, now check the incoming
240 * call user data vs this sockets call user data 242 * call user data vs this sockets call user data
241 */ 243 */
242 if (x25_check_calluserdata(&x25_sk(s)->calluserdata, calluserdata)) { 244 if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) {
243 sock_hold(s); 245 if((memcmp(x25_sk(s)->calluserdata.cuddata,
244 goto found; 246 skb->data,
245 } 247 x25_sk(s)->cudmatchlength)) == 0) {
246 if (x25_sk(s)->calluserdata.cudlength == 0) { 248 sock_hold(s);
249 goto found;
250 }
251 } else
247 next_best = s; 252 next_best = s;
248 }
249 } 253 }
250 if (next_best) { 254 if (next_best) {
251 s = next_best; 255 s = next_best;
@@ -497,6 +501,7 @@ static int x25_create(struct socket *sock, int protocol)
497 x25->t23 = sysctl_x25_clear_request_timeout; 501 x25->t23 = sysctl_x25_clear_request_timeout;
498 x25->t2 = sysctl_x25_ack_holdback_timeout; 502 x25->t2 = sysctl_x25_ack_holdback_timeout;
499 x25->state = X25_STATE_0; 503 x25->state = X25_STATE_0;
504 x25->cudmatchlength = 0;
500 505
501 x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; 506 x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE;
502 x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; 507 x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
@@ -545,6 +550,7 @@ static struct sock *x25_make_new(struct sock *osk)
545 x25->t2 = ox25->t2; 550 x25->t2 = ox25->t2;
546 x25->facilities = ox25->facilities; 551 x25->facilities = ox25->facilities;
547 x25->qbitincl = ox25->qbitincl; 552 x25->qbitincl = ox25->qbitincl;
553 x25->cudmatchlength = ox25->cudmatchlength;
548 554
549 x25_init_timers(sk); 555 x25_init_timers(sk);
550out: 556out:
@@ -822,7 +828,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
822 struct x25_sock *makex25; 828 struct x25_sock *makex25;
823 struct x25_address source_addr, dest_addr; 829 struct x25_address source_addr, dest_addr;
824 struct x25_facilities facilities; 830 struct x25_facilities facilities;
825 struct x25_calluserdata calluserdata;
826 int len, rc; 831 int len, rc;
827 832
828 /* 833 /*
@@ -845,19 +850,10 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
845 skb_pull(skb,len); 850 skb_pull(skb,len);
846 851
847 /* 852 /*
848 * Incoming Call User Data.
849 */
850 if (skb->len >= 0) {
851 memcpy(calluserdata.cuddata, skb->data, skb->len);
852 calluserdata.cudlength = skb->len;
853 }
854
855 skb_push(skb,len);
856
857 /*
858 * Find a listener for the particular address/cud pair. 853 * Find a listener for the particular address/cud pair.
859 */ 854 */
860 sk = x25_find_listener(&source_addr,&calluserdata); 855 sk = x25_find_listener(&source_addr,skb);
856 skb_push(skb,len);
861 857
862 /* 858 /*
863 * We can't accept the Call Request. 859 * We can't accept the Call Request.
@@ -900,12 +896,22 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
900 makex25->neighbour = nb; 896 makex25->neighbour = nb;
901 makex25->facilities = facilities; 897 makex25->facilities = facilities;
902 makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; 898 makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
903 makex25->calluserdata = calluserdata; 899 /* ensure no reverse facil on accept */
900 makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
901 makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
904 902
905 x25_write_internal(make, X25_CALL_ACCEPTED); 903 x25_write_internal(make, X25_CALL_ACCEPTED);
906 904
907 makex25->state = X25_STATE_3; 905 makex25->state = X25_STATE_3;
908 906
907 /*
908 * Incoming Call User Data.
909 */
910 if (skb->len >= 0) {
911 memcpy(makex25->calluserdata.cuddata, skb->data, skb->len);
912 makex25->calluserdata.cudlength = skb->len;
913 }
914
909 sk->sk_ack_backlog++; 915 sk->sk_ack_backlog++;
910 916
911 x25_insert_socket(make); 917 x25_insert_socket(make);
@@ -1325,6 +1331,23 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1325 break; 1331 break;
1326 } 1332 }
1327 1333
1334 case SIOCX25SCUDMATCHLEN: {
1335 struct x25_subaddr sub_addr;
1336 rc = -EINVAL;
1337 if(sk->sk_state != TCP_CLOSE)
1338 break;
1339 rc = -EFAULT;
1340 if (copy_from_user(&sub_addr, argp,
1341 sizeof(sub_addr)))
1342 break;
1343 rc = -EINVAL;
1344 if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
1345 break;
1346 x25->cudmatchlength = sub_addr.cudmatchlength;
1347 rc = 0;
1348 break;
1349 }
1350
1328 default: 1351 default:
1329 rc = dev_ioctl(cmd, argp); 1352 rc = dev_ioctl(cmd, argp);
1330 break; 1353 break;
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 183fea3bba67..c349bbd61684 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -354,21 +354,3 @@ void x25_check_rbuf(struct sock *sk)
354 } 354 }
355} 355}
356 356
357/*
358 * Compare 2 calluserdata structures, used to find correct listening sockets
359 * when call user data is used.
360 */
361int x25_check_calluserdata(struct x25_calluserdata *ours, struct x25_calluserdata *theirs)
362{
363 int i;
364 if (ours->cudlength != theirs->cudlength)
365 return 0;
366
367 for (i=0;i<ours->cudlength;i++) {
368 if (ours->cuddata[i] != theirs->cuddata[i]) {
369 return 0;
370 }
371 }
372 return 1;
373}
374