diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/x25 | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/x25')
-rw-r--r-- | net/x25/af_x25.c | 206 | ||||
-rw-r--r-- | net/x25/sysctl_net_x25.c | 15 | ||||
-rw-r--r-- | net/x25/x25_dev.c | 3 | ||||
-rw-r--r-- | net/x25/x25_facilities.c | 27 | ||||
-rw-r--r-- | net/x25/x25_forward.c | 1 | ||||
-rw-r--r-- | net/x25/x25_in.c | 18 | ||||
-rw-r--r-- | net/x25/x25_link.c | 1 | ||||
-rw-r--r-- | net/x25/x25_out.c | 1 | ||||
-rw-r--r-- | net/x25/x25_proc.c | 114 | ||||
-rw-r--r-- | net/x25/x25_route.c | 7 | ||||
-rw-r--r-- | net/x25/x25_subr.c | 7 |
11 files changed, 241 insertions, 159 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 7fa9c7ad3d3b..36e84e13c6aa 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/netdevice.h> | 47 | #include <linux/netdevice.h> |
48 | #include <linux/if_arp.h> | 48 | #include <linux/if_arp.h> |
49 | #include <linux/skbuff.h> | 49 | #include <linux/skbuff.h> |
50 | #include <linux/slab.h> | ||
50 | #include <net/sock.h> | 51 | #include <net/sock.h> |
51 | #include <net/tcp_states.h> | 52 | #include <net/tcp_states.h> |
52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
@@ -55,6 +56,7 @@ | |||
55 | #include <linux/notifier.h> | 56 | #include <linux/notifier.h> |
56 | #include <linux/init.h> | 57 | #include <linux/init.h> |
57 | #include <linux/compat.h> | 58 | #include <linux/compat.h> |
59 | #include <linux/ctype.h> | ||
58 | 60 | ||
59 | #include <net/x25.h> | 61 | #include <net/x25.h> |
60 | #include <net/compat.h> | 62 | #include <net/compat.h> |
@@ -81,6 +83,41 @@ struct compat_x25_subscrip_struct { | |||
81 | }; | 83 | }; |
82 | #endif | 84 | #endif |
83 | 85 | ||
86 | |||
87 | int x25_parse_address_block(struct sk_buff *skb, | ||
88 | struct x25_address *called_addr, | ||
89 | struct x25_address *calling_addr) | ||
90 | { | ||
91 | unsigned char len; | ||
92 | int needed; | ||
93 | int rc; | ||
94 | |||
95 | if (skb->len < 1) { | ||
96 | /* packet has no address block */ | ||
97 | rc = 0; | ||
98 | goto empty; | ||
99 | } | ||
100 | |||
101 | len = *skb->data; | ||
102 | needed = 1 + (len >> 4) + (len & 0x0f); | ||
103 | |||
104 | if (skb->len < needed) { | ||
105 | /* packet is too short to hold the addresses it claims | ||
106 | to hold */ | ||
107 | rc = -1; | ||
108 | goto empty; | ||
109 | } | ||
110 | |||
111 | return x25_addr_ntoa(skb->data, called_addr, calling_addr); | ||
112 | |||
113 | empty: | ||
114 | *called_addr->x25_addr = 0; | ||
115 | *calling_addr->x25_addr = 0; | ||
116 | |||
117 | return rc; | ||
118 | } | ||
119 | |||
120 | |||
84 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, | 121 | int x25_addr_ntoa(unsigned char *p, struct x25_address *called_addr, |
85 | struct x25_address *calling_addr) | 122 | struct x25_address *calling_addr) |
86 | { | 123 | { |
@@ -365,6 +402,7 @@ static void __x25_destroy_socket(struct sock *sk) | |||
365 | /* | 402 | /* |
366 | * Queue the unaccepted socket for death | 403 | * Queue the unaccepted socket for death |
367 | */ | 404 | */ |
405 | skb->sk->sk_state = TCP_LISTEN; | ||
368 | sock_set_flag(skb->sk, SOCK_DEAD); | 406 | sock_set_flag(skb->sk, SOCK_DEAD); |
369 | x25_start_heartbeat(skb->sk); | 407 | x25_start_heartbeat(skb->sk); |
370 | x25_sk(skb->sk)->state = X25_STATE_0; | 408 | x25_sk(skb->sk)->state = X25_STATE_0; |
@@ -415,6 +453,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
415 | struct sock *sk = sock->sk; | 453 | struct sock *sk = sock->sk; |
416 | int rc = -ENOPROTOOPT; | 454 | int rc = -ENOPROTOOPT; |
417 | 455 | ||
456 | lock_kernel(); | ||
418 | if (level != SOL_X25 || optname != X25_QBITINCL) | 457 | if (level != SOL_X25 || optname != X25_QBITINCL) |
419 | goto out; | 458 | goto out; |
420 | 459 | ||
@@ -429,6 +468,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
429 | x25_sk(sk)->qbitincl = !!opt; | 468 | x25_sk(sk)->qbitincl = !!opt; |
430 | rc = 0; | 469 | rc = 0; |
431 | out: | 470 | out: |
471 | unlock_kernel(); | ||
432 | return rc; | 472 | return rc; |
433 | } | 473 | } |
434 | 474 | ||
@@ -438,6 +478,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
438 | struct sock *sk = sock->sk; | 478 | struct sock *sk = sock->sk; |
439 | int val, len, rc = -ENOPROTOOPT; | 479 | int val, len, rc = -ENOPROTOOPT; |
440 | 480 | ||
481 | lock_kernel(); | ||
441 | if (level != SOL_X25 || optname != X25_QBITINCL) | 482 | if (level != SOL_X25 || optname != X25_QBITINCL) |
442 | goto out; | 483 | goto out; |
443 | 484 | ||
@@ -458,6 +499,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
458 | val = x25_sk(sk)->qbitincl; | 499 | val = x25_sk(sk)->qbitincl; |
459 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; | 500 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; |
460 | out: | 501 | out: |
502 | unlock_kernel(); | ||
461 | return rc; | 503 | return rc; |
462 | } | 504 | } |
463 | 505 | ||
@@ -466,12 +508,14 @@ static int x25_listen(struct socket *sock, int backlog) | |||
466 | struct sock *sk = sock->sk; | 508 | struct sock *sk = sock->sk; |
467 | int rc = -EOPNOTSUPP; | 509 | int rc = -EOPNOTSUPP; |
468 | 510 | ||
511 | lock_kernel(); | ||
469 | if (sk->sk_state != TCP_LISTEN) { | 512 | if (sk->sk_state != TCP_LISTEN) { |
470 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); | 513 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); |
471 | sk->sk_max_ack_backlog = backlog; | 514 | sk->sk_max_ack_backlog = backlog; |
472 | sk->sk_state = TCP_LISTEN; | 515 | sk->sk_state = TCP_LISTEN; |
473 | rc = 0; | 516 | rc = 0; |
474 | } | 517 | } |
518 | unlock_kernel(); | ||
475 | 519 | ||
476 | return rc; | 520 | return rc; |
477 | } | 521 | } |
@@ -501,19 +545,25 @@ out: | |||
501 | return sk; | 545 | return sk; |
502 | } | 546 | } |
503 | 547 | ||
504 | static int x25_create(struct net *net, struct socket *sock, int protocol) | 548 | static int x25_create(struct net *net, struct socket *sock, int protocol, |
549 | int kern) | ||
505 | { | 550 | { |
506 | struct sock *sk; | 551 | struct sock *sk; |
507 | struct x25_sock *x25; | 552 | struct x25_sock *x25; |
508 | int rc = -ESOCKTNOSUPPORT; | 553 | int rc = -EAFNOSUPPORT; |
509 | 554 | ||
510 | if (net != &init_net) | 555 | if (!net_eq(net, &init_net)) |
511 | return -EAFNOSUPPORT; | 556 | goto out; |
512 | 557 | ||
513 | if (sock->type != SOCK_SEQPACKET || protocol) | 558 | rc = -ESOCKTNOSUPPORT; |
559 | if (sock->type != SOCK_SEQPACKET) | ||
514 | goto out; | 560 | goto out; |
515 | 561 | ||
516 | rc = -ENOMEM; | 562 | rc = -EINVAL; |
563 | if (protocol) | ||
564 | goto out; | ||
565 | |||
566 | rc = -ENOBUFS; | ||
517 | if ((sk = x25_alloc_socket(net)) == NULL) | 567 | if ((sk = x25_alloc_socket(net)) == NULL) |
518 | goto out; | 568 | goto out; |
519 | 569 | ||
@@ -540,7 +590,8 @@ static int x25_create(struct net *net, struct socket *sock, int protocol) | |||
540 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; | 590 | x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE; |
541 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; | 591 | x25->facilities.pacsize_in = X25_DEFAULT_PACKET_SIZE; |
542 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; | 592 | x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE; |
543 | x25->facilities.throughput = X25_DEFAULT_THROUGHPUT; | 593 | x25->facilities.throughput = 0; /* by default don't negotiate |
594 | throughput */ | ||
544 | x25->facilities.reverse = X25_DEFAULT_REVERSE; | 595 | x25->facilities.reverse = X25_DEFAULT_REVERSE; |
545 | x25->dte_facilities.calling_len = 0; | 596 | x25->dte_facilities.calling_len = 0; |
546 | x25->dte_facilities.called_len = 0; | 597 | x25->dte_facilities.called_len = 0; |
@@ -597,6 +648,7 @@ static int x25_release(struct socket *sock) | |||
597 | struct sock *sk = sock->sk; | 648 | struct sock *sk = sock->sk; |
598 | struct x25_sock *x25; | 649 | struct x25_sock *x25; |
599 | 650 | ||
651 | lock_kernel(); | ||
600 | if (!sk) | 652 | if (!sk) |
601 | goto out; | 653 | goto out; |
602 | 654 | ||
@@ -627,6 +679,7 @@ static int x25_release(struct socket *sock) | |||
627 | 679 | ||
628 | sock_orphan(sk); | 680 | sock_orphan(sk); |
629 | out: | 681 | out: |
682 | unlock_kernel(); | ||
630 | return 0; | 683 | return 0; |
631 | } | 684 | } |
632 | 685 | ||
@@ -634,18 +687,31 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
634 | { | 687 | { |
635 | struct sock *sk = sock->sk; | 688 | struct sock *sk = sock->sk; |
636 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; | 689 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; |
690 | int len, i, rc = 0; | ||
637 | 691 | ||
692 | lock_kernel(); | ||
638 | if (!sock_flag(sk, SOCK_ZAPPED) || | 693 | if (!sock_flag(sk, SOCK_ZAPPED) || |
639 | addr_len != sizeof(struct sockaddr_x25) || | 694 | addr_len != sizeof(struct sockaddr_x25) || |
640 | addr->sx25_family != AF_X25) | 695 | addr->sx25_family != AF_X25) { |
641 | return -EINVAL; | 696 | rc = -EINVAL; |
697 | goto out; | ||
698 | } | ||
699 | |||
700 | len = strlen(addr->sx25_addr.x25_addr); | ||
701 | for (i = 0; i < len; i++) { | ||
702 | if (!isdigit(addr->sx25_addr.x25_addr[i])) { | ||
703 | rc = -EINVAL; | ||
704 | goto out; | ||
705 | } | ||
706 | } | ||
642 | 707 | ||
643 | x25_sk(sk)->source_addr = addr->sx25_addr; | 708 | x25_sk(sk)->source_addr = addr->sx25_addr; |
644 | x25_insert_socket(sk); | 709 | x25_insert_socket(sk); |
645 | sock_reset_flag(sk, SOCK_ZAPPED); | 710 | sock_reset_flag(sk, SOCK_ZAPPED); |
646 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); | 711 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); |
647 | 712 | out: | |
648 | return 0; | 713 | unlock_kernel(); |
714 | return rc; | ||
649 | } | 715 | } |
650 | 716 | ||
651 | static int x25_wait_for_connection_establishment(struct sock *sk) | 717 | static int x25_wait_for_connection_establishment(struct sock *sk) |
@@ -686,6 +752,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, | |||
686 | struct x25_route *rt; | 752 | struct x25_route *rt; |
687 | int rc = 0; | 753 | int rc = 0; |
688 | 754 | ||
755 | lock_kernel(); | ||
689 | lock_sock(sk); | 756 | lock_sock(sk); |
690 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | 757 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { |
691 | sock->state = SS_CONNECTED; | 758 | sock->state = SS_CONNECTED; |
@@ -763,6 +830,7 @@ out_put_route: | |||
763 | x25_route_put(rt); | 830 | x25_route_put(rt); |
764 | out: | 831 | out: |
765 | release_sock(sk); | 832 | release_sock(sk); |
833 | unlock_kernel(); | ||
766 | return rc; | 834 | return rc; |
767 | } | 835 | } |
768 | 836 | ||
@@ -802,6 +870,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
802 | struct sk_buff *skb; | 870 | struct sk_buff *skb; |
803 | int rc = -EINVAL; | 871 | int rc = -EINVAL; |
804 | 872 | ||
873 | lock_kernel(); | ||
805 | if (!sk || sk->sk_state != TCP_LISTEN) | 874 | if (!sk || sk->sk_state != TCP_LISTEN) |
806 | goto out; | 875 | goto out; |
807 | 876 | ||
@@ -829,6 +898,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
829 | out2: | 898 | out2: |
830 | release_sock(sk); | 899 | release_sock(sk); |
831 | out: | 900 | out: |
901 | unlock_kernel(); | ||
832 | return rc; | 902 | return rc; |
833 | } | 903 | } |
834 | 904 | ||
@@ -838,10 +908,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
838 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; | 908 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; |
839 | struct sock *sk = sock->sk; | 909 | struct sock *sk = sock->sk; |
840 | struct x25_sock *x25 = x25_sk(sk); | 910 | struct x25_sock *x25 = x25_sk(sk); |
911 | int rc = 0; | ||
841 | 912 | ||
913 | lock_kernel(); | ||
842 | if (peer) { | 914 | if (peer) { |
843 | if (sk->sk_state != TCP_ESTABLISHED) | 915 | if (sk->sk_state != TCP_ESTABLISHED) { |
844 | return -ENOTCONN; | 916 | rc = -ENOTCONN; |
917 | goto out; | ||
918 | } | ||
845 | sx25->sx25_addr = x25->dest_addr; | 919 | sx25->sx25_addr = x25->dest_addr; |
846 | } else | 920 | } else |
847 | sx25->sx25_addr = x25->source_addr; | 921 | sx25->sx25_addr = x25->source_addr; |
@@ -849,7 +923,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
849 | sx25->sx25_family = AF_X25; | 923 | sx25->sx25_family = AF_X25; |
850 | *uaddr_len = sizeof(*sx25); | 924 | *uaddr_len = sizeof(*sx25); |
851 | 925 | ||
852 | return 0; | 926 | out: |
927 | unlock_kernel(); | ||
928 | return rc; | ||
929 | } | ||
930 | |||
931 | static unsigned int x25_datagram_poll(struct file *file, struct socket *sock, | ||
932 | poll_table *wait) | ||
933 | { | ||
934 | int rc; | ||
935 | |||
936 | lock_kernel(); | ||
937 | rc = datagram_poll(file, sock, wait); | ||
938 | unlock_kernel(); | ||
939 | |||
940 | return rc; | ||
853 | } | 941 | } |
854 | 942 | ||
855 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | 943 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, |
@@ -871,16 +959,26 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
871 | /* | 959 | /* |
872 | * Extract the X.25 addresses and convert them to ASCII strings, | 960 | * Extract the X.25 addresses and convert them to ASCII strings, |
873 | * and remove them. | 961 | * and remove them. |
962 | * | ||
963 | * Address block is mandatory in call request packets | ||
874 | */ | 964 | */ |
875 | addr_len = x25_addr_ntoa(skb->data, &source_addr, &dest_addr); | 965 | addr_len = x25_parse_address_block(skb, &source_addr, &dest_addr); |
966 | if (addr_len <= 0) | ||
967 | goto out_clear_request; | ||
876 | skb_pull(skb, addr_len); | 968 | skb_pull(skb, addr_len); |
877 | 969 | ||
878 | /* | 970 | /* |
879 | * Get the length of the facilities, skip past them for the moment | 971 | * Get the length of the facilities, skip past them for the moment |
880 | * get the call user data because this is needed to determine | 972 | * get the call user data because this is needed to determine |
881 | * the correct listener | 973 | * the correct listener |
974 | * | ||
975 | * Facilities length is mandatory in call request packets | ||
882 | */ | 976 | */ |
977 | if (skb->len < 1) | ||
978 | goto out_clear_request; | ||
883 | len = skb->data[0] + 1; | 979 | len = skb->data[0] + 1; |
980 | if (skb->len < len) | ||
981 | goto out_clear_request; | ||
884 | skb_pull(skb,len); | 982 | skb_pull(skb,len); |
885 | 983 | ||
886 | /* | 984 | /* |
@@ -1002,6 +1100,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1002 | size_t size; | 1100 | size_t size; |
1003 | int qbit = 0, rc = -EINVAL; | 1101 | int qbit = 0, rc = -EINVAL; |
1004 | 1102 | ||
1103 | lock_kernel(); | ||
1005 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) | 1104 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) |
1006 | goto out; | 1105 | goto out; |
1007 | 1106 | ||
@@ -1166,6 +1265,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1166 | release_sock(sk); | 1265 | release_sock(sk); |
1167 | rc = len; | 1266 | rc = len; |
1168 | out: | 1267 | out: |
1268 | unlock_kernel(); | ||
1169 | return rc; | 1269 | return rc; |
1170 | out_kfree_skb: | 1270 | out_kfree_skb: |
1171 | kfree_skb(skb); | 1271 | kfree_skb(skb); |
@@ -1186,6 +1286,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1186 | unsigned char *asmptr; | 1286 | unsigned char *asmptr; |
1187 | int rc = -ENOTCONN; | 1287 | int rc = -ENOTCONN; |
1188 | 1288 | ||
1289 | lock_kernel(); | ||
1189 | /* | 1290 | /* |
1190 | * This works for seqpacket too. The receiver has ordered the queue for | 1291 | * This works for seqpacket too. The receiver has ordered the queue for |
1191 | * us! We do one quick check first though | 1292 | * us! We do one quick check first though |
@@ -1259,6 +1360,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1259 | out_free_dgram: | 1360 | out_free_dgram: |
1260 | skb_free_datagram(sk, skb); | 1361 | skb_free_datagram(sk, skb); |
1261 | out: | 1362 | out: |
1363 | unlock_kernel(); | ||
1262 | return rc; | 1364 | return rc; |
1263 | } | 1365 | } |
1264 | 1366 | ||
@@ -1270,6 +1372,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1270 | void __user *argp = (void __user *)arg; | 1372 | void __user *argp = (void __user *)arg; |
1271 | int rc; | 1373 | int rc; |
1272 | 1374 | ||
1375 | lock_kernel(); | ||
1273 | switch (cmd) { | 1376 | switch (cmd) { |
1274 | case TIOCOUTQ: { | 1377 | case TIOCOUTQ: { |
1275 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | 1378 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
@@ -1359,11 +1462,22 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1359 | if (facilities.winsize_in < 1 || | 1462 | if (facilities.winsize_in < 1 || |
1360 | facilities.winsize_in > 127) | 1463 | facilities.winsize_in > 127) |
1361 | break; | 1464 | break; |
1362 | if (facilities.throughput < 0x03 || | 1465 | if (facilities.throughput) { |
1363 | facilities.throughput > 0xDD) | 1466 | int out = facilities.throughput & 0xf0; |
1364 | break; | 1467 | int in = facilities.throughput & 0x0f; |
1468 | if (!out) | ||
1469 | facilities.throughput |= | ||
1470 | X25_DEFAULT_THROUGHPUT << 4; | ||
1471 | else if (out < 0x30 || out > 0xD0) | ||
1472 | break; | ||
1473 | if (!in) | ||
1474 | facilities.throughput |= | ||
1475 | X25_DEFAULT_THROUGHPUT; | ||
1476 | else if (in < 0x03 || in > 0x0D) | ||
1477 | break; | ||
1478 | } | ||
1365 | if (facilities.reverse && | 1479 | if (facilities.reverse && |
1366 | (facilities.reverse | 0x81)!= 0x81) | 1480 | (facilities.reverse & 0x81) != 0x81) |
1367 | break; | 1481 | break; |
1368 | x25->facilities = facilities; | 1482 | x25->facilities = facilities; |
1369 | rc = 0; | 1483 | rc = 0; |
@@ -1430,6 +1544,17 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1430 | break; | 1544 | break; |
1431 | } | 1545 | } |
1432 | 1546 | ||
1547 | case SIOCX25SCAUSEDIAG: { | ||
1548 | struct x25_causediag causediag; | ||
1549 | rc = -EFAULT; | ||
1550 | if (copy_from_user(&causediag, argp, sizeof(causediag))) | ||
1551 | break; | ||
1552 | x25->causediag = causediag; | ||
1553 | rc = 0; | ||
1554 | break; | ||
1555 | |||
1556 | } | ||
1557 | |||
1433 | case SIOCX25SCUDMATCHLEN: { | 1558 | case SIOCX25SCUDMATCHLEN: { |
1434 | struct x25_subaddr sub_addr; | 1559 | struct x25_subaddr sub_addr; |
1435 | rc = -EINVAL; | 1560 | rc = -EINVAL; |
@@ -1472,11 +1597,12 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1472 | rc = -ENOIOCTLCMD; | 1597 | rc = -ENOIOCTLCMD; |
1473 | break; | 1598 | break; |
1474 | } | 1599 | } |
1600 | unlock_kernel(); | ||
1475 | 1601 | ||
1476 | return rc; | 1602 | return rc; |
1477 | } | 1603 | } |
1478 | 1604 | ||
1479 | static struct net_proto_family x25_family_ops = { | 1605 | static const struct net_proto_family x25_family_ops = { |
1480 | .family = AF_X25, | 1606 | .family = AF_X25, |
1481 | .create = x25_create, | 1607 | .create = x25_create, |
1482 | .owner = THIS_MODULE, | 1608 | .owner = THIS_MODULE, |
@@ -1542,15 +1668,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1542 | break; | 1668 | break; |
1543 | case SIOCGSTAMP: | 1669 | case SIOCGSTAMP: |
1544 | rc = -EINVAL; | 1670 | rc = -EINVAL; |
1671 | lock_kernel(); | ||
1545 | if (sk) | 1672 | if (sk) |
1546 | rc = compat_sock_get_timestamp(sk, | 1673 | rc = compat_sock_get_timestamp(sk, |
1547 | (struct timeval __user*)argp); | 1674 | (struct timeval __user*)argp); |
1675 | unlock_kernel(); | ||
1548 | break; | 1676 | break; |
1549 | case SIOCGSTAMPNS: | 1677 | case SIOCGSTAMPNS: |
1550 | rc = -EINVAL; | 1678 | rc = -EINVAL; |
1679 | lock_kernel(); | ||
1551 | if (sk) | 1680 | if (sk) |
1552 | rc = compat_sock_get_timestampns(sk, | 1681 | rc = compat_sock_get_timestampns(sk, |
1553 | (struct timespec __user*)argp); | 1682 | (struct timespec __user*)argp); |
1683 | unlock_kernel(); | ||
1554 | break; | 1684 | break; |
1555 | case SIOCGIFADDR: | 1685 | case SIOCGIFADDR: |
1556 | case SIOCSIFADDR: | 1686 | case SIOCSIFADDR: |
@@ -1569,16 +1699,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1569 | rc = -EPERM; | 1699 | rc = -EPERM; |
1570 | if (!capable(CAP_NET_ADMIN)) | 1700 | if (!capable(CAP_NET_ADMIN)) |
1571 | break; | 1701 | break; |
1702 | lock_kernel(); | ||
1572 | rc = x25_route_ioctl(cmd, argp); | 1703 | rc = x25_route_ioctl(cmd, argp); |
1704 | unlock_kernel(); | ||
1573 | break; | 1705 | break; |
1574 | case SIOCX25GSUBSCRIP: | 1706 | case SIOCX25GSUBSCRIP: |
1707 | lock_kernel(); | ||
1575 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1708 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1709 | unlock_kernel(); | ||
1576 | break; | 1710 | break; |
1577 | case SIOCX25SSUBSCRIP: | 1711 | case SIOCX25SSUBSCRIP: |
1578 | rc = -EPERM; | 1712 | rc = -EPERM; |
1579 | if (!capable(CAP_NET_ADMIN)) | 1713 | if (!capable(CAP_NET_ADMIN)) |
1580 | break; | 1714 | break; |
1715 | lock_kernel(); | ||
1581 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1716 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1717 | unlock_kernel(); | ||
1582 | break; | 1718 | break; |
1583 | case SIOCX25GFACILITIES: | 1719 | case SIOCX25GFACILITIES: |
1584 | case SIOCX25SFACILITIES: | 1720 | case SIOCX25SFACILITIES: |
@@ -1587,6 +1723,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1587 | case SIOCX25GCALLUSERDATA: | 1723 | case SIOCX25GCALLUSERDATA: |
1588 | case SIOCX25SCALLUSERDATA: | 1724 | case SIOCX25SCALLUSERDATA: |
1589 | case SIOCX25GCAUSEDIAG: | 1725 | case SIOCX25GCAUSEDIAG: |
1726 | case SIOCX25SCAUSEDIAG: | ||
1590 | case SIOCX25SCUDMATCHLEN: | 1727 | case SIOCX25SCUDMATCHLEN: |
1591 | case SIOCX25CALLACCPTAPPRV: | 1728 | case SIOCX25CALLACCPTAPPRV: |
1592 | case SIOCX25SENDCALLACCPT: | 1729 | case SIOCX25SENDCALLACCPT: |
@@ -1600,7 +1737,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1600 | } | 1737 | } |
1601 | #endif | 1738 | #endif |
1602 | 1739 | ||
1603 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | 1740 | static const struct proto_ops x25_proto_ops = { |
1604 | .family = AF_X25, | 1741 | .family = AF_X25, |
1605 | .owner = THIS_MODULE, | 1742 | .owner = THIS_MODULE, |
1606 | .release = x25_release, | 1743 | .release = x25_release, |
@@ -1609,7 +1746,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1609 | .socketpair = sock_no_socketpair, | 1746 | .socketpair = sock_no_socketpair, |
1610 | .accept = x25_accept, | 1747 | .accept = x25_accept, |
1611 | .getname = x25_getname, | 1748 | .getname = x25_getname, |
1612 | .poll = datagram_poll, | 1749 | .poll = x25_datagram_poll, |
1613 | .ioctl = x25_ioctl, | 1750 | .ioctl = x25_ioctl, |
1614 | #ifdef CONFIG_COMPAT | 1751 | #ifdef CONFIG_COMPAT |
1615 | .compat_ioctl = compat_x25_ioctl, | 1752 | .compat_ioctl = compat_x25_ioctl, |
@@ -1624,8 +1761,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1624 | .sendpage = sock_no_sendpage, | 1761 | .sendpage = sock_no_sendpage, |
1625 | }; | 1762 | }; |
1626 | 1763 | ||
1627 | SOCKOPS_WRAP(x25_proto, AF_X25); | ||
1628 | |||
1629 | static struct packet_type x25_packet_type __read_mostly = { | 1764 | static struct packet_type x25_packet_type __read_mostly = { |
1630 | .type = cpu_to_be16(ETH_P_X25), | 1765 | .type = cpu_to_be16(ETH_P_X25), |
1631 | .func = x25_lapb_receive_frame, | 1766 | .func = x25_lapb_receive_frame, |
@@ -1659,20 +1794,31 @@ static int __init x25_init(void) | |||
1659 | if (rc != 0) | 1794 | if (rc != 0) |
1660 | goto out; | 1795 | goto out; |
1661 | 1796 | ||
1662 | sock_register(&x25_family_ops); | 1797 | rc = sock_register(&x25_family_ops); |
1798 | if (rc != 0) | ||
1799 | goto out_proto; | ||
1663 | 1800 | ||
1664 | dev_add_pack(&x25_packet_type); | 1801 | dev_add_pack(&x25_packet_type); |
1665 | 1802 | ||
1666 | register_netdevice_notifier(&x25_dev_notifier); | 1803 | rc = register_netdevice_notifier(&x25_dev_notifier); |
1804 | if (rc != 0) | ||
1805 | goto out_sock; | ||
1667 | 1806 | ||
1668 | printk(KERN_INFO "X.25 for Linux Version 0.2\n"); | 1807 | printk(KERN_INFO "X.25 for Linux Version 0.2\n"); |
1669 | 1808 | ||
1670 | #ifdef CONFIG_SYSCTL | ||
1671 | x25_register_sysctl(); | 1809 | x25_register_sysctl(); |
1672 | #endif | 1810 | rc = x25_proc_init(); |
1673 | x25_proc_init(); | 1811 | if (rc != 0) |
1812 | goto out_dev; | ||
1674 | out: | 1813 | out: |
1675 | return rc; | 1814 | return rc; |
1815 | out_dev: | ||
1816 | unregister_netdevice_notifier(&x25_dev_notifier); | ||
1817 | out_sock: | ||
1818 | sock_unregister(AF_X25); | ||
1819 | out_proto: | ||
1820 | proto_unregister(&x25_proto); | ||
1821 | goto out; | ||
1676 | } | 1822 | } |
1677 | module_init(x25_init); | 1823 | module_init(x25_init); |
1678 | 1824 | ||
@@ -1682,9 +1828,7 @@ static void __exit x25_exit(void) | |||
1682 | x25_link_free(); | 1828 | x25_link_free(); |
1683 | x25_route_free(); | 1829 | x25_route_free(); |
1684 | 1830 | ||
1685 | #ifdef CONFIG_SYSCTL | ||
1686 | x25_unregister_sysctl(); | 1831 | x25_unregister_sysctl(); |
1687 | #endif | ||
1688 | 1832 | ||
1689 | unregister_netdevice_notifier(&x25_dev_notifier); | 1833 | unregister_netdevice_notifier(&x25_dev_notifier); |
1690 | 1834 | ||
diff --git a/net/x25/sysctl_net_x25.c b/net/x25/sysctl_net_x25.c index a5d3416522de..d2efd29f434e 100644 --- a/net/x25/sysctl_net_x25.c +++ b/net/x25/sysctl_net_x25.c | |||
@@ -19,62 +19,51 @@ static struct ctl_table_header *x25_table_header; | |||
19 | 19 | ||
20 | static struct ctl_table x25_table[] = { | 20 | static struct ctl_table x25_table[] = { |
21 | { | 21 | { |
22 | .ctl_name = NET_X25_RESTART_REQUEST_TIMEOUT, | ||
23 | .procname = "restart_request_timeout", | 22 | .procname = "restart_request_timeout", |
24 | .data = &sysctl_x25_restart_request_timeout, | 23 | .data = &sysctl_x25_restart_request_timeout, |
25 | .maxlen = sizeof(int), | 24 | .maxlen = sizeof(int), |
26 | .mode = 0644, | 25 | .mode = 0644, |
27 | .proc_handler = proc_dointvec_minmax, | 26 | .proc_handler = proc_dointvec_minmax, |
28 | .strategy = sysctl_intvec, | ||
29 | .extra1 = &min_timer, | 27 | .extra1 = &min_timer, |
30 | .extra2 = &max_timer, | 28 | .extra2 = &max_timer, |
31 | }, | 29 | }, |
32 | { | 30 | { |
33 | .ctl_name = NET_X25_CALL_REQUEST_TIMEOUT, | ||
34 | .procname = "call_request_timeout", | 31 | .procname = "call_request_timeout", |
35 | .data = &sysctl_x25_call_request_timeout, | 32 | .data = &sysctl_x25_call_request_timeout, |
36 | .maxlen = sizeof(int), | 33 | .maxlen = sizeof(int), |
37 | .mode = 0644, | 34 | .mode = 0644, |
38 | .proc_handler = proc_dointvec_minmax, | 35 | .proc_handler = proc_dointvec_minmax, |
39 | .strategy = sysctl_intvec, | ||
40 | .extra1 = &min_timer, | 36 | .extra1 = &min_timer, |
41 | .extra2 = &max_timer, | 37 | .extra2 = &max_timer, |
42 | }, | 38 | }, |
43 | { | 39 | { |
44 | .ctl_name = NET_X25_RESET_REQUEST_TIMEOUT, | ||
45 | .procname = "reset_request_timeout", | 40 | .procname = "reset_request_timeout", |
46 | .data = &sysctl_x25_reset_request_timeout, | 41 | .data = &sysctl_x25_reset_request_timeout, |
47 | .maxlen = sizeof(int), | 42 | .maxlen = sizeof(int), |
48 | .mode = 0644, | 43 | .mode = 0644, |
49 | .proc_handler = proc_dointvec_minmax, | 44 | .proc_handler = proc_dointvec_minmax, |
50 | .strategy = sysctl_intvec, | ||
51 | .extra1 = &min_timer, | 45 | .extra1 = &min_timer, |
52 | .extra2 = &max_timer, | 46 | .extra2 = &max_timer, |
53 | }, | 47 | }, |
54 | { | 48 | { |
55 | .ctl_name = NET_X25_CLEAR_REQUEST_TIMEOUT, | ||
56 | .procname = "clear_request_timeout", | 49 | .procname = "clear_request_timeout", |
57 | .data = &sysctl_x25_clear_request_timeout, | 50 | .data = &sysctl_x25_clear_request_timeout, |
58 | .maxlen = sizeof(int), | 51 | .maxlen = sizeof(int), |
59 | .mode = 0644, | 52 | .mode = 0644, |
60 | .proc_handler = proc_dointvec_minmax, | 53 | .proc_handler = proc_dointvec_minmax, |
61 | .strategy = sysctl_intvec, | ||
62 | .extra1 = &min_timer, | 54 | .extra1 = &min_timer, |
63 | .extra2 = &max_timer, | 55 | .extra2 = &max_timer, |
64 | }, | 56 | }, |
65 | { | 57 | { |
66 | .ctl_name = NET_X25_ACK_HOLD_BACK_TIMEOUT, | ||
67 | .procname = "acknowledgement_hold_back_timeout", | 58 | .procname = "acknowledgement_hold_back_timeout", |
68 | .data = &sysctl_x25_ack_holdback_timeout, | 59 | .data = &sysctl_x25_ack_holdback_timeout, |
69 | .maxlen = sizeof(int), | 60 | .maxlen = sizeof(int), |
70 | .mode = 0644, | 61 | .mode = 0644, |
71 | .proc_handler = proc_dointvec_minmax, | 62 | .proc_handler = proc_dointvec_minmax, |
72 | .strategy = sysctl_intvec, | ||
73 | .extra1 = &min_timer, | 63 | .extra1 = &min_timer, |
74 | .extra2 = &max_timer, | 64 | .extra2 = &max_timer, |
75 | }, | 65 | }, |
76 | { | 66 | { |
77 | .ctl_name = NET_X25_FORWARD, | ||
78 | .procname = "x25_forward", | 67 | .procname = "x25_forward", |
79 | .data = &sysctl_x25_forward, | 68 | .data = &sysctl_x25_forward, |
80 | .maxlen = sizeof(int), | 69 | .maxlen = sizeof(int), |
@@ -85,8 +74,8 @@ static struct ctl_table x25_table[] = { | |||
85 | }; | 74 | }; |
86 | 75 | ||
87 | static struct ctl_path x25_path[] = { | 76 | static struct ctl_path x25_path[] = { |
88 | { .procname = "net", .ctl_name = CTL_NET, }, | 77 | { .procname = "net", }, |
89 | { .procname = "x25", .ctl_name = NET_X25, }, | 78 | { .procname = "x25", }, |
90 | { } | 79 | { } |
91 | }; | 80 | }; |
92 | 81 | ||
diff --git a/net/x25/x25_dev.c b/net/x25/x25_dev.c index 3e1efe534645..b9ef682230a0 100644 --- a/net/x25/x25_dev.c +++ b/net/x25/x25_dev.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/netdevice.h> | 21 | #include <linux/netdevice.h> |
22 | #include <linux/skbuff.h> | 22 | #include <linux/skbuff.h> |
23 | #include <linux/slab.h> | ||
23 | #include <net/sock.h> | 24 | #include <net/sock.h> |
24 | #include <linux/if_arp.h> | 25 | #include <linux/if_arp.h> |
25 | #include <net/x25.h> | 26 | #include <net/x25.h> |
@@ -53,7 +54,7 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *nb) | |||
53 | if (!sock_owned_by_user(sk)) { | 54 | if (!sock_owned_by_user(sk)) { |
54 | queued = x25_process_rx_frame(sk, skb); | 55 | queued = x25_process_rx_frame(sk, skb); |
55 | } else { | 56 | } else { |
56 | sk_add_backlog(sk, skb); | 57 | queued = !sk_add_backlog(sk, skb); |
57 | } | 58 | } |
58 | bh_unlock_sock(sk); | 59 | bh_unlock_sock(sk); |
59 | sock_put(sk); | 60 | sock_put(sk); |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index a21f6646eb3a..771bab00754b 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
@@ -35,7 +35,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) | 35 | struct x25_dte_facilities *dte_facs, unsigned long *vc_fac_mask) |
36 | { | 36 | { |
37 | unsigned char *p = skb->data; | 37 | unsigned char *p = skb->data; |
38 | unsigned int len = *p++; | 38 | unsigned int len; |
39 | 39 | ||
40 | *vc_fac_mask = 0; | 40 | *vc_fac_mask = 0; |
41 | 41 | ||
@@ -50,6 +50,14 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, | |||
50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); | 50 | memset(dte_facs->called_ae, '\0', sizeof(dte_facs->called_ae)); |
51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); | 51 | memset(dte_facs->calling_ae, '\0', sizeof(dte_facs->calling_ae)); |
52 | 52 | ||
53 | if (skb->len < 1) | ||
54 | return 0; | ||
55 | |||
56 | len = *p++; | ||
57 | |||
58 | if (len >= skb->len) | ||
59 | return -1; | ||
60 | |||
53 | while (len > 0) { | 61 | while (len > 0) { |
54 | switch (*p & X25_FAC_CLASS_MASK) { | 62 | switch (*p & X25_FAC_CLASS_MASK) { |
55 | case X25_FAC_CLASS_A: | 63 | case X25_FAC_CLASS_A: |
@@ -247,6 +255,8 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
247 | memcpy(new, ours, sizeof(*new)); | 255 | memcpy(new, ours, sizeof(*new)); |
248 | 256 | ||
249 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); | 257 | len = x25_parse_facilities(skb, &theirs, dte, &x25->vc_facil_mask); |
258 | if (len < 0) | ||
259 | return len; | ||
250 | 260 | ||
251 | /* | 261 | /* |
252 | * They want reverse charging, we won't accept it. | 262 | * They want reverse charging, we won't accept it. |
@@ -259,9 +269,18 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, | |||
259 | new->reverse = theirs.reverse; | 269 | new->reverse = theirs.reverse; |
260 | 270 | ||
261 | if (theirs.throughput) { | 271 | if (theirs.throughput) { |
262 | if (theirs.throughput < ours->throughput) { | 272 | int theirs_in = theirs.throughput & 0x0f; |
263 | SOCK_DEBUG(sk, "X.25: throughput negotiated down\n"); | 273 | int theirs_out = theirs.throughput & 0xf0; |
264 | new->throughput = theirs.throughput; | 274 | int ours_in = ours->throughput & 0x0f; |
275 | int ours_out = ours->throughput & 0xf0; | ||
276 | if (!ours_in || theirs_in < ours_in) { | ||
277 | SOCK_DEBUG(sk, "X.25: inbound throughput negotiated\n"); | ||
278 | new->throughput = (new->throughput & 0xf0) | theirs_in; | ||
279 | } | ||
280 | if (!ours_out || theirs_out < ours_out) { | ||
281 | SOCK_DEBUG(sk, | ||
282 | "X.25: outbound throughput negotiated\n"); | ||
283 | new->throughput = (new->throughput & 0x0f) | theirs_out; | ||
265 | } | 284 | } |
266 | } | 285 | } |
267 | 286 | ||
diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index 056a55f3a871..25a810793968 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c | |||
@@ -10,6 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | #include <linux/if_arp.h> | 11 | #include <linux/if_arp.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/slab.h> | ||
13 | #include <net/x25.h> | 14 | #include <net/x25.h> |
14 | 15 | ||
15 | LIST_HEAD(x25_forward_list); | 16 | LIST_HEAD(x25_forward_list); |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 7d7c3abf38b5..372ac226e648 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * i-frames. | 23 | * i-frames. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/slab.h> | ||
26 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
27 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
28 | #include <linux/string.h> | 29 | #include <linux/string.h> |
@@ -89,6 +90,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) | |||
89 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 90 | static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
90 | { | 91 | { |
91 | struct x25_address source_addr, dest_addr; | 92 | struct x25_address source_addr, dest_addr; |
93 | int len; | ||
92 | 94 | ||
93 | switch (frametype) { | 95 | switch (frametype) { |
94 | case X25_CALL_ACCEPTED: { | 96 | case X25_CALL_ACCEPTED: { |
@@ -106,15 +108,21 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
106 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
107 | */ | 109 | */ |
108 | skb_pull(skb, X25_STD_MIN_LEN); | 110 | skb_pull(skb, X25_STD_MIN_LEN); |
109 | skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); | 111 | |
110 | skb_pull(skb, | 112 | len = x25_parse_address_block(skb, &source_addr, |
111 | x25_parse_facilities(skb, &x25->facilities, | 113 | &dest_addr); |
114 | if (len > 0) | ||
115 | skb_pull(skb, len); | ||
116 | |||
117 | len = x25_parse_facilities(skb, &x25->facilities, | ||
112 | &x25->dte_facilities, | 118 | &x25->dte_facilities, |
113 | &x25->vc_facil_mask)); | 119 | &x25->vc_facil_mask); |
120 | if (len > 0) | ||
121 | skb_pull(skb, len); | ||
114 | /* | 122 | /* |
115 | * Copy any Call User Data. | 123 | * Copy any Call User Data. |
116 | */ | 124 | */ |
117 | if (skb->len >= 0) { | 125 | if (skb->len > 0) { |
118 | skb_copy_from_linear_data(skb, | 126 | skb_copy_from_linear_data(skb, |
119 | x25->calluserdata.cuddata, | 127 | x25->calluserdata.cuddata, |
120 | skb->len); | 128 | skb->len); |
diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index e4e1b6e49538..73e7b954ad28 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/jiffies.h> | 25 | #include <linux/jiffies.h> |
26 | #include <linux/timer.h> | 26 | #include <linux/timer.h> |
27 | #include <linux/slab.h> | ||
27 | #include <linux/netdevice.h> | 28 | #include <linux/netdevice.h> |
28 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
29 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c index 2b96b52114d6..52351a26b6fc 100644 --- a/net/x25/x25_out.c +++ b/net/x25/x25_out.c | |||
@@ -22,6 +22,7 @@ | |||
22 | * needed cleaned seq-number fields. | 22 | * needed cleaned seq-number fields. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/slab.h> | ||
25 | #include <linux/socket.h> | 26 | #include <linux/socket.h> |
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
diff --git a/net/x25/x25_proc.c b/net/x25/x25_proc.c index 0a04e62e0e18..7ff373792324 100644 --- a/net/x25/x25_proc.c +++ b/net/x25/x25_proc.c | |||
@@ -25,49 +25,17 @@ | |||
25 | #include <net/x25.h> | 25 | #include <net/x25.h> |
26 | 26 | ||
27 | #ifdef CONFIG_PROC_FS | 27 | #ifdef CONFIG_PROC_FS |
28 | static __inline__ struct x25_route *x25_get_route_idx(loff_t pos) | ||
29 | { | ||
30 | struct list_head *route_entry; | ||
31 | struct x25_route *rt = NULL; | ||
32 | |||
33 | list_for_each(route_entry, &x25_route_list) { | ||
34 | rt = list_entry(route_entry, struct x25_route, node); | ||
35 | if (!pos--) | ||
36 | goto found; | ||
37 | } | ||
38 | rt = NULL; | ||
39 | found: | ||
40 | return rt; | ||
41 | } | ||
42 | 28 | ||
43 | static void *x25_seq_route_start(struct seq_file *seq, loff_t *pos) | 29 | static void *x25_seq_route_start(struct seq_file *seq, loff_t *pos) |
44 | __acquires(x25_route_list_lock) | 30 | __acquires(x25_route_list_lock) |
45 | { | 31 | { |
46 | loff_t l = *pos; | ||
47 | |||
48 | read_lock_bh(&x25_route_list_lock); | 32 | read_lock_bh(&x25_route_list_lock); |
49 | return l ? x25_get_route_idx(--l) : SEQ_START_TOKEN; | 33 | return seq_list_start_head(&x25_route_list, *pos); |
50 | } | 34 | } |
51 | 35 | ||
52 | static void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) | 36 | static void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) |
53 | { | 37 | { |
54 | struct x25_route *rt; | 38 | return seq_list_next(v, &x25_route_list, pos); |
55 | |||
56 | ++*pos; | ||
57 | if (v == SEQ_START_TOKEN) { | ||
58 | rt = NULL; | ||
59 | if (!list_empty(&x25_route_list)) | ||
60 | rt = list_entry(x25_route_list.next, | ||
61 | struct x25_route, node); | ||
62 | goto out; | ||
63 | } | ||
64 | rt = v; | ||
65 | if (rt->node.next != &x25_route_list) | ||
66 | rt = list_entry(rt->node.next, struct x25_route, node); | ||
67 | else | ||
68 | rt = NULL; | ||
69 | out: | ||
70 | return rt; | ||
71 | } | 39 | } |
72 | 40 | ||
73 | static void x25_seq_route_stop(struct seq_file *seq, void *v) | 41 | static void x25_seq_route_stop(struct seq_file *seq, void *v) |
@@ -78,9 +46,9 @@ static void x25_seq_route_stop(struct seq_file *seq, void *v) | |||
78 | 46 | ||
79 | static int x25_seq_route_show(struct seq_file *seq, void *v) | 47 | static int x25_seq_route_show(struct seq_file *seq, void *v) |
80 | { | 48 | { |
81 | struct x25_route *rt; | 49 | struct x25_route *rt = list_entry(v, struct x25_route, node); |
82 | 50 | ||
83 | if (v == SEQ_START_TOKEN) { | 51 | if (v == &x25_route_list) { |
84 | seq_puts(seq, "Address Digits Device\n"); | 52 | seq_puts(seq, "Address Digits Device\n"); |
85 | goto out; | 53 | goto out; |
86 | } | 54 | } |
@@ -93,40 +61,16 @@ out: | |||
93 | return 0; | 61 | return 0; |
94 | } | 62 | } |
95 | 63 | ||
96 | static __inline__ struct sock *x25_get_socket_idx(loff_t pos) | ||
97 | { | ||
98 | struct sock *s; | ||
99 | struct hlist_node *node; | ||
100 | |||
101 | sk_for_each(s, node, &x25_list) | ||
102 | if (!pos--) | ||
103 | goto found; | ||
104 | s = NULL; | ||
105 | found: | ||
106 | return s; | ||
107 | } | ||
108 | |||
109 | static void *x25_seq_socket_start(struct seq_file *seq, loff_t *pos) | 64 | static void *x25_seq_socket_start(struct seq_file *seq, loff_t *pos) |
110 | __acquires(x25_list_lock) | 65 | __acquires(x25_list_lock) |
111 | { | 66 | { |
112 | loff_t l = *pos; | ||
113 | |||
114 | read_lock_bh(&x25_list_lock); | 67 | read_lock_bh(&x25_list_lock); |
115 | return l ? x25_get_socket_idx(--l) : SEQ_START_TOKEN; | 68 | return seq_hlist_start_head(&x25_list, *pos); |
116 | } | 69 | } |
117 | 70 | ||
118 | static void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) | 71 | static void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) |
119 | { | 72 | { |
120 | struct sock *s; | 73 | return seq_hlist_next(v, &x25_list, pos); |
121 | |||
122 | ++*pos; | ||
123 | if (v == SEQ_START_TOKEN) { | ||
124 | s = sk_head(&x25_list); | ||
125 | goto out; | ||
126 | } | ||
127 | s = sk_next(v); | ||
128 | out: | ||
129 | return s; | ||
130 | } | 74 | } |
131 | 75 | ||
132 | static void x25_seq_socket_stop(struct seq_file *seq, void *v) | 76 | static void x25_seq_socket_stop(struct seq_file *seq, void *v) |
@@ -148,7 +92,7 @@ static int x25_seq_socket_show(struct seq_file *seq, void *v) | |||
148 | goto out; | 92 | goto out; |
149 | } | 93 | } |
150 | 94 | ||
151 | s = v; | 95 | s = sk_entry(v); |
152 | x25 = x25_sk(s); | 96 | x25 = x25_sk(s); |
153 | 97 | ||
154 | if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL) | 98 | if (!x25->neighbour || (dev = x25->neighbour->dev) == NULL) |
@@ -170,51 +114,16 @@ out: | |||
170 | return 0; | 114 | return 0; |
171 | } | 115 | } |
172 | 116 | ||
173 | static __inline__ struct x25_forward *x25_get_forward_idx(loff_t pos) | ||
174 | { | ||
175 | struct x25_forward *f; | ||
176 | struct list_head *entry; | ||
177 | |||
178 | list_for_each(entry, &x25_forward_list) { | ||
179 | f = list_entry(entry, struct x25_forward, node); | ||
180 | if (!pos--) | ||
181 | goto found; | ||
182 | } | ||
183 | |||
184 | f = NULL; | ||
185 | found: | ||
186 | return f; | ||
187 | } | ||
188 | |||
189 | static void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos) | 117 | static void *x25_seq_forward_start(struct seq_file *seq, loff_t *pos) |
190 | __acquires(x25_forward_list_lock) | 118 | __acquires(x25_forward_list_lock) |
191 | { | 119 | { |
192 | loff_t l = *pos; | ||
193 | |||
194 | read_lock_bh(&x25_forward_list_lock); | 120 | read_lock_bh(&x25_forward_list_lock); |
195 | return l ? x25_get_forward_idx(--l) : SEQ_START_TOKEN; | 121 | return seq_list_start_head(&x25_forward_list, *pos); |
196 | } | 122 | } |
197 | 123 | ||
198 | static void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos) | 124 | static void *x25_seq_forward_next(struct seq_file *seq, void *v, loff_t *pos) |
199 | { | 125 | { |
200 | struct x25_forward *f; | 126 | return seq_list_next(v, &x25_forward_list, pos); |
201 | |||
202 | ++*pos; | ||
203 | if (v == SEQ_START_TOKEN) { | ||
204 | f = NULL; | ||
205 | if (!list_empty(&x25_forward_list)) | ||
206 | f = list_entry(x25_forward_list.next, | ||
207 | struct x25_forward, node); | ||
208 | goto out; | ||
209 | } | ||
210 | f = v; | ||
211 | if (f->node.next != &x25_forward_list) | ||
212 | f = list_entry(f->node.next, struct x25_forward, node); | ||
213 | else | ||
214 | f = NULL; | ||
215 | out: | ||
216 | return f; | ||
217 | |||
218 | } | 127 | } |
219 | 128 | ||
220 | static void x25_seq_forward_stop(struct seq_file *seq, void *v) | 129 | static void x25_seq_forward_stop(struct seq_file *seq, void *v) |
@@ -225,9 +134,9 @@ static void x25_seq_forward_stop(struct seq_file *seq, void *v) | |||
225 | 134 | ||
226 | static int x25_seq_forward_show(struct seq_file *seq, void *v) | 135 | static int x25_seq_forward_show(struct seq_file *seq, void *v) |
227 | { | 136 | { |
228 | struct x25_forward *f; | 137 | struct x25_forward *f = list_entry(v, struct x25_forward, node); |
229 | 138 | ||
230 | if (v == SEQ_START_TOKEN) { | 139 | if (v == &x25_forward_list) { |
231 | seq_printf(seq, "lci dev1 dev2\n"); | 140 | seq_printf(seq, "lci dev1 dev2\n"); |
232 | goto out; | 141 | goto out; |
233 | } | 142 | } |
@@ -236,7 +145,6 @@ static int x25_seq_forward_show(struct seq_file *seq, void *v) | |||
236 | 145 | ||
237 | seq_printf(seq, "%d %-10s %-10s\n", | 146 | seq_printf(seq, "%d %-10s %-10s\n", |
238 | f->lci, f->dev1->name, f->dev2->name); | 147 | f->lci, f->dev1->name, f->dev2->name); |
239 | |||
240 | out: | 148 | out: |
241 | return 0; | 149 | return 0; |
242 | } | 150 | } |
diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c index 2c999ccf504a..97d77c532d8c 100644 --- a/net/x25/x25_route.c +++ b/net/x25/x25_route.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/if_arp.h> | 20 | #include <linux/if_arp.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/slab.h> | ||
22 | #include <net/x25.h> | 23 | #include <net/x25.h> |
23 | 24 | ||
24 | LIST_HEAD(x25_route_list); | 25 | LIST_HEAD(x25_route_list); |
@@ -136,8 +137,10 @@ struct net_device *x25_dev_get(char *devname) | |||
136 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) | 137 | #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE) |
137 | && dev->type != ARPHRD_ETHER | 138 | && dev->type != ARPHRD_ETHER |
138 | #endif | 139 | #endif |
139 | ))) | 140 | ))){ |
140 | dev_put(dev); | 141 | dev_put(dev); |
142 | dev = NULL; | ||
143 | } | ||
141 | 144 | ||
142 | return dev; | 145 | return dev; |
143 | } | 146 | } |
@@ -190,7 +193,7 @@ int x25_route_ioctl(unsigned int cmd, void __user *arg) | |||
190 | goto out; | 193 | goto out; |
191 | 194 | ||
192 | rc = -EINVAL; | 195 | rc = -EINVAL; |
193 | if (rt.sigdigits < 0 || rt.sigdigits > 15) | 196 | if (rt.sigdigits > 15) |
194 | goto out; | 197 | goto out; |
195 | 198 | ||
196 | dev = x25_dev_get(rt.device); | 199 | dev = x25_dev_get(rt.device); |
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 511a5986af3e..dc20cf12f39b 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * restriction on response. | 23 | * restriction on response. |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/slab.h> | ||
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
27 | #include <linux/string.h> | 28 | #include <linux/string.h> |
28 | #include <linux/skbuff.h> | 29 | #include <linux/skbuff.h> |
@@ -225,6 +226,12 @@ void x25_write_internal(struct sock *sk, int frametype) | |||
225 | break; | 226 | break; |
226 | 227 | ||
227 | case X25_CLEAR_REQUEST: | 228 | case X25_CLEAR_REQUEST: |
229 | dptr = skb_put(skb, 3); | ||
230 | *dptr++ = frametype; | ||
231 | *dptr++ = x25->causediag.cause; | ||
232 | *dptr++ = x25->causediag.diagnostic; | ||
233 | break; | ||
234 | |||
228 | case X25_RESET_REQUEST: | 235 | case X25_RESET_REQUEST: |
229 | dptr = skb_put(skb, 3); | 236 | dptr = skb_put(skb, 3); |
230 | *dptr++ = frametype; | 237 | *dptr++ = frametype; |