diff options
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 73 |
1 files changed, 48 insertions, 25 deletions
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; |