On Mon, Feb 25, 2019 at 11:27 AM Nazarov Sergey <s-naza...@yandex.ru> wrote: > > Extract IP options in cipso_v4_error and use __icmp_send. > > Signed-off-by: Sergey Nazarov <s-naza...@yandex.ru> > --- > include/net/ip.h | 2 ++ > net/ipv4/cipso_ipv4.c | 17 +++++++++++++++-- > net/ipv4/ip_options.c | 22 +++++++++++++++++----- > 3 files changed, 34 insertions(+), 7 deletions(-)
Thanks Sergey. Acked-by: Paul Moore <p...@paul-moore.com> > diff --git a/include/net/ip.h b/include/net/ip.h > index 8866bfc..f0e8d06 100644 > --- a/include/net/ip.h > +++ b/include/net/ip.h > @@ -667,6 +667,8 @@ static inline int ip_options_echo(struct net *net, struct > ip_options *dopt, > } > > void ip_options_fragment(struct sk_buff *skb); > +int __ip_options_compile(struct net *net, struct ip_options *opt, > + struct sk_buff *skb, __be32 *info); > int ip_options_compile(struct net *net, struct ip_options *opt, > struct sk_buff *skb); > int ip_options_get(struct net *net, struct ip_options_rcu **optp, > diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c > index 777fa3b..eff86a7 100644 > --- a/net/ipv4/cipso_ipv4.c > +++ b/net/ipv4/cipso_ipv4.c > @@ -1735,13 +1735,26 @@ int cipso_v4_validate(const struct sk_buff *skb, > unsigned char **option) > */ > void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) > { > + unsigned char optbuf[sizeof(struct ip_options) + 40]; > + struct ip_options *opt = (struct ip_options *)optbuf; > + > if (ip_hdr(skb)->protocol == IPPROTO_ICMP || error != -EACCES) > return; > > + /* > + * We might be called above the IP layer, > + * so we can not use icmp_send and IPCB here. > + */ > + > + memset(opt, 0, sizeof(struct ip_options)); > + opt->optlen = ip_hdr(skb)->ihl*4 - sizeof(struct iphdr); > + if (__ip_options_compile(dev_net(skb->dev), opt, skb, NULL)) > + return; > + > if (gateway) > - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0); > + __icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0, opt); > else > - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); > + __icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0, opt); > } > > /** > diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c > index ed194d4..32a3504 100644 > --- a/net/ipv4/ip_options.c > +++ b/net/ipv4/ip_options.c > @@ -251,8 +251,9 @@ static void spec_dst_fill(__be32 *spec_dst, struct > sk_buff *skb) > * If opt == NULL, then skb->data should point to IP header. > */ > > -int ip_options_compile(struct net *net, > - struct ip_options *opt, struct sk_buff *skb) > +int __ip_options_compile(struct net *net, > + struct ip_options *opt, struct sk_buff *skb, > + __be32 *info) > { > __be32 spec_dst = htonl(INADDR_ANY); > unsigned char *pp_ptr = NULL; > @@ -468,11 +469,22 @@ int ip_options_compile(struct net *net, > return 0; > > error: > - if (skb) { > - icmp_send(skb, ICMP_PARAMETERPROB, 0, > htonl((pp_ptr-iph)<<24)); > - } > + if (info) > + *info = htonl((pp_ptr-iph)<<24); > return -EINVAL; > } > + > +int ip_options_compile(struct net *net, > + struct ip_options *opt, struct sk_buff *skb) > +{ > + int ret; > + __be32 info; > + > + ret = __ip_options_compile(net, opt, skb, &info); > + if (ret != 0 && skb) > + icmp_send(skb, ICMP_PARAMETERPROB, 0, info); > + return ret; > +} > EXPORT_SYMBOL(ip_options_compile); > > /* > --- > -- paul moore www.paul-moore.com