aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c118
1 files changed, 9 insertions, 109 deletions
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
508static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) 508static 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 */
847static 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
908int udpv6_setsockopt(struct sock *sk, int level, int optname, 848int 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
926static 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
968int udpv6_getsockopt(struct sock *sk, int level, int optname, 868int 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