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 | |||
