diff options
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 110 |
1 files changed, 81 insertions, 29 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 2a24b243b841..04bec047fa9a 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -29,6 +29,10 @@ | |||
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 | ||
34 | * 2005-04-15 Shaun Pereira Fast select with no restriction on | ||
35 | * response | ||
32 | */ | 36 | */ |
33 | 37 | ||
34 | #include <linux/config.h> | 38 | #include <linux/config.h> |
@@ -219,7 +223,8 @@ static void x25_insert_socket(struct sock *sk) | |||
219 | * Note: if a listening socket has cud set it must only get calls | 223 | * Note: if a listening socket has cud set it must only get calls |
220 | * with matching cud. | 224 | * with matching cud. |
221 | */ | 225 | */ |
222 | static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata) | 226 | static struct sock *x25_find_listener(struct x25_address *addr, |
227 | struct sk_buff *skb) | ||
223 | { | 228 | { |
224 | struct sock *s; | 229 | struct sock *s; |
225 | struct sock *next_best; | 230 | struct sock *next_best; |
@@ -230,22 +235,23 @@ static struct sock *x25_find_listener(struct x25_address *addr, struct x25_callu | |||
230 | 235 | ||
231 | sk_for_each(s, node, &x25_list) | 236 | sk_for_each(s, node, &x25_list) |
232 | if ((!strcmp(addr->x25_addr, | 237 | if ((!strcmp(addr->x25_addr, |
233 | x25_sk(s)->source_addr.x25_addr) || | 238 | x25_sk(s)->source_addr.x25_addr) || |
234 | !strcmp(addr->x25_addr, | 239 | !strcmp(addr->x25_addr, |
235 | null_x25_address.x25_addr)) && | 240 | null_x25_address.x25_addr)) && |
236 | s->sk_state == TCP_LISTEN) { | 241 | s->sk_state == TCP_LISTEN) { |
237 | |||
238 | /* | 242 | /* |
239 | * Found a listening socket, now check the incoming | 243 | * Found a listening socket, now check the incoming |
240 | * call user data vs this sockets call user data | 244 | * call user data vs this sockets call user data |
241 | */ | 245 | */ |
242 | if (x25_check_calluserdata(&x25_sk(s)->calluserdata, calluserdata)) { | 246 | if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) { |
243 | sock_hold(s); | 247 | if((memcmp(x25_sk(s)->calluserdata.cuddata, |
244 | goto found; | 248 | skb->data, |
245 | } | 249 | x25_sk(s)->cudmatchlength)) == 0) { |
246 | if (x25_sk(s)->calluserdata.cudlength == 0) { | 250 | sock_hold(s); |
251 | goto found; | ||
252 | } | ||
253 | } else | ||
247 | next_best = s; | 254 | next_best = s; |
248 | } | ||
249 | } | 255 | } |
250 | if (next_best) { | 256 | if (next_best) { |
251 | s = next_best; | 257 | s = next_best; |
@@ -497,6 +503,9 @@ static int x25_create(struct socket *sock, int protocol) | |||
497 | x25->t23 = sysctl_x25_clear_request_timeout; | 503 | x25->t23 = sysctl_x25_clear_request_timeout; |
498 | x25->t2 = sysctl_x25_ack_holdback_timeout; | 504 | x25->t2 = sysctl_x25_ack_holdback_timeout; |
499 | x25->state = X25_STATE_0; | 505 | x25->state = X25_STATE_0; |
506 | x25->cudmatchlength = 0; | ||
507 | x25->accptapprv = X25_DENY_ACCPT_APPRV; /* normally no cud */ | ||
508 | /* on call accept */ | ||
500 | 509 | ||
501 | x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; | 510 | x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE; |
502 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 511 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
@@ -545,6 +554,8 @@ static struct sock *x25_make_new(struct sock *osk) | |||
545 | x25->t2 = ox25->t2; | 554 | x25->t2 = ox25->t2; |
546 | x25->facilities = ox25->facilities; | 555 | x25->facilities = ox25->facilities; |
547 | x25->qbitincl = ox25->qbitincl; | 556 | x25->qbitincl = ox25->qbitincl; |
557 | x25->cudmatchlength = ox25->cudmatchlength; | ||
558 | x25->accptapprv = ox25->accptapprv; | ||
548 | 559 | ||
549 | x25_init_timers(sk); | 560 | x25_init_timers(sk); |
550 | out: | 561 | out: |
@@ -822,7 +833,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
822 | struct x25_sock *makex25; | 833 | struct x25_sock *makex25; |
823 | struct x25_address source_addr, dest_addr; | 834 | struct x25_address source_addr, dest_addr; |
824 | struct x25_facilities facilities; | 835 | struct x25_facilities facilities; |
825 | struct x25_calluserdata calluserdata; | ||
826 | int len, rc; | 836 | int len, rc; |
827 | 837 | ||
828 | /* | 838 | /* |
@@ -845,19 +855,10 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
845 | skb_pull(skb,len); | 855 | skb_pull(skb,len); |
846 | 856 | ||
847 | /* | 857 | /* |
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. | 858 | * Find a listener for the particular address/cud pair. |
859 | */ | 859 | */ |
860 | sk = x25_find_listener(&source_addr,&calluserdata); | 860 | sk = x25_find_listener(&source_addr,skb); |
861 | skb_push(skb,len); | ||
861 | 862 | ||
862 | /* | 863 | /* |
863 | * We can't accept the Call Request. | 864 | * We can't accept the Call Request. |
@@ -900,11 +901,23 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
900 | makex25->neighbour = nb; | 901 | makex25->neighbour = nb; |
901 | makex25->facilities = facilities; | 902 | makex25->facilities = facilities; |
902 | makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; | 903 | makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask; |
903 | makex25->calluserdata = calluserdata; | 904 | /* ensure no reverse facil on accept */ |
904 | 905 | makex25->vc_facil_mask &= ~X25_MASK_REVERSE; | |
905 | x25_write_internal(make, X25_CALL_ACCEPTED); | 906 | makex25->cudmatchlength = x25_sk(sk)->cudmatchlength; |
907 | |||
908 | /* Normally all calls are accepted immediatly */ | ||
909 | if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) { | ||
910 | x25_write_internal(make, X25_CALL_ACCEPTED); | ||
911 | makex25->state = X25_STATE_3; | ||
912 | } | ||
906 | 913 | ||
907 | makex25->state = X25_STATE_3; | 914 | /* |
915 | * Incoming Call User Data. | ||
916 | */ | ||
917 | if (skb->len >= 0) { | ||
918 | memcpy(makex25->calluserdata.cuddata, skb->data, skb->len); | ||
919 | makex25->calluserdata.cudlength = skb->len; | ||
920 | } | ||
908 | 921 | ||
909 | sk->sk_ack_backlog++; | 922 | sk->sk_ack_backlog++; |
910 | 923 | ||
@@ -1288,7 +1301,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1288 | if (facilities.throughput < 0x03 || | 1301 | if (facilities.throughput < 0x03 || |
1289 | facilities.throughput > 0xDD) | 1302 | facilities.throughput > 0xDD) |
1290 | break; | 1303 | break; |
1291 | if (facilities.reverse && facilities.reverse != 1) | 1304 | if (facilities.reverse && |
1305 | (facilities.reverse | 0x81)!= 0x81) | ||
1292 | break; | 1306 | break; |
1293 | x25->facilities = facilities; | 1307 | x25->facilities = facilities; |
1294 | rc = 0; | 1308 | rc = 0; |
@@ -1325,6 +1339,44 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1325 | break; | 1339 | break; |
1326 | } | 1340 | } |
1327 | 1341 | ||
1342 | case SIOCX25SCUDMATCHLEN: { | ||
1343 | struct x25_subaddr sub_addr; | ||
1344 | rc = -EINVAL; | ||
1345 | if(sk->sk_state != TCP_CLOSE) | ||
1346 | break; | ||
1347 | rc = -EFAULT; | ||
1348 | if (copy_from_user(&sub_addr, argp, | ||
1349 | sizeof(sub_addr))) | ||
1350 | break; | ||
1351 | rc = -EINVAL; | ||
1352 | if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN) | ||
1353 | break; | ||
1354 | x25->cudmatchlength = sub_addr.cudmatchlength; | ||
1355 | rc = 0; | ||
1356 | break; | ||
1357 | } | ||
1358 | |||
1359 | case SIOCX25CALLACCPTAPPRV: { | ||
1360 | rc = -EINVAL; | ||
1361 | if (sk->sk_state != TCP_CLOSE) | ||
1362 | break; | ||
1363 | x25->accptapprv = X25_ALLOW_ACCPT_APPRV; | ||
1364 | rc = 0; | ||
1365 | break; | ||
1366 | } | ||
1367 | |||
1368 | case SIOCX25SENDCALLACCPT: { | ||
1369 | rc = -EINVAL; | ||
1370 | if (sk->sk_state != TCP_ESTABLISHED) | ||
1371 | break; | ||
1372 | if (x25->accptapprv) /* must call accptapprv above */ | ||
1373 | break; | ||
1374 | x25_write_internal(sk, X25_CALL_ACCEPTED); | ||
1375 | x25->state = X25_STATE_3; | ||
1376 | rc = 0; | ||
1377 | break; | ||
1378 | } | ||
1379 | |||
1328 | default: | 1380 | default: |
1329 | rc = dev_ioctl(cmd, argp); | 1381 | rc = dev_ioctl(cmd, argp); |
1330 | break; | 1382 | break; |