diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-13 01:43:25 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-13 01:43:25 -0500 |
commit | d9bc125caf592b7d081021f32ce5b717efdf70c8 (patch) | |
tree | 263b7066ba22ddce21db610c0300f6eaac6f2064 /net/x25/af_x25.c | |
parent | 43d78ef2ba5bec26d0315859e8324bfc0be23766 (diff) | |
parent | ec2f9d1331f658433411c58077871e1eef4ee1b4 (diff) |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts:
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_spkm3_token.c
net/sunrpc/clnt.c
Merge with mainline and fix conflicts.
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r-- | net/x25/af_x25.c | 96 |
1 files changed, 59 insertions, 37 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index b5c80b189902..e62ba41b05c5 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * This is ALPHA test software. This code may break your machine, | 4 | * This is ALPHA test software. This code may break your machine, |
5 | * randomly fail to work with new releases, misbehave and/or generally | 5 | * randomly fail to work with new releases, misbehave and/or generally |
6 | * screw up. It might even work. | 6 | * screw up. It might even work. |
7 | * | 7 | * |
8 | * This code REQUIRES 2.1.15 or higher | 8 | * This code REQUIRES 2.1.15 or higher |
9 | * | 9 | * |
@@ -18,11 +18,11 @@ | |||
18 | * X.25 002 Jonathan Naylor Centralised disconnect handling. | 18 | * X.25 002 Jonathan Naylor Centralised disconnect handling. |
19 | * New timer architecture. | 19 | * New timer architecture. |
20 | * 2000-03-11 Henner Eisen MSG_EOR handling more POSIX compliant. | 20 | * 2000-03-11 Henner Eisen MSG_EOR handling more POSIX compliant. |
21 | * 2000-03-22 Daniela Squassoni Allowed disabling/enabling of | 21 | * 2000-03-22 Daniela Squassoni Allowed disabling/enabling of |
22 | * facilities negotiation and increased | 22 | * facilities negotiation and increased |
23 | * the throughput upper limit. | 23 | * the throughput upper limit. |
24 | * 2000-08-27 Arnaldo C. Melo s/suser/capable/ + micro cleanups | 24 | * 2000-08-27 Arnaldo C. Melo s/suser/capable/ + micro cleanups |
25 | * 2000-09-04 Henner Eisen Set sock->state in x25_accept(). | 25 | * 2000-09-04 Henner Eisen Set sock->state in x25_accept(). |
26 | * Fixed x25_output() related skb leakage. | 26 | * Fixed x25_output() related skb leakage. |
27 | * 2000-10-02 Henner Eisen Made x25_kick() single threaded per socket. | 27 | * 2000-10-02 Henner Eisen Made x25_kick() single threaded per socket. |
28 | * 2000-10-27 Henner Eisen MSG_DONTWAIT for fragment allocation. | 28 | * 2000-10-27 Henner Eisen MSG_DONTWAIT for fragment allocation. |
@@ -63,6 +63,7 @@ int sysctl_x25_call_request_timeout = X25_DEFAULT_T21; | |||
63 | int sysctl_x25_reset_request_timeout = X25_DEFAULT_T22; | 63 | int sysctl_x25_reset_request_timeout = X25_DEFAULT_T22; |
64 | int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23; | 64 | int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23; |
65 | int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2; | 65 | int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2; |
66 | int sysctl_x25_forward = 0; | ||
66 | 67 | ||
67 | HLIST_HEAD(x25_list); | 68 | HLIST_HEAD(x25_list); |
68 | DEFINE_RWLOCK(x25_list_lock); | 69 | DEFINE_RWLOCK(x25_list_lock); |
@@ -255,8 +256,8 @@ static struct sock *x25_find_listener(struct x25_address *addr, | |||
255 | * call user data vs this sockets call user data | 256 | * call user data vs this sockets call user data |
256 | */ | 257 | */ |
257 | if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) { | 258 | if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) { |
258 | if((memcmp(x25_sk(s)->calluserdata.cuddata, | 259 | if((memcmp(x25_sk(s)->calluserdata.cuddata, |
259 | skb->data, | 260 | skb->data, |
260 | x25_sk(s)->cudmatchlength)) == 0) { | 261 | x25_sk(s)->cudmatchlength)) == 0) { |
261 | sock_hold(s); | 262 | sock_hold(s); |
262 | goto found; | 263 | goto found; |
@@ -420,7 +421,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
420 | { | 421 | { |
421 | struct sock *sk = sock->sk; | 422 | struct sock *sk = sock->sk; |
422 | int val, len, rc = -ENOPROTOOPT; | 423 | int val, len, rc = -ENOPROTOOPT; |
423 | 424 | ||
424 | if (level != SOL_X25 || optname != X25_QBITINCL) | 425 | if (level != SOL_X25 || optname != X25_QBITINCL) |
425 | goto out; | 426 | goto out; |
426 | 427 | ||
@@ -433,7 +434,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
433 | rc = -EINVAL; | 434 | rc = -EINVAL; |
434 | if (len < 0) | 435 | if (len < 0) |
435 | goto out; | 436 | goto out; |
436 | 437 | ||
437 | rc = -EFAULT; | 438 | rc = -EFAULT; |
438 | if (put_user(len, optlen)) | 439 | if (put_user(len, optlen)) |
439 | goto out; | 440 | goto out; |
@@ -522,12 +523,12 @@ static int x25_create(struct socket *sock, int protocol) | |||
522 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 523 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
523 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 524 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; |
524 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 525 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
525 | x25->dte_facilities.calling_len = 0; | 526 | x25->dte_facilities.calling_len = 0; |
526 | x25->dte_facilities.called_len = 0; | 527 | x25->dte_facilities.called_len = 0; |
527 | memset(x25->dte_facilities.called_ae, '\0', | 528 | memset(x25->dte_facilities.called_ae, '\0', |
528 | sizeof(x25->dte_facilities.called_ae)); | 529 | sizeof(x25->dte_facilities.called_ae)); |
529 | memset(x25->dte_facilities.calling_ae, '\0', | 530 | memset(x25->dte_facilities.calling_ae, '\0', |
530 | sizeof(x25->dte_facilities.calling_ae)); | 531 | sizeof(x25->dte_facilities.calling_ae)); |
531 | 532 | ||
532 | rc = 0; | 533 | rc = 0; |
533 | out: | 534 | out: |
@@ -607,7 +608,7 @@ static int x25_release(struct socket *sock) | |||
607 | break; | 608 | break; |
608 | } | 609 | } |
609 | 610 | ||
610 | sock->sk = NULL; | 611 | sock->sk = NULL; |
611 | sk->sk_socket = NULL; /* Not used, but we should do this */ | 612 | sk->sk_socket = NULL; /* Not used, but we should do this */ |
612 | out: | 613 | out: |
613 | return 0; | 614 | return 0; |
@@ -634,7 +635,7 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
634 | static int x25_wait_for_connection_establishment(struct sock *sk) | 635 | static int x25_wait_for_connection_establishment(struct sock *sk) |
635 | { | 636 | { |
636 | DECLARE_WAITQUEUE(wait, current); | 637 | DECLARE_WAITQUEUE(wait, current); |
637 | int rc; | 638 | int rc; |
638 | 639 | ||
639 | add_wait_queue_exclusive(sk->sk_sleep, &wait); | 640 | add_wait_queue_exclusive(sk->sk_sleep, &wait); |
640 | for (;;) { | 641 | for (;;) { |
@@ -685,7 +686,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, | |||
685 | if (sk->sk_state == TCP_ESTABLISHED) | 686 | if (sk->sk_state == TCP_ESTABLISHED) |
686 | goto out; | 687 | goto out; |
687 | 688 | ||
688 | sk->sk_state = TCP_CLOSE; | 689 | sk->sk_state = TCP_CLOSE; |
689 | sock->state = SS_UNCONNECTED; | 690 | sock->state = SS_UNCONNECTED; |
690 | 691 | ||
691 | rc = -EINVAL; | 692 | rc = -EINVAL; |
@@ -777,7 +778,7 @@ static int x25_wait_for_data(struct sock *sk, long timeout) | |||
777 | remove_wait_queue(sk->sk_sleep, &wait); | 778 | remove_wait_queue(sk->sk_sleep, &wait); |
778 | return rc; | 779 | return rc; |
779 | } | 780 | } |
780 | 781 | ||
781 | static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | 782 | static int x25_accept(struct socket *sock, struct socket *newsock, int flags) |
782 | { | 783 | { |
783 | struct sock *sk = sock->sk; | 784 | struct sock *sk = sock->sk; |
@@ -836,7 +837,7 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
836 | 837 | ||
837 | return 0; | 838 | return 0; |
838 | } | 839 | } |
839 | 840 | ||
840 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | 841 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, |
841 | unsigned int lci) | 842 | unsigned int lci) |
842 | { | 843 | { |
@@ -846,7 +847,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
846 | struct x25_address source_addr, dest_addr; | 847 | struct x25_address source_addr, dest_addr; |
847 | struct x25_facilities facilities; | 848 | struct x25_facilities facilities; |
848 | struct x25_dte_facilities dte_facilities; | 849 | struct x25_dte_facilities dte_facilities; |
849 | int len, rc; | 850 | int len, addr_len, rc; |
850 | 851 | ||
851 | /* | 852 | /* |
852 | * Remove the LCI and frame type. | 853 | * Remove the LCI and frame type. |
@@ -857,7 +858,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
857 | * Extract the X.25 addresses and convert them to ASCII strings, | 858 | * Extract the X.25 addresses and convert them to ASCII strings, |
858 | * and remove them. | 859 | * and remove them. |
859 | */ | 860 | */ |
860 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 861 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); |
862 | skb_pull(skb, addr_len); | ||
861 | 863 | ||
862 | /* | 864 | /* |
863 | * Get the length of the facilities, skip past them for the moment | 865 | * Get the length of the facilities, skip past them for the moment |
@@ -873,11 +875,28 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
873 | sk = x25_find_listener(&source_addr,skb); | 875 | sk = x25_find_listener(&source_addr,skb); |
874 | skb_push(skb,len); | 876 | skb_push(skb,len); |
875 | 877 | ||
878 | if (sk != NULL && sk_acceptq_is_full(sk)) { | ||
879 | goto out_sock_put; | ||
880 | } | ||
881 | |||
876 | /* | 882 | /* |
877 | * We can't accept the Call Request. | 883 | * We dont have any listeners for this incoming call. |
884 | * Try forwarding it. | ||
878 | */ | 885 | */ |
879 | if (sk == NULL || sk_acceptq_is_full(sk)) | 886 | if (sk == NULL) { |
880 | goto out_clear_request; | 887 | skb_push(skb, addr_len + X25_STD_MIN_LEN); |
888 | if (sysctl_x25_forward && | ||
889 | x25_forward_call(&dest_addr, nb, skb, lci) > 0) | ||
890 | { | ||
891 | /* Call was forwarded, dont process it any more */ | ||
892 | kfree_skb(skb); | ||
893 | rc = 1; | ||
894 | goto out; | ||
895 | } else { | ||
896 | /* No listeners, can't forward, clear the call */ | ||
897 | goto out_clear_request; | ||
898 | } | ||
899 | } | ||
881 | 900 | ||
882 | /* | 901 | /* |
883 | * Try to reach a compromise on the requested facilities. | 902 | * Try to reach a compromise on the requested facilities. |
@@ -1101,7 +1120,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1101 | if (msg->msg_flags & MSG_OOB) | 1120 | if (msg->msg_flags & MSG_OOB) |
1102 | skb_queue_tail(&x25->interrupt_out_queue, skb); | 1121 | skb_queue_tail(&x25->interrupt_out_queue, skb); |
1103 | else { | 1122 | else { |
1104 | len = x25_output(sk, skb); | 1123 | len = x25_output(sk, skb); |
1105 | if (len < 0) | 1124 | if (len < 0) |
1106 | kfree_skb(skb); | 1125 | kfree_skb(skb); |
1107 | else if (x25->qbitincl) | 1126 | else if (x25->qbitincl) |
@@ -1200,7 +1219,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1200 | msg->msg_flags |= MSG_TRUNC; | 1219 | msg->msg_flags |= MSG_TRUNC; |
1201 | } | 1220 | } |
1202 | 1221 | ||
1203 | /* Currently, each datagram always contains a complete record */ | 1222 | /* Currently, each datagram always contains a complete record */ |
1204 | msg->msg_flags |= MSG_EOR; | 1223 | msg->msg_flags |= MSG_EOR; |
1205 | 1224 | ||
1206 | rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | 1225 | rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); |
@@ -1258,8 +1277,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1258 | case SIOCGSTAMP: | 1277 | case SIOCGSTAMP: |
1259 | rc = -EINVAL; | 1278 | rc = -EINVAL; |
1260 | if (sk) | 1279 | if (sk) |
1261 | rc = sock_get_timestamp(sk, | 1280 | rc = sock_get_timestamp(sk, |
1262 | (struct timeval __user *)argp); | 1281 | (struct timeval __user *)argp); |
1263 | break; | 1282 | break; |
1264 | case SIOCGIFADDR: | 1283 | case SIOCGIFADDR: |
1265 | case SIOCSIFADDR: | 1284 | case SIOCSIFADDR: |
@@ -1327,17 +1346,17 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1327 | } | 1346 | } |
1328 | 1347 | ||
1329 | case SIOCX25GDTEFACILITIES: { | 1348 | case SIOCX25GDTEFACILITIES: { |
1330 | rc = copy_to_user(argp, &x25->dte_facilities, | 1349 | rc = copy_to_user(argp, &x25->dte_facilities, |
1331 | sizeof(x25->dte_facilities)); | 1350 | sizeof(x25->dte_facilities)); |
1332 | if (rc) | 1351 | if (rc) |
1333 | rc = -EFAULT; | 1352 | rc = -EFAULT; |
1334 | break; | 1353 | break; |
1335 | } | 1354 | } |
1336 | 1355 | ||
1337 | case SIOCX25SDTEFACILITIES: { | 1356 | case SIOCX25SDTEFACILITIES: { |
1338 | struct x25_dte_facilities dtefacs; | 1357 | struct x25_dte_facilities dtefacs; |
1339 | rc = -EFAULT; | 1358 | rc = -EFAULT; |
1340 | if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) | 1359 | if (copy_from_user(&dtefacs, argp, sizeof(dtefacs))) |
1341 | break; | 1360 | break; |
1342 | rc = -EINVAL; | 1361 | rc = -EINVAL; |
1343 | if (sk->sk_state != TCP_LISTEN && | 1362 | if (sk->sk_state != TCP_LISTEN && |
@@ -1395,7 +1414,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1395 | if (copy_from_user(&sub_addr, argp, | 1414 | if (copy_from_user(&sub_addr, argp, |
1396 | sizeof(sub_addr))) | 1415 | sizeof(sub_addr))) |
1397 | break; | 1416 | break; |
1398 | rc = -EINVAL; | 1417 | rc = -EINVAL; |
1399 | if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN) | 1418 | if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN) |
1400 | break; | 1419 | break; |
1401 | x25->cudmatchlength = sub_addr.cudmatchlength; | 1420 | x25->cudmatchlength = sub_addr.cudmatchlength; |
@@ -1424,7 +1443,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1424 | break; | 1443 | break; |
1425 | } | 1444 | } |
1426 | 1445 | ||
1427 | default: | 1446 | default: |
1428 | rc = -ENOIOCTLCMD; | 1447 | rc = -ENOIOCTLCMD; |
1429 | break; | 1448 | break; |
1430 | } | 1449 | } |
@@ -1598,6 +1617,9 @@ void x25_kill_by_neigh(struct x25_neigh *nb) | |||
1598 | x25_disconnect(s, ENETUNREACH, 0, 0); | 1617 | x25_disconnect(s, ENETUNREACH, 0, 0); |
1599 | 1618 | ||
1600 | write_unlock_bh(&x25_list_lock); | 1619 | write_unlock_bh(&x25_list_lock); |
1620 | |||
1621 | /* Remove any related forwards */ | ||
1622 | x25_clear_forward_by_dev(nb->dev); | ||
1601 | } | 1623 | } |
1602 | 1624 | ||
1603 | static int __init x25_init(void) | 1625 | static int __init x25_init(void) |