diff options
-rw-r--r-- | include/linux/x25.h | 10 | ||||
-rw-r--r-- | include/net/x25.h | 3 | ||||
-rw-r--r-- | net/x25/af_x25.c | 73 | ||||
-rw-r--r-- | net/x25/x25_subr.c | 18 |
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 | */ | ||
118 | struct 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); | |||
242 | extern void x25_write_internal(struct sock *, int); | 242 | extern void x25_write_internal(struct sock *, int); |
243 | extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *); | 243 | extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *); |
244 | extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char); | 244 | extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char); |
245 | extern int x25_check_calluserdata(struct x25_calluserdata *,struct x25_calluserdata *); | ||
246 | 245 | ||
247 | /* x25_timer.c */ | 246 | /* x25_timer.c */ |
248 | extern void x25_start_heartbeat(struct sock *); | 247 | extern 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 | */ |
222 | static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata) | 224 | static 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); |
550 | out: | 556 | out: |
@@ -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 | */ | ||
361 | int 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 | |||