diff options
-rw-r--r-- | include/net/udp.h | 5 | ||||
-rw-r--r-- | net/ipv4/udp.c | 30 | ||||
-rw-r--r-- | net/ipv6/udp.c | 118 |
3 files changed, 32 insertions, 121 deletions
diff --git a/include/net/udp.h b/include/net/udp.h index eac69ff0582c..1548d68d45da 100644 --- a/include/net/udp.h +++ b/include/net/udp.h | |||
@@ -134,6 +134,11 @@ extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); | |||
134 | extern int udp_disconnect(struct sock *sk, int flags); | 134 | extern int udp_disconnect(struct sock *sk, int flags); |
135 | extern unsigned int udp_poll(struct file *file, struct socket *sock, | 135 | extern unsigned int udp_poll(struct file *file, struct socket *sock, |
136 | poll_table *wait); | 136 | poll_table *wait); |
137 | extern int udp_lib_getsockopt(struct sock *sk, int level, int optname, | ||
138 | char __user *optval, int __user *optlen); | ||
139 | extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, | ||
140 | char __user *optval, int optlen, | ||
141 | int (*push_pending_frames)(struct sock *)); | ||
137 | 142 | ||
138 | DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); | 143 | DECLARE_SNMP_STAT(struct udp_mib, udp_statistics); |
139 | /* | 144 | /* |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 1807a30694d9..035915fc9ed3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -448,8 +448,9 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, | |||
448 | /* | 448 | /* |
449 | * Push out all pending data as one UDP datagram. Socket is locked. | 449 | * Push out all pending data as one UDP datagram. Socket is locked. |
450 | */ | 450 | */ |
451 | static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) | 451 | static int udp_push_pending_frames(struct sock *sk) |
452 | { | 452 | { |
453 | struct udp_sock *up = udp_sk(sk); | ||
453 | struct inet_sock *inet = inet_sk(sk); | 454 | struct inet_sock *inet = inet_sk(sk); |
454 | struct flowi *fl = &inet->cork.fl; | 455 | struct flowi *fl = &inet->cork.fl; |
455 | struct sk_buff *skb; | 456 | struct sk_buff *skb; |
@@ -673,7 +674,7 @@ do_append_data: | |||
673 | if (err) | 674 | if (err) |
674 | udp_flush_pending_frames(sk); | 675 | udp_flush_pending_frames(sk); |
675 | else if (!corkreq) | 676 | else if (!corkreq) |
676 | err = udp_push_pending_frames(sk, up); | 677 | err = udp_push_pending_frames(sk); |
677 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) | 678 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) |
678 | up->pending = 0; | 679 | up->pending = 0; |
679 | release_sock(sk); | 680 | release_sock(sk); |
@@ -746,7 +747,7 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, | |||
746 | 747 | ||
747 | up->len += size; | 748 | up->len += size; |
748 | if (!(up->corkflag || (flags&MSG_MORE))) | 749 | if (!(up->corkflag || (flags&MSG_MORE))) |
749 | ret = udp_push_pending_frames(sk, up); | 750 | ret = udp_push_pending_frames(sk); |
750 | if (!ret) | 751 | if (!ret) |
751 | ret = size; | 752 | ret = size; |
752 | out: | 753 | out: |
@@ -1299,8 +1300,9 @@ int udp_destroy_sock(struct sock *sk) | |||
1299 | /* | 1300 | /* |
1300 | * Socket option code for UDP | 1301 | * Socket option code for UDP |
1301 | */ | 1302 | */ |
1302 | static int do_udp_setsockopt(struct sock *sk, int level, int optname, | 1303 | int udp_lib_setsockopt(struct sock *sk, int level, int optname, |
1303 | char __user *optval, int optlen) | 1304 | char __user *optval, int optlen, |
1305 | int (*push_pending_frames)(struct sock *)) | ||
1304 | { | 1306 | { |
1305 | struct udp_sock *up = udp_sk(sk); | 1307 | struct udp_sock *up = udp_sk(sk); |
1306 | int val; | 1308 | int val; |
@@ -1319,7 +1321,7 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname, | |||
1319 | } else { | 1321 | } else { |
1320 | up->corkflag = 0; | 1322 | up->corkflag = 0; |
1321 | lock_sock(sk); | 1323 | lock_sock(sk); |
1322 | udp_push_pending_frames(sk, up); | 1324 | (*push_pending_frames)(sk); |
1323 | release_sock(sk); | 1325 | release_sock(sk); |
1324 | } | 1326 | } |
1325 | break; | 1327 | break; |
@@ -1375,7 +1377,8 @@ int udp_setsockopt(struct sock *sk, int level, int optname, | |||
1375 | char __user *optval, int optlen) | 1377 | char __user *optval, int optlen) |
1376 | { | 1378 | { |
1377 | if (level == SOL_UDP || level == SOL_UDPLITE) | 1379 | if (level == SOL_UDP || level == SOL_UDPLITE) |
1378 | return do_udp_setsockopt(sk, level, optname, optval, optlen); | 1380 | return udp_lib_setsockopt(sk, level, optname, optval, optlen, |
1381 | udp_push_pending_frames); | ||
1379 | return ip_setsockopt(sk, level, optname, optval, optlen); | 1382 | return ip_setsockopt(sk, level, optname, optval, optlen); |
1380 | } | 1383 | } |
1381 | 1384 | ||
@@ -1384,13 +1387,14 @@ int compat_udp_setsockopt(struct sock *sk, int level, int optname, | |||
1384 | char __user *optval, int optlen) | 1387 | char __user *optval, int optlen) |
1385 | { | 1388 | { |
1386 | if (level == SOL_UDP || level == SOL_UDPLITE) | 1389 | if (level == SOL_UDP || level == SOL_UDPLITE) |
1387 | return do_udp_setsockopt(sk, level, optname, optval, optlen); | 1390 | return udp_lib_setsockopt(sk, level, optname, optval, optlen, |
1391 | udp_push_pending_frames); | ||
1388 | return compat_ip_setsockopt(sk, level, optname, optval, optlen); | 1392 | return compat_ip_setsockopt(sk, level, optname, optval, optlen); |
1389 | } | 1393 | } |
1390 | #endif | 1394 | #endif |
1391 | 1395 | ||
1392 | static int do_udp_getsockopt(struct sock *sk, int level, int optname, | 1396 | int udp_lib_getsockopt(struct sock *sk, int level, int optname, |
1393 | char __user *optval, int __user *optlen) | 1397 | char __user *optval, int __user *optlen) |
1394 | { | 1398 | { |
1395 | struct udp_sock *up = udp_sk(sk); | 1399 | struct udp_sock *up = udp_sk(sk); |
1396 | int val, len; | 1400 | int val, len; |
@@ -1437,7 +1441,7 @@ int udp_getsockopt(struct sock *sk, int level, int optname, | |||
1437 | char __user *optval, int __user *optlen) | 1441 | char __user *optval, int __user *optlen) |
1438 | { | 1442 | { |
1439 | if (level == SOL_UDP || level == SOL_UDPLITE) | 1443 | if (level == SOL_UDP || level == SOL_UDPLITE) |
1440 | return do_udp_getsockopt(sk, level, optname, optval, optlen); | 1444 | return udp_lib_getsockopt(sk, level, optname, optval, optlen); |
1441 | return ip_getsockopt(sk, level, optname, optval, optlen); | 1445 | return ip_getsockopt(sk, level, optname, optval, optlen); |
1442 | } | 1446 | } |
1443 | 1447 | ||
@@ -1446,7 +1450,7 @@ int compat_udp_getsockopt(struct sock *sk, int level, int optname, | |||
1446 | char __user *optval, int __user *optlen) | 1450 | char __user *optval, int __user *optlen) |
1447 | { | 1451 | { |
1448 | if (level == SOL_UDP || level == SOL_UDPLITE) | 1452 | if (level == SOL_UDP || level == SOL_UDPLITE) |
1449 | return do_udp_getsockopt(sk, level, optname, optval, optlen); | 1453 | return udp_lib_getsockopt(sk, level, optname, optval, optlen); |
1450 | return compat_ip_getsockopt(sk, level, optname, optval, optlen); | 1454 | return compat_ip_getsockopt(sk, level, optname, optval, optlen); |
1451 | } | 1455 | } |
1452 | #endif | 1456 | #endif |
@@ -1716,6 +1720,8 @@ EXPORT_SYMBOL(udp_ioctl); | |||
1716 | EXPORT_SYMBOL(udp_get_port); | 1720 | EXPORT_SYMBOL(udp_get_port); |
1717 | EXPORT_SYMBOL(udp_prot); | 1721 | EXPORT_SYMBOL(udp_prot); |
1718 | EXPORT_SYMBOL(udp_sendmsg); | 1722 | EXPORT_SYMBOL(udp_sendmsg); |
1723 | EXPORT_SYMBOL(udp_lib_getsockopt); | ||
1724 | EXPORT_SYMBOL(udp_lib_setsockopt); | ||
1719 | EXPORT_SYMBOL(udp_poll); | 1725 | EXPORT_SYMBOL(udp_poll); |
1720 | 1726 | ||
1721 | #ifdef CONFIG_PROC_FS | 1727 | #ifdef CONFIG_PROC_FS |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b3ea8af50a9b..f52a5c3cc0a3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -505,10 +505,11 @@ static void udp_v6_flush_pending_frames(struct sock *sk) | |||
505 | * Sending | 505 | * Sending |
506 | */ | 506 | */ |
507 | 507 | ||
508 | static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) | 508 | static int udp_v6_push_pending_frames(struct sock *sk) |
509 | { | 509 | { |
510 | struct sk_buff *skb; | 510 | struct sk_buff *skb; |
511 | struct udphdr *uh; | 511 | struct udphdr *uh; |
512 | struct udp_sock *up = udp_sk(sk); | ||
512 | struct inet_sock *inet = inet_sk(sk); | 513 | struct inet_sock *inet = inet_sk(sk); |
513 | struct flowi *fl = &inet->cork.fl; | 514 | struct flowi *fl = &inet->cork.fl; |
514 | int err = 0; | 515 | int err = 0; |
@@ -782,7 +783,7 @@ do_append_data: | |||
782 | if (err) | 783 | if (err) |
783 | udp_v6_flush_pending_frames(sk); | 784 | udp_v6_flush_pending_frames(sk); |
784 | else if (!corkreq) | 785 | else if (!corkreq) |
785 | err = udp_v6_push_pending_frames(sk, up); | 786 | err = udp_v6_push_pending_frames(sk); |
786 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) | 787 | else if (unlikely(skb_queue_empty(&sk->sk_write_queue))) |
787 | up->pending = 0; | 788 | up->pending = 0; |
788 | 789 | ||
@@ -844,72 +845,12 @@ int udpv6_destroy_sock(struct sock *sk) | |||
844 | /* | 845 | /* |
845 | * Socket option code for UDP | 846 | * Socket option code for UDP |
846 | */ | 847 | */ |
847 | static int do_udpv6_setsockopt(struct sock *sk, int level, int optname, | ||
848 | char __user *optval, int optlen) | ||
849 | { | ||
850 | struct udp_sock *up = udp_sk(sk); | ||
851 | int val; | ||
852 | int err = 0; | ||
853 | |||
854 | if(optlen<sizeof(int)) | ||
855 | return -EINVAL; | ||
856 | |||
857 | if (get_user(val, (int __user *)optval)) | ||
858 | return -EFAULT; | ||
859 | |||
860 | switch(optname) { | ||
861 | case UDP_CORK: | ||
862 | if (val != 0) { | ||
863 | up->corkflag = 1; | ||
864 | } else { | ||
865 | up->corkflag = 0; | ||
866 | lock_sock(sk); | ||
867 | udp_v6_push_pending_frames(sk, up); | ||
868 | release_sock(sk); | ||
869 | } | ||
870 | break; | ||
871 | case UDP_ENCAP: | ||
872 | switch (val) { | ||
873 | case 0: | ||
874 | up->encap_type = val; | ||
875 | break; | ||
876 | default: | ||
877 | err = -ENOPROTOOPT; | ||
878 | break; | ||
879 | } | ||
880 | break; | ||
881 | |||
882 | case UDPLITE_SEND_CSCOV: | ||
883 | if (!up->pcflag) /* Disable the option on UDP sockets */ | ||
884 | return -ENOPROTOOPT; | ||
885 | if (val != 0 && val < 8) /* Illegal coverage: use default (8) */ | ||
886 | val = 8; | ||
887 | up->pcslen = val; | ||
888 | up->pcflag |= UDPLITE_SEND_CC; | ||
889 | break; | ||
890 | |||
891 | case UDPLITE_RECV_CSCOV: | ||
892 | if (!up->pcflag) /* Disable the option on UDP sockets */ | ||
893 | return -ENOPROTOOPT; | ||
894 | if (val != 0 && val < 8) /* Avoid silly minimal values. */ | ||
895 | val = 8; | ||
896 | up->pcrlen = val; | ||
897 | up->pcflag |= UDPLITE_RECV_CC; | ||
898 | break; | ||
899 | |||
900 | default: | ||
901 | err = -ENOPROTOOPT; | ||
902 | break; | ||
903 | }; | ||
904 | |||
905 | return err; | ||
906 | } | ||
907 | |||
908 | int udpv6_setsockopt(struct sock *sk, int level, int optname, | 848 | int udpv6_setsockopt(struct sock *sk, int level, int optname, |
909 | char __user *optval, int optlen) | 849 | char __user *optval, int optlen) |
910 | { | 850 | { |
911 | if (level == SOL_UDP || level == SOL_UDPLITE) | 851 | if (level == SOL_UDP || level == SOL_UDPLITE) |
912 | return do_udpv6_setsockopt(sk, level, optname, optval, optlen); | 852 | return udp_lib_setsockopt(sk, level, optname, optval, optlen, |
853 | udp_v6_push_pending_frames); | ||
913 | return ipv6_setsockopt(sk, level, optname, optval, optlen); | 854 | return ipv6_setsockopt(sk, level, optname, optval, optlen); |
914 | } | 855 | } |
915 | 856 | ||
@@ -918,58 +859,17 @@ int compat_udpv6_setsockopt(struct sock *sk, int level, int optname, | |||
918 | char __user *optval, int optlen) | 859 | char __user *optval, int optlen) |
919 | { | 860 | { |
920 | if (level == SOL_UDP || level == SOL_UDPLITE) | 861 | if (level == SOL_UDP || level == SOL_UDPLITE) |
921 | return do_udpv6_setsockopt(sk, level, optname, optval, optlen); | 862 | return udp_lib_setsockopt(sk, level, optname, optval, optlen, |
863 | udp_v6_push_pending_frames); | ||
922 | return compat_ipv6_setsockopt(sk, level, optname, optval, optlen); | 864 | return compat_ipv6_setsockopt(sk, level, optname, optval, optlen); |
923 | } | 865 | } |
924 | #endif | 866 | #endif |
925 | 867 | ||
926 | static int do_udpv6_getsockopt(struct sock *sk, int level, int optname, | ||
927 | char __user *optval, int __user *optlen) | ||
928 | { | ||
929 | struct udp_sock *up = udp_sk(sk); | ||
930 | int val, len; | ||
931 | |||
932 | if(get_user(len,optlen)) | ||
933 | return -EFAULT; | ||
934 | |||
935 | len = min_t(unsigned int, len, sizeof(int)); | ||
936 | |||
937 | if(len < 0) | ||
938 | return -EINVAL; | ||
939 | |||
940 | switch(optname) { | ||
941 | case UDP_CORK: | ||
942 | val = up->corkflag; | ||
943 | break; | ||
944 | |||
945 | case UDP_ENCAP: | ||
946 | val = up->encap_type; | ||
947 | break; | ||
948 | |||
949 | case UDPLITE_SEND_CSCOV: | ||
950 | val = up->pcslen; | ||
951 | break; | ||
952 | |||
953 | case UDPLITE_RECV_CSCOV: | ||
954 | val = up->pcrlen; | ||
955 | break; | ||
956 | |||
957 | default: | ||
958 | return -ENOPROTOOPT; | ||
959 | }; | ||
960 | |||
961 | if(put_user(len, optlen)) | ||
962 | return -EFAULT; | ||
963 | if(copy_to_user(optval, &val,len)) | ||
964 | return -EFAULT; | ||
965 | return 0; | ||
966 | } | ||
967 | |||
968 | int udpv6_getsockopt(struct sock *sk, int level, int optname, | 868 | int udpv6_getsockopt(struct sock *sk, int level, int optname, |
969 | char __user *optval, int __user *optlen) | 869 | char __user *optval, int __user *optlen) |
970 | { | 870 | { |
971 | if (level == SOL_UDP || level == SOL_UDPLITE) | 871 | if (level == SOL_UDP || level == SOL_UDPLITE) |
972 | return do_udpv6_getsockopt(sk, level, optname, optval, optlen); | 872 | return udp_lib_getsockopt(sk, level, optname, optval, optlen); |
973 | return ipv6_getsockopt(sk, level, optname, optval, optlen); | 873 | return ipv6_getsockopt(sk, level, optname, optval, optlen); |
974 | } | 874 | } |
975 | 875 | ||
@@ -978,7 +878,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, | |||
978 | char __user *optval, int __user *optlen) | 878 | char __user *optval, int __user *optlen) |
979 | { | 879 | { |
980 | if (level == SOL_UDP || level == SOL_UDPLITE) | 880 | if (level == SOL_UDP || level == SOL_UDPLITE) |
981 | return do_udpv6_getsockopt(sk, level, optname, optval, optlen); | 881 | return udp_lib_getsockopt(sk, level, optname, optval, optlen); |
982 | return compat_ipv6_getsockopt(sk, level, optname, optval, optlen); | 882 | return compat_ipv6_getsockopt(sk, level, optname, optval, optlen); |
983 | } | 883 | } |
984 | #endif | 884 | #endif |