GNU Linux-libre 4.4.299-gnu1
[releases.git] / net / openvswitch / conntrack.c
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
28 struct ovs_ct_len_tbl {
29         size_t maxlen;
30         size_t minlen;
31 };
32
33 /* Metadata mark for masked write to conntrack mark */
34 struct md_mark {
35         u32 value;
36         u32 mask;
37 };
38
39 /* Metadata label for masked write to conntrack label. */
40 struct md_labels {
41         struct ovs_key_ct_labels value;
42         struct ovs_key_ct_labels mask;
43 };
44
45 /* Conntrack action context for execution. */
46 struct 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
56 static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
57
58 static 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. */
71 static 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
105 static 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
114 static 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
132 static 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  */
145 static 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
170 void 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
175 int 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
196 static 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
223 static 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. */
255 static 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  */
304 static 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
359 static struct nf_conntrack_expect *
360 ovs_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         struct nf_conntrack_expect *exp;
365
366         if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple))
367                 return NULL;
368
369         exp = __nf_ct_expect_find(net, zone, &tuple);
370         if (exp) {
371                 struct nf_conntrack_tuple_hash *h;
372
373                 /* Delete existing conntrack entry, if it clashes with the
374                  * expectation.  This can happen since conntrack ALGs do not
375                  * check for clashes between (new) expectations and existing
376                  * conntrack entries.  nf_conntrack_in() will check the
377                  * expectations only if a conntrack entry can not be found,
378                  * which can lead to OVS finding the expectation (here) in the
379                  * init direction, but which will not be removed by the
380                  * nf_conntrack_in() call, if a matching conntrack entry is
381                  * found instead.  In this case all init direction packets
382                  * would be reported as new related packets, while reply
383                  * direction packets would be reported as un-related
384                  * established packets.
385                  */
386                 h = nf_conntrack_find_get(net, zone, &tuple);
387                 if (h) {
388                         struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
389
390                         nf_ct_delete(ct, 0, 0);
391                         nf_conntrack_put(&ct->ct_general);
392                 }
393         }
394
395         return exp;
396 }
397
398 /* Determine whether skb->nfct is equal to the result of conntrack lookup. */
399 static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb,
400                             const struct ovs_conntrack_info *info)
401 {
402         enum ip_conntrack_info ctinfo;
403         struct nf_conn *ct;
404
405         ct = nf_ct_get(skb, &ctinfo);
406         if (!ct)
407                 return false;
408         if (!net_eq(net, read_pnet(&ct->ct_net)))
409                 return false;
410         if (!nf_ct_zone_equal_any(info->ct, nf_ct_zone(ct)))
411                 return false;
412         if (info->helper) {
413                 struct nf_conn_help *help;
414
415                 help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
416                 if (help && rcu_access_pointer(help->helper) != info->helper)
417                         return false;
418         }
419
420         return true;
421 }
422
423 static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
424                            const struct ovs_conntrack_info *info,
425                            struct sk_buff *skb)
426 {
427         /* If we are recirculating packets to match on conntrack fields and
428          * committing with a separate conntrack action,  then we don't need to
429          * actually run the packet through conntrack twice unless it's for a
430          * different zone.
431          */
432         if (!skb_nfct_cached(net, skb, info)) {
433                 struct nf_conn *tmpl = info->ct;
434
435                 /* Associate skb with specified zone. */
436                 if (tmpl) {
437                         if (skb->nfct)
438                                 nf_conntrack_put(skb->nfct);
439                         nf_conntrack_get(&tmpl->ct_general);
440                         skb->nfct = &tmpl->ct_general;
441                         skb->nfctinfo = IP_CT_NEW;
442                 }
443
444                 if (nf_conntrack_in(net, info->family, NF_INET_PRE_ROUTING,
445                                     skb) != NF_ACCEPT)
446                         return -ENOENT;
447
448                 if (ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
449                         WARN_ONCE(1, "helper rejected packet");
450                         return -EINVAL;
451                 }
452         }
453
454         ovs_ct_update_key(skb, info, key, true);
455
456         return 0;
457 }
458
459 /* Lookup connection and read fields into key. */
460 static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
461                          const struct ovs_conntrack_info *info,
462                          struct sk_buff *skb)
463 {
464         struct nf_conntrack_expect *exp;
465
466         exp = ovs_ct_expect_find(net, &info->zone, info->family, skb);
467         if (exp) {
468                 u8 state;
469
470                 state = OVS_CS_F_TRACKED | OVS_CS_F_NEW | OVS_CS_F_RELATED;
471                 __ovs_ct_update_key(key, state, &info->zone, exp->master);
472         } else {
473                 int err;
474
475                 err = __ovs_ct_lookup(net, key, info, skb);
476                 if (err)
477                         return err;
478         }
479
480         return 0;
481 }
482
483 /* Lookup connection and confirm if unconfirmed. */
484 static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
485                          const struct ovs_conntrack_info *info,
486                          struct sk_buff *skb)
487 {
488         u8 state;
489         int err;
490
491         state = key->ct.state;
492         if (key->ct.zone == info->zone.id &&
493             ((state & OVS_CS_F_TRACKED) && !(state & OVS_CS_F_NEW))) {
494                 /* Previous lookup has shown that this connection is already
495                  * tracked and committed. Skip committing.
496                  */
497                 return 0;
498         }
499
500         err = __ovs_ct_lookup(net, key, info, skb);
501         if (err)
502                 return err;
503         if (nf_conntrack_confirm(skb) != NF_ACCEPT)
504                 return -EINVAL;
505
506         return 0;
507 }
508
509 static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
510 {
511         size_t i;
512
513         for (i = 0; i < sizeof(*labels); i++)
514                 if (labels->ct_labels[i])
515                         return true;
516
517         return false;
518 }
519
520 /* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
521  * value if 'skb' is freed.
522  */
523 int ovs_ct_execute(struct net *net, struct sk_buff *skb,
524                    struct sw_flow_key *key,
525                    const struct ovs_conntrack_info *info)
526 {
527         int nh_ofs;
528         int err;
529
530         /* The conntrack module expects to be working at L3. */
531         nh_ofs = skb_network_offset(skb);
532         skb_pull_rcsum(skb, nh_ofs);
533
534         if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
535                 err = handle_fragments(net, key, info->zone.id, skb);
536                 if (err)
537                         return err;
538         }
539
540         if (info->commit)
541                 err = ovs_ct_commit(net, key, info, skb);
542         else
543                 err = ovs_ct_lookup(net, key, info, skb);
544         if (err)
545                 goto err;
546
547         if (info->mark.mask) {
548                 err = ovs_ct_set_mark(skb, key, info->mark.value,
549                                       info->mark.mask);
550                 if (err)
551                         goto err;
552         }
553         if (labels_nonzero(&info->labels.mask))
554                 err = ovs_ct_set_labels(skb, key, &info->labels.value,
555                                         &info->labels.mask);
556 err:
557         skb_push(skb, nh_ofs);
558         skb_postpush_rcsum(skb, skb->data, nh_ofs);
559         if (err)
560                 kfree_skb(skb);
561         return err;
562 }
563
564 static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
565                              const struct sw_flow_key *key, bool log)
566 {
567         struct nf_conntrack_helper *helper;
568         struct nf_conn_help *help;
569
570         helper = nf_conntrack_helper_try_module_get(name, info->family,
571                                                     key->ip.proto);
572         if (!helper) {
573                 OVS_NLERR(log, "Unknown helper \"%s\"", name);
574                 return -EINVAL;
575         }
576
577         help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL);
578         if (!help) {
579                 module_put(helper->me);
580                 return -ENOMEM;
581         }
582
583         rcu_assign_pointer(help->helper, helper);
584         info->helper = helper;
585         return 0;
586 }
587
588 static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
589         [OVS_CT_ATTR_COMMIT]    = { .minlen = 0, .maxlen = 0 },
590         [OVS_CT_ATTR_ZONE]      = { .minlen = sizeof(u16),
591                                     .maxlen = sizeof(u16) },
592         [OVS_CT_ATTR_MARK]      = { .minlen = sizeof(struct md_mark),
593                                     .maxlen = sizeof(struct md_mark) },
594         [OVS_CT_ATTR_LABELS]    = { .minlen = sizeof(struct md_labels),
595                                     .maxlen = sizeof(struct md_labels) },
596         [OVS_CT_ATTR_HELPER]    = { .minlen = 1,
597                                     .maxlen = NF_CT_HELPER_NAME_LEN }
598 };
599
600 static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
601                     const char **helper, bool log)
602 {
603         struct nlattr *a;
604         int rem;
605
606         nla_for_each_nested(a, attr, rem) {
607                 int type = nla_type(a);
608                 int maxlen;
609                 int minlen;
610
611                 if (type > OVS_CT_ATTR_MAX) {
612                         OVS_NLERR(log,
613                                   "Unknown conntrack attr (type=%d, max=%d)",
614                                   type, OVS_CT_ATTR_MAX);
615                         return -EINVAL;
616                 }
617
618                 maxlen = ovs_ct_attr_lens[type].maxlen;
619                 minlen = ovs_ct_attr_lens[type].minlen;
620                 if (nla_len(a) < minlen || nla_len(a) > maxlen) {
621                         OVS_NLERR(log,
622                                   "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)",
623                                   type, nla_len(a), maxlen);
624                         return -EINVAL;
625                 }
626
627                 switch (type) {
628                 case OVS_CT_ATTR_COMMIT:
629                         info->commit = true;
630                         break;
631 #ifdef CONFIG_NF_CONNTRACK_ZONES
632                 case OVS_CT_ATTR_ZONE:
633                         info->zone.id = nla_get_u16(a);
634                         break;
635 #endif
636 #ifdef CONFIG_NF_CONNTRACK_MARK
637                 case OVS_CT_ATTR_MARK: {
638                         struct md_mark *mark = nla_data(a);
639
640                         if (!mark->mask) {
641                                 OVS_NLERR(log, "ct_mark mask cannot be 0");
642                                 return -EINVAL;
643                         }
644                         info->mark = *mark;
645                         break;
646                 }
647 #endif
648 #ifdef CONFIG_NF_CONNTRACK_LABELS
649                 case OVS_CT_ATTR_LABELS: {
650                         struct md_labels *labels = nla_data(a);
651
652                         if (!labels_nonzero(&labels->mask)) {
653                                 OVS_NLERR(log, "ct_labels mask cannot be 0");
654                                 return -EINVAL;
655                         }
656                         info->labels = *labels;
657                         break;
658                 }
659 #endif
660                 case OVS_CT_ATTR_HELPER:
661                         *helper = nla_data(a);
662                         if (!memchr(*helper, '\0', nla_len(a))) {
663                                 OVS_NLERR(log, "Invalid conntrack helper");
664                                 return -EINVAL;
665                         }
666                         break;
667                 default:
668                         OVS_NLERR(log, "Unknown conntrack attr (%d)",
669                                   type);
670                         return -EINVAL;
671                 }
672         }
673
674         if (rem > 0) {
675                 OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
676                 return -EINVAL;
677         }
678
679         return 0;
680 }
681
682 bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
683 {
684         if (attr == OVS_KEY_ATTR_CT_STATE)
685                 return true;
686         if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
687             attr == OVS_KEY_ATTR_CT_ZONE)
688                 return true;
689         if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
690             attr == OVS_KEY_ATTR_CT_MARK)
691                 return true;
692         if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
693             attr == OVS_KEY_ATTR_CT_LABELS) {
694                 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
695
696                 return ovs_net->xt_label;
697         }
698
699         return false;
700 }
701
702 int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
703                        const struct sw_flow_key *key,
704                        struct sw_flow_actions **sfa,  bool log)
705 {
706         struct ovs_conntrack_info ct_info;
707         const char *helper = NULL;
708         u16 family;
709         int err;
710
711         family = key_to_nfproto(key);
712         if (family == NFPROTO_UNSPEC) {
713                 OVS_NLERR(log, "ct family unspecified");
714                 return -EINVAL;
715         }
716
717         memset(&ct_info, 0, sizeof(ct_info));
718         ct_info.family = family;
719
720         nf_ct_zone_init(&ct_info.zone, NF_CT_DEFAULT_ZONE_ID,
721                         NF_CT_DEFAULT_ZONE_DIR, 0);
722
723         err = parse_ct(attr, &ct_info, &helper, log);
724         if (err)
725                 return err;
726
727         /* Set up template for tracking connections in specific zones. */
728         ct_info.ct = nf_ct_tmpl_alloc(net, &ct_info.zone, GFP_KERNEL);
729         if (!ct_info.ct) {
730                 OVS_NLERR(log, "Failed to allocate conntrack template");
731                 return -ENOMEM;
732         }
733
734         __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
735         nf_conntrack_get(&ct_info.ct->ct_general);
736
737         if (helper) {
738                 err = ovs_ct_add_helper(&ct_info, helper, key, log);
739                 if (err)
740                         goto err_free_ct;
741         }
742
743         err = ovs_nla_add_action(sfa, OVS_ACTION_ATTR_CT, &ct_info,
744                                  sizeof(ct_info), log);
745         if (err)
746                 goto err_free_ct;
747
748         return 0;
749 err_free_ct:
750         __ovs_ct_free_action(&ct_info);
751         return err;
752 }
753
754 int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
755                           struct sk_buff *skb)
756 {
757         struct nlattr *start;
758
759         start = nla_nest_start(skb, OVS_ACTION_ATTR_CT);
760         if (!start)
761                 return -EMSGSIZE;
762
763         if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
764                 return -EMSGSIZE;
765         if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
766             nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
767                 return -EMSGSIZE;
768         if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
769             nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
770                     &ct_info->mark))
771                 return -EMSGSIZE;
772         if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
773             labels_nonzero(&ct_info->labels.mask) &&
774             nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
775                     &ct_info->labels))
776                 return -EMSGSIZE;
777         if (ct_info->helper) {
778                 if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
779                                    ct_info->helper->name))
780                         return -EMSGSIZE;
781         }
782
783         nla_nest_end(skb, start);
784
785         return 0;
786 }
787
788 void ovs_ct_free_action(const struct nlattr *a)
789 {
790         struct ovs_conntrack_info *ct_info = nla_data(a);
791
792         __ovs_ct_free_action(ct_info);
793 }
794
795 static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
796 {
797         if (ct_info->helper)
798                 module_put(ct_info->helper->me);
799         if (ct_info->ct)
800                 nf_ct_put(ct_info->ct);
801 }
802
803 void ovs_ct_init(struct net *net)
804 {
805         unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
806         struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
807
808         if (nf_connlabels_get(net, n_bits)) {
809                 ovs_net->xt_label = false;
810                 OVS_NLERR(true, "Failed to set connlabel length");
811         } else {
812                 ovs_net->xt_label = true;
813         }
814 }
815
816 void ovs_ct_exit(struct net *net)
817 {
818         struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
819
820         if (ovs_net->xt_label)
821                 nf_connlabels_put(net);
822 }