aboutsummaryrefslogtreecommitdiffstats
path: root/net/x25/af_x25.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-02-13 01:43:25 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-02-13 01:43:25 -0500
commitd9bc125caf592b7d081021f32ce5b717efdf70c8 (patch)
tree263b7066ba22ddce21db610c0300f6eaac6f2064 /net/x25/af_x25.c
parent43d78ef2ba5bec26d0315859e8324bfc0be23766 (diff)
parentec2f9d1331f658433411c58077871e1eef4ee1b4 (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.c96
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;
63int sysctl_x25_reset_request_timeout = X25_DEFAULT_T22; 63int sysctl_x25_reset_request_timeout = X25_DEFAULT_T22;
64int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23; 64int sysctl_x25_clear_request_timeout = X25_DEFAULT_T23;
65int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2; 65int sysctl_x25_ack_holdback_timeout = X25_DEFAULT_T2;
66int sysctl_x25_forward = 0;
66 67
67HLIST_HEAD(x25_list); 68HLIST_HEAD(x25_list);
68DEFINE_RWLOCK(x25_list_lock); 69DEFINE_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;
533out: 534out:
@@ -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 */
612out: 613out:
613 return 0; 614 return 0;
@@ -634,7 +635,7 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
634static int x25_wait_for_connection_establishment(struct sock *sk) 635static 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
781static int x25_accept(struct socket *sock, struct socket *newsock, int flags) 782static 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
840int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, 841int 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
1603static int __init x25_init(void) 1625static int __init x25_init(void)