aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r--net/ipv6/raw.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index dc65ec198f7c..fa59dd7a427e 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -733,6 +733,7 @@ static int raw6_getfrag(void *from, char *to, int offset, int len, int odd,
733 733
734static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) 734static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
735{ 735{
736 struct ipv6_txoptions *opt_to_free = NULL;
736 struct ipv6_txoptions opt_space; 737 struct ipv6_txoptions opt_space;
737 DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name); 738 DECLARE_SOCKADDR(struct sockaddr_in6 *, sin6, msg->msg_name);
738 struct in6_addr *daddr, *final_p, final; 739 struct in6_addr *daddr, *final_p, final;
@@ -839,8 +840,10 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
839 if (!(opt->opt_nflen|opt->opt_flen)) 840 if (!(opt->opt_nflen|opt->opt_flen))
840 opt = NULL; 841 opt = NULL;
841 } 842 }
842 if (!opt) 843 if (!opt) {
843 opt = np->opt; 844 opt = txopt_get(np);
845 opt_to_free = opt;
846 }
844 if (flowlabel) 847 if (flowlabel)
845 opt = fl6_merge_options(&opt_space, flowlabel, opt); 848 opt = fl6_merge_options(&opt_space, flowlabel, opt);
846 opt = ipv6_fixup_options(&opt_space, opt); 849 opt = ipv6_fixup_options(&opt_space, opt);
@@ -906,6 +909,7 @@ done:
906 dst_release(dst); 909 dst_release(dst);
907out: 910out:
908 fl6_sock_release(flowlabel); 911 fl6_sock_release(flowlabel);
912 txopt_put(opt_to_free);
909 return err < 0 ? err : len; 913 return err < 0 ? err : len;
910do_confirm: 914do_confirm:
911 dst_confirm(dst); 915 dst_confirm(dst);
@@ -968,6 +972,11 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
968 return -EFAULT; 972 return -EFAULT;
969 973
970 switch (optname) { 974 switch (optname) {
975 case IPV6_HDRINCL:
976 if (sk->sk_type != SOCK_RAW)
977 return -EINVAL;
978 inet_sk(sk)->hdrincl = !!val;
979 return 0;
971 case IPV6_CHECKSUM: 980 case IPV6_CHECKSUM:
972 if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 && 981 if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
973 level == IPPROTO_IPV6) { 982 level == IPPROTO_IPV6) {
@@ -1012,7 +1021,8 @@ static int rawv6_setsockopt(struct sock *sk, int level, int optname,
1012 return -EOPNOTSUPP; 1021 return -EOPNOTSUPP;
1013 return rawv6_seticmpfilter(sk, level, optname, optval, optlen); 1022 return rawv6_seticmpfilter(sk, level, optname, optval, optlen);
1014 case SOL_IPV6: 1023 case SOL_IPV6:
1015 if (optname == IPV6_CHECKSUM) 1024 if (optname == IPV6_CHECKSUM ||
1025 optname == IPV6_HDRINCL)
1016 break; 1026 break;
1017 default: 1027 default:
1018 return ipv6_setsockopt(sk, level, optname, optval, optlen); 1028 return ipv6_setsockopt(sk, level, optname, optval, optlen);
@@ -1033,7 +1043,8 @@ static int compat_rawv6_setsockopt(struct sock *sk, int level, int optname,
1033 return -EOPNOTSUPP; 1043 return -EOPNOTSUPP;
1034 return rawv6_seticmpfilter(sk, level, optname, optval, optlen); 1044 return rawv6_seticmpfilter(sk, level, optname, optval, optlen);
1035 case SOL_IPV6: 1045 case SOL_IPV6:
1036 if (optname == IPV6_CHECKSUM) 1046 if (optname == IPV6_CHECKSUM ||
1047 optname == IPV6_HDRINCL)
1037 break; 1048 break;
1038 default: 1049 default:
1039 return compat_ipv6_setsockopt(sk, level, optname, 1050 return compat_ipv6_setsockopt(sk, level, optname,
@@ -1053,6 +1064,9 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
1053 return -EFAULT; 1064 return -EFAULT;
1054 1065
1055 switch (optname) { 1066 switch (optname) {
1067 case IPV6_HDRINCL:
1068 val = inet_sk(sk)->hdrincl;
1069 break;
1056 case IPV6_CHECKSUM: 1070 case IPV6_CHECKSUM:
1057 /* 1071 /*
1058 * We allow getsockopt() for IPPROTO_IPV6-level 1072 * We allow getsockopt() for IPPROTO_IPV6-level
@@ -1090,7 +1104,8 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
1090 return -EOPNOTSUPP; 1104 return -EOPNOTSUPP;
1091 return rawv6_geticmpfilter(sk, level, optname, optval, optlen); 1105 return rawv6_geticmpfilter(sk, level, optname, optval, optlen);
1092 case SOL_IPV6: 1106 case SOL_IPV6:
1093 if (optname == IPV6_CHECKSUM) 1107 if (optname == IPV6_CHECKSUM ||
1108 optname == IPV6_HDRINCL)
1094 break; 1109 break;
1095 default: 1110 default:
1096 return ipv6_getsockopt(sk, level, optname, optval, optlen); 1111 return ipv6_getsockopt(sk, level, optname, optval, optlen);
@@ -1111,7 +1126,8 @@ static int compat_rawv6_getsockopt(struct sock *sk, int level, int optname,
1111 return -EOPNOTSUPP; 1126 return -EOPNOTSUPP;
1112 return rawv6_geticmpfilter(sk, level, optname, optval, optlen); 1127 return rawv6_geticmpfilter(sk, level, optname, optval, optlen);
1113 case SOL_IPV6: 1128 case SOL_IPV6:
1114 if (optname == IPV6_CHECKSUM) 1129 if (optname == IPV6_CHECKSUM ||
1130 optname == IPV6_HDRINCL)
1115 break; 1131 break;
1116 default: 1132 default:
1117 return compat_ipv6_getsockopt(sk, level, optname, 1133 return compat_ipv6_getsockopt(sk, level, optname,