aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2005-11-19 22:23:18 -0500
committerYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2005-11-19 22:23:18 -0500
commitdf9890c31a1a447254f39e40c3fd81ad6547945b (patch)
treebf432d75796112d86d102fe721bdce93e6ad6901 /net
parenta305989386e402f48b216786a5c8cf440b33bdad (diff)
[IPV6]: Fix sending extension headers before and including routing header.
Based on suggestion from Masahide Nakamura <nakam@linux-ipv6.org>. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/exthdrs.c19
-rw-r--r--net/ipv6/ip6_flowlabel.c16
-rw-r--r--net/ipv6/raw.c4
-rw-r--r--net/ipv6/udp.c4
4 files changed, 31 insertions, 12 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 748577b76d7..be6faf31138 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -673,3 +673,22 @@ out:
673 return ERR_PTR(err); 673 return ERR_PTR(err);
674} 674}
675 675
676struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
677 struct ipv6_txoptions *opt)
678{
679 /*
680 * ignore the dest before srcrt unless srcrt is being included.
681 * --yoshfuji
682 */
683 if (opt && opt->dst0opt && !opt->srcrt) {
684 if (opt_space != opt) {
685 memcpy(opt_space, opt, sizeof(*opt_space));
686 opt = opt_space;
687 }
688 opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
689 opt->dst0opt = NULL;
690 }
691
692 return opt;
693}
694
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index bbbe80cdaf7..1cf02765fb5 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -225,20 +225,16 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
225 struct ip6_flowlabel * fl, 225 struct ip6_flowlabel * fl,
226 struct ipv6_txoptions * fopt) 226 struct ipv6_txoptions * fopt)
227{ 227{
228 struct ipv6_txoptions * fl_opt = fl ? fl->opt : NULL; 228 struct ipv6_txoptions * fl_opt = fl->opt;
229 229
230 if (fopt == NULL || fopt->opt_flen == 0) { 230 if (fopt == NULL || fopt->opt_flen == 0)
231 if (!fl_opt || !fl_opt->dst0opt || fl_opt->srcrt) 231 return fl_opt;
232 return fl_opt; 232
233 }
234
235 if (fl_opt != NULL) { 233 if (fl_opt != NULL) {
236 opt_space->hopopt = fl_opt->hopopt; 234 opt_space->hopopt = fl_opt->hopopt;
237 opt_space->dst0opt = fl_opt->srcrt ? fl_opt->dst0opt : NULL; 235 opt_space->dst0opt = fl_opt->dst0opt;
238 opt_space->srcrt = fl_opt->srcrt; 236 opt_space->srcrt = fl_opt->srcrt;
239 opt_space->opt_nflen = fl_opt->opt_nflen; 237 opt_space->opt_nflen = fl_opt->opt_nflen;
240 if (fl_opt->dst0opt && !fl_opt->srcrt)
241 opt_space->opt_nflen -= ipv6_optlen(fl_opt->dst0opt);
242 } else { 238 } else {
243 if (fopt->opt_nflen == 0) 239 if (fopt->opt_nflen == 0)
244 return fopt; 240 return fopt;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index a1265a320b1..d77d3352c96 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -756,7 +756,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
756 } 756 }
757 if (opt == NULL) 757 if (opt == NULL)
758 opt = np->opt; 758 opt = np->opt;
759 opt = fl6_merge_options(&opt_space, flowlabel, opt); 759 if (flowlabel)
760 opt = fl6_merge_options(&opt_space, flowlabel, opt);
761 opt = ipv6_fixup_options(&opt_space, opt);
760 762
761 fl.proto = proto; 763 fl.proto = proto;
762 rawv6_probe_proto_opt(&fl, msg); 764 rawv6_probe_proto_opt(&fl, msg);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index bf9519341fd..e2b87cc68b7 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -778,7 +778,9 @@ do_udp_sendmsg:
778 } 778 }
779 if (opt == NULL) 779 if (opt == NULL)
780 opt = np->opt; 780 opt = np->opt;
781 opt = fl6_merge_options(&opt_space, flowlabel, opt); 781 if (flowlabel)
782 opt = fl6_merge_options(&opt_space, flowlabel, opt);
783 opt = ipv6_fixup_options(&opt_space, opt);
782 784
783 fl->proto = IPPROTO_UDP; 785 fl->proto = IPPROTO_UDP;
784 ipv6_addr_copy(&fl->fl6_dst, daddr); 786 ipv6_addr_copy(&fl->fl6_dst, daddr);