1/*
2 * Copyright (c) 2015 Nicira, Inc.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 2 of the GNU General Public
6 * License as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 */
13
14#include <linux/module.h>
15#include <linux/openvswitch.h>
16#include <net/ip.h>
17#include <net/netfilter/nf_conntrack_core.h>
18#include <net/netfilter/nf_conntrack_helper.h>
19#include <net/netfilter/nf_conntrack_labels.h>
20#include <net/netfilter/nf_conntrack_zones.h>
21#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
22
23#include "datapath.h"
24#include "conntrack.h"
25#include "flow.h"
26#include "flow_netlink.h"
27
28struct ovs_ct_len_tbl {
29	size_t maxlen;
30	size_t minlen;
31};
32
33/* Metadata mark for masked write to conntrack mark */
34struct md_mark {
35	u32 value;
36	u32 mask;
37};
38
39/* Metadata label for masked write to conntrack label. */
40struct md_labels {
41	struct ovs_key_ct_labels value;
42	struct ovs_key_ct_labels mask;
43};
44
45/* Conntrack action context for execution. */
46struct ovs_conntrack_info {
47	struct nf_conntrack_helper *helper;
48	struct nf_conntrack_zone zone;
49	struct nf_conn *ct;
50	u8 commit : 1;
51	u16 family;
52	struct md_mark mark;
53	struct md_labels labels;
54};
55
56static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
57
58static u16 key_to_nfproto(const struct sw_flow_key *key)
59{
60	switch (ntohs(key->eth.type)) {
61	case ETH_P_IP:
62		return NFPROTO_IPV4;
63	case ETH_P_IPV6:
64		return NFPROTO_IPV6;
65	default:
66		return NFPROTO_UNSPEC;
67	}
68}
69
70/* Map SKB connection state into the values used by flow definition. */
71static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo)
72{
73	u8 ct_state = OVS_CS_F_TRACKED;
74
75	switch (ctinfo) {
76	case IP_CT_ESTABLISHED_REPLY:
77	case IP_CT_RELATED_REPLY:
78	case IP_CT_NEW_REPLY:
79		ct_state |= OVS_CS_F_REPLY_DIR;
80		break;
81	default:
82		break;
83	}
84
85	switch (ctinfo) {
86	case IP_CT_ESTABLISHED:
87	case IP_CT_ESTABLISHED_REPLY:
88		ct_state |= OVS_CS_F_ESTABLISHED;
89		break;
90	case IP_CT_RELATED:
91	case IP_CT_RELATED_REPLY:
92		ct_state |= OVS_CS_F_RELATED;
93		break;
94	case IP_CT_NEW:
95	case IP_CT_NEW_REPLY:
96		ct_state |= OVS_CS_F_NEW;
97		break;
98	default:
99		break;
100	}
101
102	return ct_state;
103}
104
105static u32 ovs_ct_get_mark(const struct nf_conn *ct)
106{
107#if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
108	return ct ? ct->mark : 0;
109#else
110	return 0;
111#endif
112}
113
114static void ovs_ct_get_labels(const struct nf_conn *ct,
115			      struct ovs_key_ct_labels *labels)
116{
117	struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
118
119	if (cl) {
120		size_t len = cl->words * sizeof(long);
121
122		if (len > OVS_CT_LABELS_LEN)
123			len = OVS_CT_LABELS_LEN;
124		else if (len < OVS_CT_LABELS_LEN)
125			memset(labels, 0, OVS_CT_LABELS_LEN);
126		memcpy(labels, cl->bits, len);
127	} else {
128		memset(labels, 0, OVS_CT_LABELS_LEN);
129	}
130}
131
132static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
133				const struct nf_conntrack_zone *zone,
134				const struct nf_conn *ct)
135{
136	key->ct.state = state;
137	key->ct.zone = zone->id;
138	key->ct.mark = ovs_ct_get_mark(ct);
139	ovs_ct_get_labels(ct, &key->ct.labels);
140}
141
142/* Update 'key' based on skb->nfct. If 'post_ct' is true, then OVS has
143 * previously sent the packet to conntrack via the ct action.
144 */
145static void ovs_ct_update_key(const struct sk_buff *skb,
146			      const struct ovs_conntrack_info *info,
147			      struct sw_flow_key *key, bool post_ct)
148{
149	const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
150	enum ip_conntrack_info ctinfo;
151	struct nf_conn *ct;
152	u8 state = 0;
153
154	ct = nf_ct_get(skb, &ctinfo);
155	if (ct) {
156		state = ovs_ct_get_state(ctinfo);
157		if (!nf_ct_is_confirmed(ct))
158			state |= OVS_CS_F_NEW;
159		if (ct->master)
160			state |= OVS_CS_F_RELATED;
161		zone = nf_ct_zone(ct);
162	} else if (post_ct) {
163		state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID;
164		if (info)
165			zone = &info->zone;
166	}
167	__ovs_ct_update_key(key, state, zone, ct);
168}
169
170void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
171{
172	ovs_ct_update_key(skb, NULL, key, false);
173}
174
175int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
176{
177	if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
178		return -EMSGSIZE;
179
180	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
181	    nla_put_u16(skb, OVS_KEY_ATTR_CT_ZONE, key->ct.zone))
182		return -EMSGSIZE;
183
184	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
185	    nla_put_u32(skb, OVS_KEY_ATTR_CT_MARK, key->ct.mark))
186		return -EMSGSIZE;
187
188	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
189	    nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
190		    &key->ct.labels))
191		return -EMSGSIZE;
192
193	return 0;
194}
195
196static int ovs_ct_set_mark(struct sk_buff *skb, struct sw_flow_key *key,
197			   u32 ct_mark, u32 mask)
198{
199#if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
200	enum ip_conntrack_info ctinfo;
201	struct nf_conn *ct;
202	u32 new_mark;
203
204
205	/* The connection could be invalid, in which case set_mark is no-op. */
206	ct = nf_ct_get(skb, &ctinfo);
207	if (!ct)
208		return 0;
209
210	new_mark = ct_mark | (ct->mark & ~(mask));
211	if (ct->mark != new_mark) {
212		ct->mark = new_mark;
213		nf_conntrack_event_cache(IPCT_MARK, ct);
214		key->ct.mark = new_mark;
215	}
216
217	return 0;
218#else
219	return -ENOTSUPP;
220#endif
221}
222
223static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key,
224			     const struct ovs_key_ct_labels *labels,
225			     const struct ovs_key_ct_labels *mask)
226{
227	enum ip_conntrack_info ctinfo;
228	struct nf_conn_labels *cl;
229	struct nf_conn *ct;
230	int err;
231
232	/* The connection could be invalid, in which case set_label is no-op.*/
233	ct = nf_ct_get(skb, &ctinfo);
234	if (!ct)
235		return 0;
236
237	cl = nf_ct_labels_find(ct);
238	if (!cl) {
239		nf_ct_labels_ext_add(ct);
240		cl = nf_ct_labels_find(ct);
241	}
242	if (!cl || cl->words * sizeof(long) < OVS_CT_LABELS_LEN)
243		return -ENOSPC;
244
245	err = nf_connlabels_replace(ct, (u32 *)labels, (u32 *)mask,
246				    OVS_CT_LABELS_LEN / sizeof(u32));
247	if (err)
248		return err;
249
250	ovs_ct_get_labels(ct, &key->ct.labels);
251	return 0;
252}
253
254/* 'skb' should already be pulled to nh_ofs. */
255static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
256{
257	const struct nf_conntrack_helper *helper;
258	const struct nf_conn_help *help;
259	enum ip_conntrack_info ctinfo;
260	unsigned int protoff;
261	struct nf_conn *ct;
262
263	ct = nf_ct_get(skb, &ctinfo);
264	if (!ct || ctinfo == IP_CT_RELATED_REPLY)
265		return NF_ACCEPT;
266
267	help = nfct_help(ct);
268	if (!help)
269		return NF_ACCEPT;
270
271	helper = rcu_dereference(help->helper);
272	if (!helper)
273		return NF_ACCEPT;
274
275	switch (proto) {
276	case NFPROTO_IPV4:
277		protoff = ip_hdrlen(skb);
278		break;
279	case NFPROTO_IPV6: {
280		u8 nexthdr = ipv6_hdr(skb)->nexthdr;
281		__be16 frag_off;
282		int ofs;
283
284		ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
285				       &frag_off);
286		if (ofs < 0 || (frag_off & htons(~0x7)) != 0) {
287			pr_debug("proto header not found\n");
288			return NF_ACCEPT;
289		}
290		protoff = ofs;
291		break;
292	}
293	default:
294		WARN_ONCE(1, "helper invoked on non-IP family!");
295		return NF_DROP;
296	}
297
298	return helper->help(skb, protoff, ct, ctinfo);
299}
300
301/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
302 * value if 'skb' is freed.
303 */
304static int handle_fragments(struct net *net, struct sw_flow_key *key,
305			    u16 zone, struct sk_buff *skb)
306{
307	struct ovs_skb_cb ovs_cb = *OVS_CB(skb);
308
309	if (key->eth.type == htons(ETH_P_IP)) {
310		enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
311		int err;
312
313		memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
314		err = ip_defrag(net, skb, user);
315		if (err)
316			return err;
317
318		ovs_cb.mru = IPCB(skb)->frag_max_size;
319#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
320	} else if (key->eth.type == htons(ETH_P_IPV6)) {
321		enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
322		struct sk_buff *reasm;
323
324		memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
325		reasm = nf_ct_frag6_gather(net, skb, user);
326		if (!reasm)
327			return -EINPROGRESS;
328
329		if (skb == reasm) {
330			kfree_skb(skb);
331			return -EINVAL;
332		}
333
334		/* Don't free 'skb' even though it is one of the original
335		 * fragments, as we're going to morph it into the head.
336		 */
337		skb_get(skb);
338		nf_ct_frag6_consume_orig(reasm);
339
340		key->ip.proto = ipv6_hdr(reasm)->nexthdr;
341		skb_morph(skb, reasm);
342		skb->next = reasm->next;
343		consume_skb(reasm);
344		ovs_cb.mru = IP6CB(skb)->frag_max_size;
345#endif
346	} else {
347		kfree_skb(skb);
348		return -EPFNOSUPPORT;
349	}
350
351	key->ip.frag = OVS_FRAG_TYPE_NONE;
352	skb_clear_hash(skb);
353	skb->ignore_df = 1;
354	*OVS_CB(skb) = ovs_cb;
355
356	return 0;
357}
358
359static struct nf_conntrack_expect *
360ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone,
361		   u16 proto, const struct sk_buff *skb)
362{
363	struct nf_conntrack_tuple tuple;
364
365	if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple))
366		return NULL;
367	return __nf_ct_expect_find(net, zone, &tuple);
368}
369
370/* Determine whether skb->nfct is equal to the result of conntrack lookup. */
371static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb,
372			    const struct ovs_conntrack_info *info)
373{
374	enum ip_conntrack_info ctinfo;
375	struct nf_conn *ct;
376
377	ct = nf_ct_get(skb, &ctinfo);
378	if (!ct)
379		return false;
380	if (!net_eq(net, read_pnet(&ct->ct_net)))
381		return false;
382	if (!nf_ct_zone_equal_any(info->ct, nf_ct_zone(ct)))
383		return false;
384	if (info->helper) {
385		struct nf_conn_help *help;
386
387		help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
388		if (help && rcu_access_pointer(help->helper) != info->helper)
389			return false;
390	}
391
392	return true;
393}
394
395static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
396			   const struct ovs_conntrack_info *info,
397			   struct sk_buff *skb)
398{
399	/* If we are recirculating packets to match on conntrack fields and
400	 * committing with a separate conntrack action,  then we don't need to
401	 * actually run the packet through conntrack twice unless it's for a
402	 * different zone.
403	 */
404	if (!skb_nfct_cached(net, skb, info)) {
405		struct nf_conn *tmpl = info->ct;
406
407		/* Associate skb with specified zone. */
408		if (tmpl) {
409			if (skb->nfct)
410				nf_conntrack_put(skb->nfct);
411			nf_conntrack_get(&tmpl->ct_general);
412			skb->nfct = &tmpl->ct_general;
413			skb->nfctinfo = IP_CT_NEW;
414		}
415
416		if (nf_conntrack_in(net, info->family, NF_INET_PRE_ROUTING,
417				    skb) != NF_ACCEPT)
418			return -ENOENT;
419
420		if (ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
421			WARN_ONCE(1, "helper rejected packet");
422			return -EINVAL;
423		}
424	}
425
426	ovs_ct_update_key(skb, info, key, true);
427
428	return 0;
429}
430
431/* Lookup connection and read fields into key. */
432static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
433			 const struct ovs_conntrack_info *info,
434			 struct sk_buff *skb)
435{
436	struct nf_conntrack_expect *exp;
437
438	exp = ovs_ct_expect_find(net, &info->zone, info->family, skb);
439	if (exp) {
440		u8 state;
441
442		state = OVS_CS_F_TRACKED | OVS_CS_F_NEW | OVS_CS_F_RELATED;
443		__ovs_ct_update_key(key, state, &info->zone, exp->master);
444	} else {
445		int err;
446
447		err = __ovs_ct_lookup(net, key, info, skb);
448		if (err)
449			return err;
450	}
451
452	return 0;
453}
454
455/* Lookup connection and confirm if unconfirmed. */
456static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
457			 const struct ovs_conntrack_info *info,
458			 struct sk_buff *skb)
459{
460	u8 state;
461	int err;
462
463	state = key->ct.state;
464	if (key->ct.zone == info->zone.id &&
465	    ((state & OVS_CS_F_TRACKED) && !(state & OVS_CS_F_NEW))) {
466		/* Previous lookup has shown that this connection is already
467		 * tracked and committed. Skip committing.
468		 */
469		return 0;
470	}
471
472	err = __ovs_ct_lookup(net, key, info, skb);
473	if (err)
474		return err;
475	if (nf_conntrack_confirm(skb) != NF_ACCEPT)
476		return -EINVAL;
477
478	return 0;
479}
480
481static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
482{
483	size_t i;
484
485	for (i = 0; i < sizeof(*labels); i++)
486		if (labels->ct_labels[i])
487			return true;
488
489	return false;
490}
491
492/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
493 * value if 'skb' is freed.
494 */
495int ovs_ct_execute(struct net *net, struct sk_buff *skb,
496		   struct sw_flow_key *key,
497		   const struct ovs_conntrack_info *info)
498{
499	int nh_ofs;
500	int err;
501
502	/* The conntrack module expects to be working at L3. */
503	nh_ofs = skb_network_offset(skb);
504	skb_pull(skb, nh_ofs);
505
506	if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
507		err = handle_fragments(net, key, info->zone.id, skb);
508		if (err)
509			return err;
510	}
511
512	if (info->commit)
513		err = ovs_ct_commit(net, key, info, skb);
514	else
515		err = ovs_ct_lookup(net, key, info, skb);
516	if (err)
517		goto err;
518
519	if (info->mark.mask) {
520		err = ovs_ct_set_mark(skb, key, info->mark.value,
521				      info->mark.mask);
522		if (err)
523			goto err;
524	}
525	if (labels_nonzero(&info->labels.mask))
526		err = ovs_ct_set_labels(skb, key, &info->labels.value,
527					&info->labels.mask);
528err:
529	skb_push(skb, nh_ofs);
530	if (err)
531		kfree_skb(skb);
532	return err;
533}
534
535static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
536			     const struct sw_flow_key *key, bool log)
537{
538	struct nf_conntrack_helper *helper;
539	struct nf_conn_help *help;
540
541	helper = nf_conntrack_helper_try_module_get(name, info->family,
542						    key->ip.proto);
543	if (!helper) {
544		OVS_NLERR(log, "Unknown helper \"%s\"", name);
545		return -EINVAL;
546	}
547
548	help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL);
549	if (!help) {
550		module_put(helper->me);
551		return -ENOMEM;
552	}
553
554	rcu_assign_pointer(help->helper, helper);
555	info->helper = helper;
556	return 0;
557}
558
559static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
560	[OVS_CT_ATTR_COMMIT]	= { .minlen = 0, .maxlen = 0 },
561	[OVS_CT_ATTR_ZONE]	= { .minlen = sizeof(u16),
562				    .maxlen = sizeof(u16) },
563	[OVS_CT_ATTR_MARK]	= { .minlen = sizeof(struct md_mark),
564				    .maxlen = sizeof(struct md_mark) },
565	[OVS_CT_ATTR_LABELS]	= { .minlen = sizeof(struct md_labels),
566				    .maxlen = sizeof(struct md_labels) },
567	[OVS_CT_ATTR_HELPER]	= { .minlen = 1,
568				    .maxlen = NF_CT_HELPER_NAME_LEN }
569};
570
571static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
572		    const char **helper, bool log)
573{
574	struct nlattr *a;
575	int rem;
576
577	nla_for_each_nested(a, attr, rem) {
578		int type = nla_type(a);
579		int maxlen = ovs_ct_attr_lens[type].maxlen;
580		int minlen = ovs_ct_attr_lens[type].minlen;
581
582		if (type > OVS_CT_ATTR_MAX) {
583			OVS_NLERR(log,
584				  "Unknown conntrack attr (type=%d, max=%d)",
585				  type, OVS_CT_ATTR_MAX);
586			return -EINVAL;
587		}
588		if (nla_len(a) < minlen || nla_len(a) > maxlen) {
589			OVS_NLERR(log,
590				  "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)",
591				  type, nla_len(a), maxlen);
592			return -EINVAL;
593		}
594
595		switch (type) {
596		case OVS_CT_ATTR_COMMIT:
597			info->commit = true;
598			break;
599#ifdef CONFIG_NF_CONNTRACK_ZONES
600		case OVS_CT_ATTR_ZONE:
601			info->zone.id = nla_get_u16(a);
602			break;
603#endif
604#ifdef CONFIG_NF_CONNTRACK_MARK
605		case OVS_CT_ATTR_MARK: {
606			struct md_mark *mark = nla_data(a);
607
608			if (!mark->mask) {
609				OVS_NLERR(log, "ct_mark mask cannot be 0");
610				return -EINVAL;
611			}
612			info->mark = *mark;
613			break;
614		}
615#endif
616#ifdef CONFIG_NF_CONNTRACK_LABELS
617		case OVS_CT_ATTR_LABELS: {
618			struct md_labels *labels = nla_data(a);
619
620			if (!labels_nonzero(&labels->mask)) {
621				OVS_NLERR(log, "ct_labels mask cannot be 0");
622				return -EINVAL;
623			}
624			info->labels = *labels;
625			break;
626		}
627#endif
628		case OVS_CT_ATTR_HELPER:
629			*helper = nla_data(a);
630			if (!memchr(*helper, '\0', nla_len(a))) {
631				OVS_NLERR(log, "Invalid conntrack helper");
632				return -EINVAL;
633			}
634			break;
635		default:
636			OVS_NLERR(log, "Unknown conntrack attr (%d)",
637				  type);
638			return -EINVAL;
639		}
640	}
641
642	if (rem > 0) {
643		OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
644		return -EINVAL;
645	}
646
647	return 0;
648}
649
650bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
651{
652	if (attr == OVS_KEY_ATTR_CT_STATE)
653		return true;
654	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
655	    attr == OVS_KEY_ATTR_CT_ZONE)
656		return true;
657	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
658	    attr == OVS_KEY_ATTR_CT_MARK)
659		return true;
660	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
661	    attr == OVS_KEY_ATTR_CT_LABELS) {
662		struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
663
664		return ovs_net->xt_label;
665	}
666
667	return false;
668}
669
670int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
671		       const struct sw_flow_key *key,
672		       struct sw_flow_actions **sfa,  bool log)
673{
674	struct ovs_conntrack_info ct_info;
675	const char *helper = NULL;
676	u16 family;
677	int err;
678
679	family = key_to_nfproto(key);
680	if (family == NFPROTO_UNSPEC) {
681		OVS_NLERR(log, "ct family unspecified");
682		return -EINVAL;
683	}
684
685	memset(&ct_info, 0, sizeof(ct_info));
686	ct_info.family = family;
687
688	nf_ct_zone_init(&ct_info.zone, NF_CT_DEFAULT_ZONE_ID,
689			NF_CT_DEFAULT_ZONE_DIR, 0);
690
691	err = parse_ct(attr, &ct_info, &helper, log);
692	if (err)
693		return err;
694
695	/* Set up template for tracking connections in specific zones. */
696	ct_info.ct = nf_ct_tmpl_alloc(net, &ct_info.zone, GFP_KERNEL);
697	if (!ct_info.ct) {
698		OVS_NLERR(log, "Failed to allocate conntrack template");
699		return -ENOMEM;
700	}
701
702	__set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
703	nf_conntrack_get(&ct_info.ct->ct_general);
704
705	if (helper) {
706		err = ovs_ct_add_helper(&ct_info, helper, key, log);
707		if (err)
708			goto err_free_ct;
709	}
710
711	err = ovs_nla_add_action(sfa, OVS_ACTION_ATTR_CT, &ct_info,
712				 sizeof(ct_info), log);
713	if (err)
714		goto err_free_ct;
715
716	return 0;
717err_free_ct:
718	__ovs_ct_free_action(&ct_info);
719	return err;
720}
721
722int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
723			  struct sk_buff *skb)
724{
725	struct nlattr *start;
726
727	start = nla_nest_start(skb, OVS_ACTION_ATTR_CT);
728	if (!start)
729		return -EMSGSIZE;
730
731	if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
732		return -EMSGSIZE;
733	if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
734	    nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
735		return -EMSGSIZE;
736	if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
737	    nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
738		    &ct_info->mark))
739		return -EMSGSIZE;
740	if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
741	    labels_nonzero(&ct_info->labels.mask) &&
742	    nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
743		    &ct_info->labels))
744		return -EMSGSIZE;
745	if (ct_info->helper) {
746		if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
747				   ct_info->helper->name))
748			return -EMSGSIZE;
749	}
750
751	nla_nest_end(skb, start);
752
753	return 0;
754}
755
756void ovs_ct_free_action(const struct nlattr *a)
757{
758	struct ovs_conntrack_info *ct_info = nla_data(a);
759
760	__ovs_ct_free_action(ct_info);
761}
762
763static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
764{
765	if (ct_info->helper)
766		module_put(ct_info->helper->me);
767	if (ct_info->ct)
768		nf_ct_put(ct_info->ct);
769}
770
771void ovs_ct_init(struct net *net)
772{
773	unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
774	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
775
776	if (nf_connlabels_get(net, n_bits)) {
777		ovs_net->xt_label = false;
778		OVS_NLERR(true, "Failed to set connlabel length");
779	} else {
780		ovs_net->xt_label = true;
781	}
782}
783
784void ovs_ct_exit(struct net *net)
785{
786	struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
787
788	if (ovs_net->xt_label)
789		nf_connlabels_put(net);
790}
791