summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHuw Davies <huw@codeweavers.com>2016-06-27 15:02:50 -0400
committerPaul Moore <paul@paul-moore.com>2016-06-27 15:02:50 -0400
commite67ae213c72f72be50561c060ae17e92426651da (patch)
treefbcab23819aeb1ebddfe02c30743c37589794e22
parentd7cce01504a0ccb95b5007d846560cfccbc1947f (diff)
downloadlinux-e67ae213c72f72be50561c060ae17e92426651da.tar.bz2
ipv6: Add ipv6_renew_options_kern() that accepts a kernel mem pointer.
The functionality is equivalent to ipv6_renew_options() except that the newopt pointer is in kernel, not user, memory The kernel memory implementation will be used by the CALIPSO network labelling engine, which needs to be able to set IPv6 hop-by-hop options. Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--include/net/ipv6.h6
-rw-r--r--net/ipv6/exthdrs.c49
2 files changed, 55 insertions, 0 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index d0aeb97aec5d..887313d978d0 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -308,6 +308,12 @@ struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,
int newtype,
struct ipv6_opt_hdr __user *newopt,
int newoptlen);
+struct ipv6_txoptions *
+ipv6_renew_options_kern(struct sock *sk,
+ struct ipv6_txoptions *opt,
+ int newtype,
+ struct ipv6_opt_hdr *newopt,
+ int newoptlen);
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
struct ipv6_txoptions *opt);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index ea7c4d64a00a..d5fd3e799f86 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -758,6 +758,27 @@ static int ipv6_renew_option(void *ohdr,
return 0;
}
+/**
+ * ipv6_renew_options - replace a specific ext hdr with a new one.
+ *
+ * @sk: sock from which to allocate memory
+ * @opt: original options
+ * @newtype: option type to replace in @opt
+ * @newopt: new option of type @newtype to replace (user-mem)
+ * @newoptlen: length of @newopt
+ *
+ * Returns a new set of options which is a copy of @opt with the
+ * option type @newtype replaced with @newopt.
+ *
+ * @opt may be NULL, in which case a new set of options is returned
+ * containing just @newopt.
+ *
+ * @newopt may be NULL, in which case the specified option type is
+ * not copied into the new set of options.
+ *
+ * The new set of options is allocated from the socket option memory
+ * buffer of @sk.
+ */
struct ipv6_txoptions *
ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
int newtype,
@@ -830,6 +851,34 @@ out:
return ERR_PTR(err);
}
+/**
+ * ipv6_renew_options_kern - replace a specific ext hdr with a new one.
+ *
+ * @sk: sock from which to allocate memory
+ * @opt: original options
+ * @newtype: option type to replace in @opt
+ * @newopt: new option of type @newtype to replace (kernel-mem)
+ * @newoptlen: length of @newopt
+ *
+ * See ipv6_renew_options(). The difference is that @newopt is
+ * kernel memory, rather than user memory.
+ */
+struct ipv6_txoptions *
+ipv6_renew_options_kern(struct sock *sk, struct ipv6_txoptions *opt,
+ int newtype, struct ipv6_opt_hdr *newopt,
+ int newoptlen)
+{
+ struct ipv6_txoptions *ret_val;
+ const mm_segment_t old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ ret_val = ipv6_renew_options(sk, opt, newtype,
+ (struct ipv6_opt_hdr __user *)newopt,
+ newoptlen);
+ set_fs(old_fs);
+ return ret_val;
+}
+
struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
struct ipv6_txoptions *opt)
{