Skip to content

Commit

Permalink
ipv6: add new struct ipcm6_cookie
Browse files Browse the repository at this point in the history
In the sendmsg function of UDP, raw, ICMP and l2tp sockets, we use local
variables like hlimits, tclass, opt and dontfrag and pass them to corresponding
functions like ip6_make_skb, ip6_append_data and xxx_push_pending_frames.
This is not a good practice and makes it hard to add new parameters.
This fix introduces a new struct ipcm6_cookie similar to ipcm_cookie in
ipv4 and include the above mentioned variables. And we only pass the
pointer to this structure to corresponding functions. This makes it easier
to add new parameters in the future and makes the function cleaner.

Signed-off-by: Wei Wang <weiwan@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
tracywwnj authored and davem330 committed May 3, 2016
1 parent 1d2077a commit 26879da
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 109 deletions.
18 changes: 12 additions & 6 deletions include/net/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ struct ipv6_fl_socklist {
struct rcu_head rcu;
};

struct ipcm6_cookie {
__s16 hlimit;
__s16 tclass;
__s8 dontfrag;
struct ipv6_txoptions *opt;
};

static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
{
struct ipv6_txoptions *opt;
Expand Down Expand Up @@ -863,9 +870,9 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr);
int ip6_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen, int hlimit,
int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6,
struct rt6_info *rt, unsigned int flags, int dontfrag,
void *from, int length, int transhdrlen,
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
struct rt6_info *rt, unsigned int flags,
const struct sockcm_cookie *sockc);

int ip6_push_pending_frames(struct sock *sk);
Expand All @@ -881,9 +888,8 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
int getfrag(void *from, char *to, int offset,
int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
int hlimit, int tclass, struct ipv6_txoptions *opt,
struct flowi6 *fl6, struct rt6_info *rt,
unsigned int flags, int dontfrag,
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
struct rt6_info *rt, unsigned int flags,
const struct sockcm_cookie *sockc);

static inline struct sk_buff *ip6_finish_skb(struct sock *sk)
Expand Down
3 changes: 1 addition & 2 deletions include/net/transp_v6.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
struct sk_buff *skb);

int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg,
struct flowi6 *fl6, struct ipv6_txoptions *opt,
int *hlimit, int *tclass, int *dontfrag,
struct flowi6 *fl6, struct ipcm6_cookie *ipc6,
struct sockcm_cookie *sockc);

void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
Expand Down
13 changes: 6 additions & 7 deletions net/ipv6/datagram.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,14 +727,13 @@ EXPORT_SYMBOL_GPL(ip6_datagram_recv_ctl);

int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
struct msghdr *msg, struct flowi6 *fl6,
struct ipv6_txoptions *opt,
int *hlimit, int *tclass, int *dontfrag,
struct sockcm_cookie *sockc)
struct ipcm6_cookie *ipc6, struct sockcm_cookie *sockc)
{
struct in6_pktinfo *src_info;
struct cmsghdr *cmsg;
struct ipv6_rt_hdr *rthdr;
struct ipv6_opt_hdr *hdr;
struct ipv6_txoptions *opt = ipc6->opt;
int len;
int err = 0;

Expand Down Expand Up @@ -953,8 +952,8 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
goto exit_f;
}

*hlimit = *(int *)CMSG_DATA(cmsg);
if (*hlimit < -1 || *hlimit > 0xff) {
ipc6->hlimit = *(int *)CMSG_DATA(cmsg);
if (ipc6->hlimit < -1 || ipc6->hlimit > 0xff) {
err = -EINVAL;
goto exit_f;
}
Expand All @@ -974,7 +973,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
goto exit_f;

err = 0;
*tclass = tc;
ipc6->tclass = tc;

break;
}
Expand All @@ -992,7 +991,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
goto exit_f;

err = 0;
*dontfrag = df;
ipc6->dontfrag = df;

break;
}
Expand Down
28 changes: 16 additions & 12 deletions net/ipv6/icmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,10 +401,10 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
struct flowi6 fl6;
struct icmpv6_msg msg;
struct sockcm_cookie sockc_unused = {0};
struct ipcm6_cookie ipc6;
int iif = 0;
int addr_type = 0;
int len;
int hlimit;
int err = 0;
u32 mark = IP6_REPLY_MARK(net, skb->mark);

Expand Down Expand Up @@ -507,7 +507,10 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
if (IS_ERR(dst))
goto out;

hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
ipc6.tclass = np->tclass;
ipc6.dontfrag = np->dontfrag;
ipc6.opt = NULL;

msg.skb = skb;
msg.offset = skb_network_offset(skb);
Expand All @@ -526,9 +529,9 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)

err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
sizeof(struct icmp6hdr), hlimit,
np->tclass, NULL, &fl6, (struct rt6_info *)dst,
MSG_DONTWAIT, np->dontfrag, &sockc_unused);
sizeof(struct icmp6hdr),
&ipc6, &fl6, (struct rt6_info *)dst,
MSG_DONTWAIT, &sockc_unused);
if (err) {
ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
ip6_flush_pending_frames(sk);
Expand Down Expand Up @@ -563,9 +566,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
struct flowi6 fl6;
struct icmpv6_msg msg;
struct dst_entry *dst;
struct ipcm6_cookie ipc6;
int err = 0;
int hlimit;
u8 tclass;
u32 mark = IP6_REPLY_MARK(net, skb->mark);
struct sockcm_cookie sockc_unused = {0};

Expand Down Expand Up @@ -607,19 +609,21 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (IS_ERR(dst))
goto out;

hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);

idev = __in6_dev_get(skb->dev);

msg.skb = skb;
msg.offset = 0;
msg.type = ICMPV6_ECHO_REPLY;

tclass = ipv6_get_dsfield(ipv6_hdr(skb));
ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
ipc6.tclass = ipv6_get_dsfield(ipv6_hdr(skb));
ipc6.dontfrag = np->dontfrag;
ipc6.opt = NULL;

err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl6,
sizeof(struct icmp6hdr), &ipc6, &fl6,
(struct rt6_info *)dst, MSG_DONTWAIT,
np->dontfrag, &sockc_unused);
&sockc_unused);

if (err) {
__ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
Expand Down
6 changes: 3 additions & 3 deletions net/ipv6/ip6_flowlabel.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
struct msghdr msg;
struct flowi6 flowi6;
struct sockcm_cookie sockc_junk;
int junk;
struct ipcm6_cookie ipc6;

err = -ENOMEM;
fl->opt = kmalloc(sizeof(*fl->opt) + olen, GFP_KERNEL);
Expand All @@ -390,8 +390,8 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq,
msg.msg_control = (void *)(fl->opt+1);
memset(&flowi6, 0, sizeof(flowi6));

err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt,
&junk, &junk, &junk, &sockc_junk);
ipc6.opt = fl->opt;
err = ip6_datagram_send_ctl(net, sk, &msg, &flowi6, &ipc6, &sockc_junk);
if (err)
goto done;
err = -EINVAL;
Expand Down
42 changes: 20 additions & 22 deletions net/ipv6/ip6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -1182,12 +1182,12 @@ static void ip6_append_data_mtu(unsigned int *mtu,
}

static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
struct inet6_cork *v6_cork,
int hlimit, int tclass, struct ipv6_txoptions *opt,
struct inet6_cork *v6_cork, struct ipcm6_cookie *ipc6,
struct rt6_info *rt, struct flowi6 *fl6)
{
struct ipv6_pinfo *np = inet6_sk(sk);
unsigned int mtu;
struct ipv6_txoptions *opt = ipc6->opt;

/*
* setup for corking
Expand Down Expand Up @@ -1229,8 +1229,8 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
dst_hold(&rt->dst);
cork->base.dst = &rt->dst;
cork->fl.u.ip6 = *fl6;
v6_cork->hop_limit = hlimit;
v6_cork->tclass = tclass;
v6_cork->hop_limit = ipc6->hlimit;
v6_cork->tclass = ipc6->tclass;
if (rt->dst.flags & DST_XFRM_TUNNEL)
mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ?
rt->dst.dev->mtu : dst_mtu(&rt->dst);
Expand Down Expand Up @@ -1258,7 +1258,7 @@ static int __ip6_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset,
int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
unsigned int flags, int dontfrag,
unsigned int flags, struct ipcm6_cookie *ipc6,
const struct sockcm_cookie *sockc)
{
struct sk_buff *skb, *skb_prev = NULL;
Expand Down Expand Up @@ -1298,7 +1298,7 @@ static int __ip6_append_data(struct sock *sk,
sizeof(struct frag_hdr) : 0) +
rt->rt6i_nfheader_len;

if (cork->length + length > mtu - headersize && dontfrag &&
if (cork->length + length > mtu - headersize && ipc6->dontfrag &&
(sk->sk_protocol == IPPROTO_UDP ||
sk->sk_protocol == IPPROTO_RAW)) {
ipv6_local_rxpmtu(sk, fl6, mtu - headersize +
Expand Down Expand Up @@ -1564,9 +1564,9 @@ static int __ip6_append_data(struct sock *sk,
int ip6_append_data(struct sock *sk,
int getfrag(void *from, char *to, int offset, int len,
int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen, int hlimit,
int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6,
struct rt6_info *rt, unsigned int flags, int dontfrag,
void *from, int length, int transhdrlen,
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
struct rt6_info *rt, unsigned int flags,
const struct sockcm_cookie *sockc)
{
struct inet_sock *inet = inet_sk(sk);
Expand All @@ -1580,12 +1580,12 @@ int ip6_append_data(struct sock *sk,
/*
* setup for corking
*/
err = ip6_setup_cork(sk, &inet->cork, &np->cork, hlimit,
tclass, opt, rt, fl6);
err = ip6_setup_cork(sk, &inet->cork, &np->cork,
ipc6, rt, fl6);
if (err)
return err;

exthdrlen = (opt ? opt->opt_flen : 0);
exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
length += exthdrlen;
transhdrlen += exthdrlen;
} else {
Expand All @@ -1595,8 +1595,7 @@ int ip6_append_data(struct sock *sk,

return __ip6_append_data(sk, fl6, &sk->sk_write_queue, &inet->cork.base,
&np->cork, sk_page_frag(sk), getfrag,
from, length, transhdrlen, flags, dontfrag,
sockc);
from, length, transhdrlen, flags, ipc6, sockc);
}
EXPORT_SYMBOL_GPL(ip6_append_data);

Expand Down Expand Up @@ -1752,15 +1751,14 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
int getfrag(void *from, char *to, int offset,
int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
int hlimit, int tclass,
struct ipv6_txoptions *opt, struct flowi6 *fl6,
struct ipcm6_cookie *ipc6, struct flowi6 *fl6,
struct rt6_info *rt, unsigned int flags,
int dontfrag, const struct sockcm_cookie *sockc)
const struct sockcm_cookie *sockc)
{
struct inet_cork_full cork;
struct inet6_cork v6_cork;
struct sk_buff_head queue;
int exthdrlen = (opt ? opt->opt_flen : 0);
int exthdrlen = (ipc6->opt ? ipc6->opt->opt_flen : 0);
int err;

if (flags & MSG_PROBE)
Expand All @@ -1772,17 +1770,17 @@ struct sk_buff *ip6_make_skb(struct sock *sk,
cork.base.addr = 0;
cork.base.opt = NULL;
v6_cork.opt = NULL;
err = ip6_setup_cork(sk, &cork, &v6_cork, hlimit, tclass, opt, rt, fl6);
err = ip6_setup_cork(sk, &cork, &v6_cork, ipc6, rt, fl6);
if (err)
return ERR_PTR(err);

if (dontfrag < 0)
dontfrag = inet6_sk(sk)->dontfrag;
if (ipc6->dontfrag < 0)
ipc6->dontfrag = inet6_sk(sk)->dontfrag;

err = __ip6_append_data(sk, fl6, &queue, &cork.base, &v6_cork,
&current->task_frag, getfrag, from,
length + exthdrlen, transhdrlen + exthdrlen,
flags, dontfrag, sockc);
flags, ipc6, sockc);
if (err) {
__ip6_flush_pending_frames(sk, &queue, &cork, &v6_cork);
return ERR_PTR(err);
Expand Down
6 changes: 3 additions & 3 deletions net/ipv6/ipv6_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
struct msghdr msg;
struct flowi6 fl6;
struct sockcm_cookie sockc_junk;
int junk;
struct ipcm6_cookie ipc6;

memset(&fl6, 0, sizeof(fl6));
fl6.flowi6_oif = sk->sk_bound_dev_if;
Expand Down Expand Up @@ -503,9 +503,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,

msg.msg_controllen = optlen;
msg.msg_control = (void *)(opt+1);
ipc6.opt = opt;

retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk,
&junk, &junk, &sockc_junk);
retv = ip6_datagram_send_ctl(net, sk, &msg, &fl6, &ipc6, &sockc_junk);
if (retv)
goto done;
update:
Expand Down
12 changes: 7 additions & 5 deletions net/ipv6/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
int iif = 0;
struct flowi6 fl6;
int err;
int hlimit;
struct dst_entry *dst;
struct rt6_info *rt;
struct pingfakehdr pfh;
struct sockcm_cookie junk = {0};
struct ipcm6_cookie ipc6;

pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);

Expand Down Expand Up @@ -139,13 +139,15 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
pfh.wcheck = 0;
pfh.family = AF_INET6;

hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
ipc6.tclass = np->tclass;
ipc6.dontfrag = np->dontfrag;
ipc6.opt = NULL;

lock_sock(sk);
err = ip6_append_data(sk, ping_getfrag, &pfh, len,
0, hlimit,
np->tclass, NULL, &fl6, rt,
MSG_DONTWAIT, np->dontfrag, &junk);
0, &ipc6, &fl6, rt,
MSG_DONTWAIT, &junk);

if (err) {
ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev,
Expand Down
Loading

0 comments on commit 26879da

Please sign in to comment.