Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a7991268 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ip-recvfragsize-cmsg'



Willem de Bruijn says:

====================
ip: add RECVFRAGSIZE cmsg

On IP datagrams and raw sockets, when packets arrive fragmented,
expose the largest received fragment size through a new cmsg.

Protocols implemented on top of these sockets may use this, for
instance, to inform peers to lower MSS on platforms that silently
allow send calls to exceed PMTU and cause fragmentation.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1b99e5e8 dbd1759e
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -229,8 +229,9 @@ struct ipv6_pinfo {
                                rxflow:1,
				rxtclass:1,
				rxpmtu:1,
				rxorigdstaddr:1;
				/* 2 bits hole */
				rxorigdstaddr:1,
				recvfragsize:1;
				/* 1 bits hole */
		} bits;
		__u16		all;
	} rxopt;
+1 −0
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ struct inet_sock {
#define IP_CMSG_PASSSEC		BIT(5)
#define IP_CMSG_ORIGDSTADDR	BIT(6)
#define IP_CMSG_CHECKSUM	BIT(7)
#define IP_CMSG_RECVFRAGSIZE	BIT(8)

/**
 * sk_to_full_sk - Access to a full socket
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ struct in_addr {
#define IP_NODEFRAG     22
#define IP_CHECKSUM	23
#define IP_BIND_ADDRESS_NO_PORT	24
#define IP_RECVFRAGSIZE	25

/* IP_MTU_DISCOVER values */
#define IP_PMTUDISC_DONT		0	/* Never send DF frames */
+1 −0
Original line number Diff line number Diff line
@@ -283,6 +283,7 @@ struct in6_flowlabel_req {
#define IPV6_RECVORIGDSTADDR    IPV6_ORIGDSTADDR
#define IPV6_TRANSPARENT        75
#define IPV6_UNICAST_IF         76
#define IPV6_RECVFRAGSIZE	77

/*
 * Multicast Routing:
+26 −0
Original line number Diff line number Diff line
@@ -97,6 +97,17 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb)
	put_cmsg(msg, SOL_IP, IP_RETOPTS, opt->optlen, opt->__data);
}

static void ip_cmsg_recv_fragsize(struct msghdr *msg, struct sk_buff *skb)
{
	int val;

	if (IPCB(skb)->frag_max_size == 0)
		return;

	val = IPCB(skb)->frag_max_size;
	put_cmsg(msg, SOL_IP, IP_RECVFRAGSIZE, sizeof(val), &val);
}

static void ip_cmsg_recv_checksum(struct msghdr *msg, struct sk_buff *skb,
				  int tlen, int offset)
{
@@ -218,6 +229,9 @@ void ip_cmsg_recv_offset(struct msghdr *msg, struct sk_buff *skb,

	if (flags & IP_CMSG_CHECKSUM)
		ip_cmsg_recv_checksum(msg, skb, tlen, offset);

	if (flags & IP_CMSG_RECVFRAGSIZE)
		ip_cmsg_recv_fragsize(msg, skb);
}
EXPORT_SYMBOL(ip_cmsg_recv_offset);

@@ -614,6 +628,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
	case IP_MULTICAST_LOOP:
	case IP_RECVORIGDSTADDR:
	case IP_CHECKSUM:
	case IP_RECVFRAGSIZE:
		if (optlen >= sizeof(int)) {
			if (get_user(val, (int __user *) optval))
				return -EFAULT;
@@ -726,6 +741,14 @@ static int do_ip_setsockopt(struct sock *sk, int level,
			}
		}
		break;
	case IP_RECVFRAGSIZE:
		if (sk->sk_type != SOCK_RAW && sk->sk_type != SOCK_DGRAM)
			goto e_inval;
		if (val)
			inet->cmsg_flags |= IP_CMSG_RECVFRAGSIZE;
		else
			inet->cmsg_flags &= ~IP_CMSG_RECVFRAGSIZE;
		break;
	case IP_TOS:	/* This sets both TOS and Precedence */
		if (sk->sk_type == SOCK_STREAM) {
			val &= ~INET_ECN_MASK;
@@ -1357,6 +1380,9 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname,
	case IP_CHECKSUM:
		val = (inet->cmsg_flags & IP_CMSG_CHECKSUM) != 0;
		break;
	case IP_RECVFRAGSIZE:
		val = (inet->cmsg_flags & IP_CMSG_RECVFRAGSIZE) != 0;
		break;
	case IP_TOS:
		val = inet->tos;
		break;
Loading