Consolidate cases for IPV6_2292HOPOPTS, IPV6_HOPOPTS, IPV6_2292DSTOPTS, IPV6_DSTOPTS, and IPV6_RTHDRDSTOPTS. Most of the work and verifications are common for all these case, individual differences in processing can be implemented with an embedded switch statement. --- net/ipv6/datagram.c | 66 ++++++++++++++++++----------------------------------- 1 file changed, 22 insertions(+), 44 deletions(-)
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index ee4a4e5..f4742db 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -842,49 +842,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, case IPV6_2292HOPOPTS: case IPV6_HOPOPTS: - if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { - err = -EINVAL; - goto exit_f; - } - - hdr = (struct ipv6_opt_hdr *)CMSG_DATA(cmsg); - len = ((hdr->hdrlen + 1) << 3); - if (cmsg->cmsg_len < CMSG_LEN(len)) { - err = -EINVAL; - goto exit_f; - } - if (!ns_capable(net->user_ns, CAP_NET_RAW)) { - err = -EPERM; - goto exit_f; - } - opt->opt_nflen += len; - opt->hopopt = hdr; - break; - case IPV6_2292DSTOPTS: - if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { - err = -EINVAL; - goto exit_f; - } - - hdr = (struct ipv6_opt_hdr *)CMSG_DATA(cmsg); - len = ((hdr->hdrlen + 1) << 3); - if (cmsg->cmsg_len < CMSG_LEN(len)) { - err = -EINVAL; - goto exit_f; - } - if (!ns_capable(net->user_ns, CAP_NET_RAW)) { - err = -EPERM; - goto exit_f; - } - if (opt->dst1opt) { - err = -EINVAL; - goto exit_f; - } - opt->opt_flen += len; - opt->dst1opt = hdr; - break; - case IPV6_DSTOPTS: case IPV6_RTHDRDSTOPTS: if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { @@ -902,13 +860,33 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, err = -EPERM; goto exit_f; } - if (cmsg->cmsg_type == IPV6_DSTOPTS) { + + switch (cmsg->cmsg_type) { + case IPV6_2292HOPOPTS: + case IPV6_HOPOPTS: + if (opt->hopopt) { + err = -EINVAL; + goto exit_f; + } + opt->opt_nflen += len; + opt->hopopt = hdr; + break; + case IPV6_2292DSTOPTS: + if (opt->dst1opt) { + err = -EINVAL; + goto exit_f; + } + /* Fallthrough */ + case IPV6_DSTOPTS: opt->opt_flen += len; opt->dst1opt = hdr; - } else { + break; + case IPV6_RTHDRDSTOPTS: opt->opt_nflen += len; opt->dst0opt = hdr; + break; } + break; case IPV6_2292RTHDR: -- 2.7.4