aboutsummaryrefslogtreecommitdiff
path: root/include/net/ipv6.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/net/ipv6.h')
-rw-r--r--include/net/ipv6.h37
1 files changed, 36 insertions, 1 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index e1a10b0ac0b0..6570f379aba2 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -205,6 +205,7 @@ extern rwlock_t ip6_ra_lock;
*/
struct ipv6_txoptions {
+ atomic_t refcnt;
/* Length of this structure */
int tot_len;
@@ -217,7 +218,7 @@ struct ipv6_txoptions {
struct ipv6_opt_hdr *dst0opt;
struct ipv6_rt_hdr *srcrt; /* Routing Header */
struct ipv6_opt_hdr *dst1opt;
-
+ struct rcu_head rcu;
/* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */
};
@@ -252,6 +253,24 @@ struct ipv6_fl_socklist {
struct rcu_head rcu;
};
+static inline struct ipv6_txoptions *txopt_get(const struct ipv6_pinfo *np)
+{
+ struct ipv6_txoptions *opt;
+
+ rcu_read_lock();
+ opt = rcu_dereference(np->opt);
+ if (opt && !atomic_inc_not_zero(&opt->refcnt))
+ opt = NULL;
+ rcu_read_unlock();
+ return opt;
+}
+
+static inline void txopt_put(struct ipv6_txoptions *opt)
+{
+ if (opt && atomic_dec_and_test(&opt->refcnt))
+ kfree_rcu(opt, rcu);
+}
+
struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label);
struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions *opt_space,
struct ip6_flowlabel *fl,
@@ -382,6 +401,21 @@ static inline void ipv6_addr_prefix(struct in6_addr *pfx,
pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b);
}
+static inline void ipv6_addr_prefix_copy(struct in6_addr *addr,
+ const struct in6_addr *pfx,
+ int plen)
+{
+ /* caller must guarantee 0 <= plen <= 128 */
+ int o = plen >> 3,
+ b = plen & 0x7;
+
+ memcpy(addr->s6_addr, pfx, o);
+ if (b != 0) {
+ addr->s6_addr[o] &= ~(0xff00 >> b);
+ addr->s6_addr[o] |= (pfx->s6_addr[o] & (0xff00 >> b));
+ }
+}
+
static inline void __ipv6_addr_set_half(__be32 *addr,
__be32 wh, __be32 wl)
{
@@ -490,6 +524,7 @@ struct ip6_create_arg {
u32 user;
const struct in6_addr *src;
const struct in6_addr *dst;
+ int iif;
u8 ecn;
};