[UDP(-Lite)]: consolidate v4 and v6 get|setsockopt code
This patch consolidates set/getsockopt code between UDP(-Lite) v4 and 6. The justification is that UDP(-Lite) is a transport-layer protocol and therefore the socket option code (at least in theory) should be AF-independent. Furthermore, there is the following code reduplication: * do_udp{,v6}_getsockopt is 100% identical between v4 and v6 * do_udp{,v6}_setsockopt is identical up to the following differerence --v4 in contrast to v4 additionally allows the experimental encapsulation types UDP_ENCAP_ESPINUDP and UDP_ENCAP_ESPINUDP_NON_IKE --the remainder is identical between v4 and v6 I believe that this difference is of little relevance. The advantages in not duplicating twice almost completely identical code. The patch further simplifies the interface of udp{,v6}_push_pending_frames, since for the second argument (struct udp_sock *up) it always holds that up = udp_sk(sk); where sk is the first function argument. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e3703b3de1
commit
4c0a6cb0db
|
@ -134,6 +134,11 @@ extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
|
|||
extern int udp_disconnect(struct sock *sk, int flags);
|
||||
extern unsigned int udp_poll(struct file *file, struct socket *sock,
|
||||
poll_table *wait);
|
||||
extern int udp_lib_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen);
|
||||
extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen,
|
||||
int (*push_pending_frames)(struct sock *));
|
||||
|
||||
DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
|
||||
/*
|
||||
|
|
|
@ -448,8 +448,9 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
|
|||
/*
|
||||
* Push out all pending data as one UDP datagram. Socket is locked.
|
||||
*/
|
||||
static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up)
|
||||
static int udp_push_pending_frames(struct sock *sk)
|
||||
{
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct flowi *fl = &inet->cork.fl;
|
||||
struct sk_buff *skb;
|
||||
|
@ -673,7 +674,7 @@ do_append_data:
|
|||
if (err)
|
||||
udp_flush_pending_frames(sk);
|
||||
else if (!corkreq)
|
||||
err = udp_push_pending_frames(sk, up);
|
||||
err = udp_push_pending_frames(sk);
|
||||
else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
|
||||
up->pending = 0;
|
||||
release_sock(sk);
|
||||
|
@ -746,7 +747,7 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,
|
|||
|
||||
up->len += size;
|
||||
if (!(up->corkflag || (flags&MSG_MORE)))
|
||||
ret = udp_push_pending_frames(sk, up);
|
||||
ret = udp_push_pending_frames(sk);
|
||||
if (!ret)
|
||||
ret = size;
|
||||
out:
|
||||
|
@ -1299,8 +1300,9 @@ int udp_destroy_sock(struct sock *sk)
|
|||
/*
|
||||
* Socket option code for UDP
|
||||
*/
|
||||
static int do_udp_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen)
|
||||
int udp_lib_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen,
|
||||
int (*push_pending_frames)(struct sock *))
|
||||
{
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
int val;
|
||||
|
@ -1319,7 +1321,7 @@ static int do_udp_setsockopt(struct sock *sk, int level, int optname,
|
|||
} else {
|
||||
up->corkflag = 0;
|
||||
lock_sock(sk);
|
||||
udp_push_pending_frames(sk, up);
|
||||
(*push_pending_frames)(sk);
|
||||
release_sock(sk);
|
||||
}
|
||||
break;
|
||||
|
@ -1375,7 +1377,8 @@ int udp_setsockopt(struct sock *sk, int level, int optname,
|
|||
char __user *optval, int optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udp_setsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
|
||||
udp_push_pending_frames);
|
||||
return ip_setsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
|
@ -1384,13 +1387,14 @@ int compat_udp_setsockopt(struct sock *sk, int level, int optname,
|
|||
char __user *optval, int optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udp_setsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
|
||||
udp_push_pending_frames);
|
||||
return compat_ip_setsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_udp_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
int udp_lib_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
int val, len;
|
||||
|
@ -1437,7 +1441,7 @@ int udp_getsockopt(struct sock *sk, int level, int optname,
|
|||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udp_getsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
|
||||
return ip_getsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
|
@ -1446,7 +1450,7 @@ int compat_udp_getsockopt(struct sock *sk, int level, int optname,
|
|||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udp_getsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
|
||||
return compat_ip_getsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
#endif
|
||||
|
@ -1716,6 +1720,8 @@ EXPORT_SYMBOL(udp_ioctl);
|
|||
EXPORT_SYMBOL(udp_get_port);
|
||||
EXPORT_SYMBOL(udp_prot);
|
||||
EXPORT_SYMBOL(udp_sendmsg);
|
||||
EXPORT_SYMBOL(udp_lib_getsockopt);
|
||||
EXPORT_SYMBOL(udp_lib_setsockopt);
|
||||
EXPORT_SYMBOL(udp_poll);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
|
|
118
net/ipv6/udp.c
118
net/ipv6/udp.c
|
@ -505,10 +505,11 @@ static void udp_v6_flush_pending_frames(struct sock *sk)
|
|||
* Sending
|
||||
*/
|
||||
|
||||
static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up)
|
||||
static int udp_v6_push_pending_frames(struct sock *sk)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct udphdr *uh;
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct flowi *fl = &inet->cork.fl;
|
||||
int err = 0;
|
||||
|
@ -782,7 +783,7 @@ do_append_data:
|
|||
if (err)
|
||||
udp_v6_flush_pending_frames(sk);
|
||||
else if (!corkreq)
|
||||
err = udp_v6_push_pending_frames(sk, up);
|
||||
err = udp_v6_push_pending_frames(sk);
|
||||
else if (unlikely(skb_queue_empty(&sk->sk_write_queue)))
|
||||
up->pending = 0;
|
||||
|
||||
|
@ -844,72 +845,12 @@ int udpv6_destroy_sock(struct sock *sk)
|
|||
/*
|
||||
* Socket option code for UDP
|
||||
*/
|
||||
static int do_udpv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
int val;
|
||||
int err = 0;
|
||||
|
||||
if(optlen<sizeof(int))
|
||||
return -EINVAL;
|
||||
|
||||
if (get_user(val, (int __user *)optval))
|
||||
return -EFAULT;
|
||||
|
||||
switch(optname) {
|
||||
case UDP_CORK:
|
||||
if (val != 0) {
|
||||
up->corkflag = 1;
|
||||
} else {
|
||||
up->corkflag = 0;
|
||||
lock_sock(sk);
|
||||
udp_v6_push_pending_frames(sk, up);
|
||||
release_sock(sk);
|
||||
}
|
||||
break;
|
||||
case UDP_ENCAP:
|
||||
switch (val) {
|
||||
case 0:
|
||||
up->encap_type = val;
|
||||
break;
|
||||
default:
|
||||
err = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case UDPLITE_SEND_CSCOV:
|
||||
if (!up->pcflag) /* Disable the option on UDP sockets */
|
||||
return -ENOPROTOOPT;
|
||||
if (val != 0 && val < 8) /* Illegal coverage: use default (8) */
|
||||
val = 8;
|
||||
up->pcslen = val;
|
||||
up->pcflag |= UDPLITE_SEND_CC;
|
||||
break;
|
||||
|
||||
case UDPLITE_RECV_CSCOV:
|
||||
if (!up->pcflag) /* Disable the option on UDP sockets */
|
||||
return -ENOPROTOOPT;
|
||||
if (val != 0 && val < 8) /* Avoid silly minimal values. */
|
||||
val = 8;
|
||||
up->pcrlen = val;
|
||||
up->pcflag |= UDPLITE_RECV_CC;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = -ENOPROTOOPT;
|
||||
break;
|
||||
};
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int udpv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
|
||||
udp_v6_push_pending_frames);
|
||||
return ipv6_setsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
|
@ -918,58 +859,17 @@ int compat_udpv6_setsockopt(struct sock *sk, int level, int optname,
|
|||
char __user *optval, int optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udpv6_setsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_setsockopt(sk, level, optname, optval, optlen,
|
||||
udp_v6_push_pending_frames);
|
||||
return compat_ipv6_setsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int do_udpv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
struct udp_sock *up = udp_sk(sk);
|
||||
int val, len;
|
||||
|
||||
if(get_user(len,optlen))
|
||||
return -EFAULT;
|
||||
|
||||
len = min_t(unsigned int, len, sizeof(int));
|
||||
|
||||
if(len < 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch(optname) {
|
||||
case UDP_CORK:
|
||||
val = up->corkflag;
|
||||
break;
|
||||
|
||||
case UDP_ENCAP:
|
||||
val = up->encap_type;
|
||||
break;
|
||||
|
||||
case UDPLITE_SEND_CSCOV:
|
||||
val = up->pcslen;
|
||||
break;
|
||||
|
||||
case UDPLITE_RECV_CSCOV:
|
||||
val = up->pcrlen;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
};
|
||||
|
||||
if(put_user(len, optlen))
|
||||
return -EFAULT;
|
||||
if(copy_to_user(optval, &val,len))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udpv6_getsockopt(struct sock *sk, int level, int optname,
|
||||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
|
||||
return ipv6_getsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
|
@ -978,7 +878,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
|
|||
char __user *optval, int __user *optlen)
|
||||
{
|
||||
if (level == SOL_UDP || level == SOL_UDPLITE)
|
||||
return do_udpv6_getsockopt(sk, level, optname, optval, optlen);
|
||||
return udp_lib_getsockopt(sk, level, optname, optval, optlen);
|
||||
return compat_ipv6_getsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue