]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/ipv6/exthdrs.c
ipv6: Add ipv6_renew_options_kern() that accepts a kernel mem pointer.
[mirror_ubuntu-artful-kernel.git] / net / ipv6 / exthdrs.c
index ea7c4d64a00adad60a634afb2c6efca4ab029799..d5fd3e799f86a8e2e51bc132f109f17cbc7f733e 100644 (file)
@@ -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)
 {