blob: f989ccf38eab49428b7d4fa273eabf4bb02bb6f2 [file] [log] [blame]
Joe Stringer7f8a4362015-08-26 11:31:48 -07001/*
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>
Jarno Rajahalme05752522016-03-10 10:54:23 -080016#include <linux/tcp.h>
17#include <linux/udp.h>
18#include <linux/sctp.h>
Joe Stringer7f8a4362015-08-26 11:31:48 -070019#include <net/ip.h>
20#include <net/netfilter/nf_conntrack_core.h>
Joe Stringercae3a262015-08-26 11:31:53 -070021#include <net/netfilter/nf_conntrack_helper.h>
Joe Stringerc2ac6672015-08-26 11:31:52 -070022#include <net/netfilter/nf_conntrack_labels.h>
Jarno Rajahalme05752522016-03-10 10:54:23 -080023#include <net/netfilter/nf_conntrack_seqadj.h>
Joe Stringer7f8a4362015-08-26 11:31:48 -070024#include <net/netfilter/nf_conntrack_zones.h>
25#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
26
Jarno Rajahalme05752522016-03-10 10:54:23 -080027#ifdef CONFIG_NF_NAT_NEEDED
28#include <linux/netfilter/nf_nat.h>
29#include <net/netfilter/nf_nat_core.h>
30#include <net/netfilter/nf_nat_l3proto.h>
31#endif
32
Joe Stringer7f8a4362015-08-26 11:31:48 -070033#include "datapath.h"
34#include "conntrack.h"
35#include "flow.h"
36#include "flow_netlink.h"
37
38struct ovs_ct_len_tbl {
Jarno Rajahalme05752522016-03-10 10:54:23 -080039 int maxlen;
40 int minlen;
Joe Stringer7f8a4362015-08-26 11:31:48 -070041};
42
Joe Stringer182e3042015-08-26 11:31:49 -070043/* Metadata mark for masked write to conntrack mark */
44struct md_mark {
45 u32 value;
46 u32 mask;
47};
48
Joe Stringerc2ac6672015-08-26 11:31:52 -070049/* Metadata label for masked write to conntrack label. */
Joe Stringer33db4122015-10-01 15:00:37 -070050struct md_labels {
51 struct ovs_key_ct_labels value;
52 struct ovs_key_ct_labels mask;
Joe Stringerc2ac6672015-08-26 11:31:52 -070053};
54
Jarno Rajahalme05752522016-03-10 10:54:23 -080055enum ovs_ct_nat {
56 OVS_CT_NAT = 1 << 0, /* NAT for committed connections only. */
57 OVS_CT_SRC_NAT = 1 << 1, /* Source NAT for NEW connections. */
58 OVS_CT_DST_NAT = 1 << 2, /* Destination NAT for NEW connections. */
59};
60
Joe Stringer7f8a4362015-08-26 11:31:48 -070061/* Conntrack action context for execution. */
62struct ovs_conntrack_info {
Joe Stringercae3a262015-08-26 11:31:53 -070063 struct nf_conntrack_helper *helper;
Joe Stringer7f8a4362015-08-26 11:31:48 -070064 struct nf_conntrack_zone zone;
65 struct nf_conn *ct;
Joe Stringerab38a7b2015-10-06 11:00:01 -070066 u8 commit : 1;
Jarno Rajahalme05752522016-03-10 10:54:23 -080067 u8 nat : 3; /* enum ovs_ct_nat */
Joe Stringer7f8a4362015-08-26 11:31:48 -070068 u16 family;
Joe Stringer182e3042015-08-26 11:31:49 -070069 struct md_mark mark;
Joe Stringer33db4122015-10-01 15:00:37 -070070 struct md_labels labels;
Jarno Rajahalme05752522016-03-10 10:54:23 -080071#ifdef CONFIG_NF_NAT_NEEDED
72 struct nf_nat_range range; /* Only present for SRC NAT and DST NAT. */
73#endif
Joe Stringer7f8a4362015-08-26 11:31:48 -070074};
75
Jarno Rajahalme09aa98a2017-02-09 11:21:58 -080076static bool labels_nonzero(const struct ovs_key_ct_labels *labels);
77
Joe Stringer2f3ab9f2015-12-09 14:07:39 -080078static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
79
Joe Stringer7f8a4362015-08-26 11:31:48 -070080static u16 key_to_nfproto(const struct sw_flow_key *key)
81{
82 switch (ntohs(key->eth.type)) {
83 case ETH_P_IP:
84 return NFPROTO_IPV4;
85 case ETH_P_IPV6:
86 return NFPROTO_IPV6;
87 default:
88 return NFPROTO_UNSPEC;
89 }
90}
91
92/* Map SKB connection state into the values used by flow definition. */
93static u8 ovs_ct_get_state(enum ip_conntrack_info ctinfo)
94{
95 u8 ct_state = OVS_CS_F_TRACKED;
96
97 switch (ctinfo) {
98 case IP_CT_ESTABLISHED_REPLY:
99 case IP_CT_RELATED_REPLY:
Joe Stringer7f8a4362015-08-26 11:31:48 -0700100 ct_state |= OVS_CS_F_REPLY_DIR;
101 break;
102 default:
103 break;
104 }
105
106 switch (ctinfo) {
107 case IP_CT_ESTABLISHED:
108 case IP_CT_ESTABLISHED_REPLY:
109 ct_state |= OVS_CS_F_ESTABLISHED;
110 break;
111 case IP_CT_RELATED:
112 case IP_CT_RELATED_REPLY:
113 ct_state |= OVS_CS_F_RELATED;
114 break;
115 case IP_CT_NEW:
Joe Stringer7f8a4362015-08-26 11:31:48 -0700116 ct_state |= OVS_CS_F_NEW;
117 break;
118 default:
119 break;
120 }
121
122 return ct_state;
123}
124
Joe Stringer0d5cdef2015-08-28 19:22:11 -0700125static u32 ovs_ct_get_mark(const struct nf_conn *ct)
126{
127#if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
128 return ct ? ct->mark : 0;
129#else
130 return 0;
131#endif
132}
133
Jarno Rajahalmeb87cec32017-02-09 11:21:56 -0800134/* Guard against conntrack labels max size shrinking below 128 bits. */
135#if NF_CT_LABELS_MAX_SIZE < 16
136#error NF_CT_LABELS_MAX_SIZE must be at least 16 bytes
137#endif
138
Joe Stringer33db4122015-10-01 15:00:37 -0700139static void ovs_ct_get_labels(const struct nf_conn *ct,
140 struct ovs_key_ct_labels *labels)
Joe Stringerc2ac6672015-08-26 11:31:52 -0700141{
142 struct nf_conn_labels *cl = ct ? nf_ct_labels_find(ct) : NULL;
143
Jarno Rajahalmeb87cec32017-02-09 11:21:56 -0800144 if (cl)
145 memcpy(labels, cl->bits, OVS_CT_LABELS_LEN);
146 else
Joe Stringer33db4122015-10-01 15:00:37 -0700147 memset(labels, 0, OVS_CT_LABELS_LEN);
Joe Stringerc2ac6672015-08-26 11:31:52 -0700148}
149
Joe Stringer7f8a4362015-08-26 11:31:48 -0700150static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
Joe Stringer182e3042015-08-26 11:31:49 -0700151 const struct nf_conntrack_zone *zone,
152 const struct nf_conn *ct)
Joe Stringer7f8a4362015-08-26 11:31:48 -0700153{
154 key->ct.state = state;
155 key->ct.zone = zone->id;
Joe Stringer0d5cdef2015-08-28 19:22:11 -0700156 key->ct.mark = ovs_ct_get_mark(ct);
Joe Stringer33db4122015-10-01 15:00:37 -0700157 ovs_ct_get_labels(ct, &key->ct.labels);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700158}
159
Jarno Rajahalme5e17da62017-02-09 11:21:52 -0800160/* Update 'key' based on skb->_nfct. If 'post_ct' is true, then OVS has
Jarno Rajahalme05752522016-03-10 10:54:23 -0800161 * previously sent the packet to conntrack via the ct action. If
162 * 'keep_nat_flags' is true, the existing NAT flags retained, else they are
163 * initialized from the connection status.
Joe Stringer7f8a4362015-08-26 11:31:48 -0700164 */
165static void ovs_ct_update_key(const struct sk_buff *skb,
Joe Stringerd1109862015-12-09 14:07:40 -0800166 const struct ovs_conntrack_info *info,
Jarno Rajahalme05752522016-03-10 10:54:23 -0800167 struct sw_flow_key *key, bool post_ct,
168 bool keep_nat_flags)
Joe Stringer7f8a4362015-08-26 11:31:48 -0700169{
170 const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
171 enum ip_conntrack_info ctinfo;
172 struct nf_conn *ct;
173 u8 state = 0;
174
175 ct = nf_ct_get(skb, &ctinfo);
176 if (ct) {
177 state = ovs_ct_get_state(ctinfo);
Jarno Rajahalme9f13ded2016-03-10 10:54:18 -0800178 /* All unconfirmed entries are NEW connections. */
Joe Stringer4f0909e2015-10-19 19:18:59 -0700179 if (!nf_ct_is_confirmed(ct))
180 state |= OVS_CS_F_NEW;
Jarno Rajahalme9f13ded2016-03-10 10:54:18 -0800181 /* OVS persists the related flag for the duration of the
182 * connection.
183 */
Joe Stringer7f8a4362015-08-26 11:31:48 -0700184 if (ct->master)
185 state |= OVS_CS_F_RELATED;
Jarno Rajahalme05752522016-03-10 10:54:23 -0800186 if (keep_nat_flags) {
187 state |= key->ct.state & OVS_CS_F_NAT_MASK;
188 } else {
189 if (ct->status & IPS_SRC_NAT)
190 state |= OVS_CS_F_SRC_NAT;
191 if (ct->status & IPS_DST_NAT)
192 state |= OVS_CS_F_DST_NAT;
193 }
Joe Stringer7f8a4362015-08-26 11:31:48 -0700194 zone = nf_ct_zone(ct);
195 } else if (post_ct) {
196 state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID;
Joe Stringerd1109862015-12-09 14:07:40 -0800197 if (info)
198 zone = &info->zone;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700199 }
Joe Stringer182e3042015-08-26 11:31:49 -0700200 __ovs_ct_update_key(key, state, zone, ct);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700201}
202
Jarno Rajahalme9f13ded2016-03-10 10:54:18 -0800203/* This is called to initialize CT key fields possibly coming in from the local
204 * stack.
205 */
Joe Stringer7f8a4362015-08-26 11:31:48 -0700206void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
207{
Jarno Rajahalme05752522016-03-10 10:54:23 -0800208 ovs_ct_update_key(skb, NULL, key, false, false);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700209}
210
211int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
212{
Joe Stringerfbccce52015-10-06 11:00:00 -0700213 if (nla_put_u32(skb, OVS_KEY_ATTR_CT_STATE, key->ct.state))
Joe Stringer7f8a4362015-08-26 11:31:48 -0700214 return -EMSGSIZE;
215
216 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
217 nla_put_u16(skb, OVS_KEY_ATTR_CT_ZONE, key->ct.zone))
218 return -EMSGSIZE;
219
Joe Stringer182e3042015-08-26 11:31:49 -0700220 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
221 nla_put_u32(skb, OVS_KEY_ATTR_CT_MARK, key->ct.mark))
222 return -EMSGSIZE;
223
Valentin Rothberg9723e6a2015-08-28 10:39:56 +0200224 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
Joe Stringer33db4122015-10-01 15:00:37 -0700225 nla_put(skb, OVS_KEY_ATTR_CT_LABELS, sizeof(key->ct.labels),
226 &key->ct.labels))
Joe Stringerc2ac6672015-08-26 11:31:52 -0700227 return -EMSGSIZE;
228
Joe Stringer182e3042015-08-26 11:31:49 -0700229 return 0;
230}
231
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800232static int ovs_ct_set_mark(struct nf_conn *ct, struct sw_flow_key *key,
Joe Stringer182e3042015-08-26 11:31:49 -0700233 u32 ct_mark, u32 mask)
234{
Joe Stringer0d5cdef2015-08-28 19:22:11 -0700235#if IS_ENABLED(CONFIG_NF_CONNTRACK_MARK)
Joe Stringer182e3042015-08-26 11:31:49 -0700236 u32 new_mark;
237
Joe Stringer182e3042015-08-26 11:31:49 -0700238 new_mark = ct_mark | (ct->mark & ~(mask));
239 if (ct->mark != new_mark) {
240 ct->mark = new_mark;
Jarno Rajahalme193e3092017-02-09 11:21:54 -0800241 if (nf_ct_is_confirmed(ct))
242 nf_conntrack_event_cache(IPCT_MARK, ct);
Joe Stringer182e3042015-08-26 11:31:49 -0700243 key->ct.mark = new_mark;
244 }
245
Joe Stringer7f8a4362015-08-26 11:31:48 -0700246 return 0;
Joe Stringer0d5cdef2015-08-28 19:22:11 -0700247#else
248 return -ENOTSUPP;
249#endif
Joe Stringer7f8a4362015-08-26 11:31:48 -0700250}
251
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800252static struct nf_conn_labels *ovs_ct_get_conn_labels(struct nf_conn *ct)
Joe Stringerc2ac6672015-08-26 11:31:52 -0700253{
Joe Stringerc2ac6672015-08-26 11:31:52 -0700254 struct nf_conn_labels *cl;
Joe Stringerc2ac6672015-08-26 11:31:52 -0700255
256 cl = nf_ct_labels_find(ct);
257 if (!cl) {
258 nf_ct_labels_ext_add(ct);
259 cl = nf_ct_labels_find(ct);
260 }
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800261
262 return cl;
263}
264
265/* Initialize labels for a new, yet to be committed conntrack entry. Note that
266 * since the new connection is not yet confirmed, and thus no-one else has
267 * access to it's labels, we simply write them over. Also, we refrain from
268 * triggering events, as receiving change events before the create event would
269 * be confusing.
270 */
271static int ovs_ct_init_labels(struct nf_conn *ct, struct sw_flow_key *key,
272 const struct ovs_key_ct_labels *labels,
273 const struct ovs_key_ct_labels *mask)
274{
Jarno Rajahalme09aa98a2017-02-09 11:21:58 -0800275 struct nf_conn_labels *cl, *master_cl;
276 bool have_mask = labels_nonzero(mask);
277
278 /* Inherit master's labels to the related connection? */
279 master_cl = ct->master ? nf_ct_labels_find(ct->master) : NULL;
280
281 if (!master_cl && !have_mask)
282 return 0; /* Nothing to do. */
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800283
284 cl = ovs_ct_get_conn_labels(ct);
Jarno Rajahalmeb87cec32017-02-09 11:21:56 -0800285 if (!cl)
Joe Stringerc2ac6672015-08-26 11:31:52 -0700286 return -ENOSPC;
287
Jarno Rajahalme09aa98a2017-02-09 11:21:58 -0800288 /* Inherit the master's labels, if any. */
289 if (master_cl)
290 *cl = *master_cl;
291
292 if (have_mask) {
293 u32 *dst = (u32 *)cl->bits;
294 int i;
295
296 for (i = 0; i < OVS_CT_LABELS_LEN_32; i++)
297 dst[i] = (dst[i] & ~mask->ct_labels_32[i]) |
298 (labels->ct_labels_32[i]
299 & mask->ct_labels_32[i]);
300 }
Jarno Rajahalme193e3092017-02-09 11:21:54 -0800301
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800302 memcpy(&key->ct.labels, cl->bits, OVS_CT_LABELS_LEN);
Joe Stringerc2ac6672015-08-26 11:31:52 -0700303
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800304 return 0;
305}
306
307static int ovs_ct_set_labels(struct nf_conn *ct, struct sw_flow_key *key,
308 const struct ovs_key_ct_labels *labels,
309 const struct ovs_key_ct_labels *mask)
310{
311 struct nf_conn_labels *cl;
312 int err;
313
314 cl = ovs_ct_get_conn_labels(ct);
315 if (!cl)
316 return -ENOSPC;
317
318 err = nf_connlabels_replace(ct, labels->ct_labels_32,
319 mask->ct_labels_32,
320 OVS_CT_LABELS_LEN_32);
321 if (err)
322 return err;
323
324 memcpy(&key->ct.labels, cl->bits, OVS_CT_LABELS_LEN);
325
Joe Stringerc2ac6672015-08-26 11:31:52 -0700326 return 0;
327}
328
Joe Stringercae3a262015-08-26 11:31:53 -0700329/* 'skb' should already be pulled to nh_ofs. */
330static int ovs_ct_helper(struct sk_buff *skb, u16 proto)
331{
332 const struct nf_conntrack_helper *helper;
333 const struct nf_conn_help *help;
334 enum ip_conntrack_info ctinfo;
335 unsigned int protoff;
336 struct nf_conn *ct;
Jarno Rajahalme05752522016-03-10 10:54:23 -0800337 int err;
Joe Stringercae3a262015-08-26 11:31:53 -0700338
339 ct = nf_ct_get(skb, &ctinfo);
340 if (!ct || ctinfo == IP_CT_RELATED_REPLY)
341 return NF_ACCEPT;
342
343 help = nfct_help(ct);
344 if (!help)
345 return NF_ACCEPT;
346
347 helper = rcu_dereference(help->helper);
348 if (!helper)
349 return NF_ACCEPT;
350
351 switch (proto) {
352 case NFPROTO_IPV4:
353 protoff = ip_hdrlen(skb);
354 break;
355 case NFPROTO_IPV6: {
356 u8 nexthdr = ipv6_hdr(skb)->nexthdr;
357 __be16 frag_off;
Joe Stringercc570602015-09-14 11:14:50 -0700358 int ofs;
Joe Stringercae3a262015-08-26 11:31:53 -0700359
Joe Stringercc570602015-09-14 11:14:50 -0700360 ofs = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
361 &frag_off);
362 if (ofs < 0 || (frag_off & htons(~0x7)) != 0) {
Joe Stringercae3a262015-08-26 11:31:53 -0700363 pr_debug("proto header not found\n");
364 return NF_ACCEPT;
365 }
Joe Stringercc570602015-09-14 11:14:50 -0700366 protoff = ofs;
Joe Stringercae3a262015-08-26 11:31:53 -0700367 break;
368 }
369 default:
370 WARN_ONCE(1, "helper invoked on non-IP family!");
371 return NF_DROP;
372 }
373
Jarno Rajahalme05752522016-03-10 10:54:23 -0800374 err = helper->help(skb, protoff, ct, ctinfo);
375 if (err != NF_ACCEPT)
376 return err;
377
378 /* Adjust seqs after helper. This is needed due to some helpers (e.g.,
379 * FTP with NAT) adusting the TCP payload size when mangling IP
380 * addresses and/or port numbers in the text-based control connection.
381 */
382 if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
383 !nf_ct_seq_adjust(skb, ct, ctinfo, protoff))
384 return NF_DROP;
385 return NF_ACCEPT;
Joe Stringercae3a262015-08-26 11:31:53 -0700386}
387
Joe Stringer74c16612015-10-25 20:21:48 -0700388/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
389 * value if 'skb' is freed.
390 */
Joe Stringer7f8a4362015-08-26 11:31:48 -0700391static int handle_fragments(struct net *net, struct sw_flow_key *key,
392 u16 zone, struct sk_buff *skb)
393{
394 struct ovs_skb_cb ovs_cb = *OVS_CB(skb);
Florian Westphaldaaa7d62015-11-18 23:32:40 +0100395 int err;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700396
397 if (key->eth.type == htons(ETH_P_IP)) {
398 enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700399
400 memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
Eric W. Biederman19bcf9f2015-10-09 13:44:54 -0500401 err = ip_defrag(net, skb, user);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700402 if (err)
403 return err;
404
405 ovs_cb.mru = IPCB(skb)->frag_max_size;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700406#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
Joe Stringer74c16612015-10-25 20:21:48 -0700407 } else if (key->eth.type == htons(ETH_P_IPV6)) {
Joe Stringer7f8a4362015-08-26 11:31:48 -0700408 enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700409
Joe Stringer49e261a2016-04-18 14:51:47 -0700410 skb_orphan(skb);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700411 memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
Florian Westphaldaaa7d62015-11-18 23:32:40 +0100412 err = nf_ct_frag6_gather(net, skb, user);
Daniele Di Proiettof92a80a2016-11-28 15:43:53 -0800413 if (err) {
414 if (err != -EINPROGRESS)
415 kfree_skb(skb);
Florian Westphaldaaa7d62015-11-18 23:32:40 +0100416 return err;
Daniele Di Proiettof92a80a2016-11-28 15:43:53 -0800417 }
Joe Stringer7f8a4362015-08-26 11:31:48 -0700418
Florian Westphaldaaa7d62015-11-18 23:32:40 +0100419 key->ip.proto = ipv6_hdr(skb)->nexthdr;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700420 ovs_cb.mru = IP6CB(skb)->frag_max_size;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700421#endif
422 } else {
Joe Stringer74c16612015-10-25 20:21:48 -0700423 kfree_skb(skb);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700424 return -EPFNOSUPPORT;
425 }
426
427 key->ip.frag = OVS_FRAG_TYPE_NONE;
428 skb_clear_hash(skb);
429 skb->ignore_df = 1;
430 *OVS_CB(skb) = ovs_cb;
431
432 return 0;
433}
434
435static struct nf_conntrack_expect *
436ovs_ct_expect_find(struct net *net, const struct nf_conntrack_zone *zone,
437 u16 proto, const struct sk_buff *skb)
438{
439 struct nf_conntrack_tuple tuple;
440
Eric W. Biedermana31f1ad2015-09-18 14:33:04 -0500441 if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), proto, net, &tuple))
Joe Stringer7f8a4362015-08-26 11:31:48 -0700442 return NULL;
443 return __nf_ct_expect_find(net, zone, &tuple);
444}
445
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800446/* This replicates logic from nf_conntrack_core.c that is not exported. */
447static enum ip_conntrack_info
448ovs_ct_get_info(const struct nf_conntrack_tuple_hash *h)
449{
450 const struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
451
452 if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY)
453 return IP_CT_ESTABLISHED_REPLY;
454 /* Once we've had two way comms, always ESTABLISHED. */
455 if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status))
456 return IP_CT_ESTABLISHED;
457 if (test_bit(IPS_EXPECTED_BIT, &ct->status))
458 return IP_CT_RELATED;
459 return IP_CT_NEW;
460}
461
462/* Find an existing connection which this packet belongs to without
463 * re-attributing statistics or modifying the connection state. This allows an
Jarno Rajahalme5e17da62017-02-09 11:21:52 -0800464 * skb->_nfct lost due to an upcall to be recovered during actions execution.
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800465 *
466 * Must be called with rcu_read_lock.
467 *
Jarno Rajahalme5e17da62017-02-09 11:21:52 -0800468 * On success, populates skb->_nfct and returns the connection. Returns NULL
469 * if there is no existing entry.
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800470 */
471static struct nf_conn *
472ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
Jarno Rajahalme9ff464d2017-02-09 11:21:53 -0800473 u8 l3num, struct sk_buff *skb, bool natted)
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800474{
475 struct nf_conntrack_l3proto *l3proto;
476 struct nf_conntrack_l4proto *l4proto;
477 struct nf_conntrack_tuple tuple;
478 struct nf_conntrack_tuple_hash *h;
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800479 struct nf_conn *ct;
480 unsigned int dataoff;
481 u8 protonum;
482
483 l3proto = __nf_ct_l3proto_find(l3num);
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800484 if (l3proto->get_l4proto(skb, skb_network_offset(skb), &dataoff,
485 &protonum) <= 0) {
486 pr_debug("ovs_ct_find_existing: Can't get protonum\n");
487 return NULL;
488 }
489 l4proto = __nf_ct_l4proto_find(l3num, protonum);
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800490 if (!nf_ct_get_tuple(skb, skb_network_offset(skb), dataoff, l3num,
491 protonum, net, &tuple, l3proto, l4proto)) {
492 pr_debug("ovs_ct_find_existing: Can't get tuple\n");
493 return NULL;
494 }
495
Jarno Rajahalme9ff464d2017-02-09 11:21:53 -0800496 /* Must invert the tuple if skb has been transformed by NAT. */
497 if (natted) {
498 struct nf_conntrack_tuple inverse;
499
500 if (!nf_ct_invert_tuple(&inverse, &tuple, l3proto, l4proto)) {
501 pr_debug("ovs_ct_find_existing: Inversion failed!\n");
502 return NULL;
503 }
504 tuple = inverse;
505 }
506
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800507 /* look for tuple match */
508 h = nf_conntrack_find_get(net, zone, &tuple);
509 if (!h)
510 return NULL; /* Not found. */
511
512 ct = nf_ct_tuplehash_to_ctrack(h);
513
Jarno Rajahalme9ff464d2017-02-09 11:21:53 -0800514 /* Inverted packet tuple matches the reverse direction conntrack tuple,
515 * select the other tuplehash to get the right 'ctinfo' bits for this
516 * packet.
517 */
518 if (natted)
519 h = &ct->tuplehash[!h->tuple.dst.dir];
520
Florian Westphalc74454f2017-01-23 18:21:57 +0100521 nf_ct_set(skb, ct, ovs_ct_get_info(h));
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800522 return ct;
523}
524
Jarno Rajahalme5e17da62017-02-09 11:21:52 -0800525/* Determine whether skb->_nfct is equal to the result of conntrack lookup. */
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800526static bool skb_nfct_cached(struct net *net,
527 const struct sw_flow_key *key,
528 const struct ovs_conntrack_info *info,
529 struct sk_buff *skb)
Joe Stringer7f8a4362015-08-26 11:31:48 -0700530{
531 enum ip_conntrack_info ctinfo;
532 struct nf_conn *ct;
533
534 ct = nf_ct_get(skb, &ctinfo);
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800535 /* If no ct, check if we have evidence that an existing conntrack entry
Jarno Rajahalme5e17da62017-02-09 11:21:52 -0800536 * might be found for this skb. This happens when we lose a skb->_nfct
Jarno Rajahalme289f2252016-03-10 10:54:20 -0800537 * due to an upcall. If the connection was not confirmed, it is not
538 * cached and needs to be run through conntrack again.
539 */
540 if (!ct && key->ct.state & OVS_CS_F_TRACKED &&
541 !(key->ct.state & OVS_CS_F_INVALID) &&
542 key->ct.zone == info->zone.id)
Jarno Rajahalme9ff464d2017-02-09 11:21:53 -0800543 ct = ovs_ct_find_existing(net, &info->zone, info->family, skb,
544 !!(key->ct.state
545 & OVS_CS_F_NAT_MASK));
Joe Stringer7f8a4362015-08-26 11:31:48 -0700546 if (!ct)
547 return false;
548 if (!net_eq(net, read_pnet(&ct->ct_net)))
549 return false;
550 if (!nf_ct_zone_equal_any(info->ct, nf_ct_zone(ct)))
551 return false;
Joe Stringercae3a262015-08-26 11:31:53 -0700552 if (info->helper) {
553 struct nf_conn_help *help;
554
555 help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
556 if (help && rcu_access_pointer(help->helper) != info->helper)
557 return false;
558 }
Joe Stringer7f8a4362015-08-26 11:31:48 -0700559
560 return true;
561}
562
Jarno Rajahalme05752522016-03-10 10:54:23 -0800563#ifdef CONFIG_NF_NAT_NEEDED
564/* Modelled after nf_nat_ipv[46]_fn().
565 * range is only used for new, uninitialized NAT state.
566 * Returns either NF_ACCEPT or NF_DROP.
567 */
568static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
569 enum ip_conntrack_info ctinfo,
570 const struct nf_nat_range *range,
571 enum nf_nat_manip_type maniptype)
572{
573 int hooknum, nh_off, err = NF_ACCEPT;
574
575 nh_off = skb_network_offset(skb);
Lance Richardson75f01a42017-01-12 19:33:18 -0500576 skb_pull_rcsum(skb, nh_off);
Jarno Rajahalme05752522016-03-10 10:54:23 -0800577
578 /* See HOOK2MANIP(). */
579 if (maniptype == NF_NAT_MANIP_SRC)
580 hooknum = NF_INET_LOCAL_IN; /* Source NAT */
581 else
582 hooknum = NF_INET_LOCAL_OUT; /* Destination NAT */
583
584 switch (ctinfo) {
585 case IP_CT_RELATED:
586 case IP_CT_RELATED_REPLY:
Arnd Bergmann99b72482016-03-18 14:33:45 +0100587 if (IS_ENABLED(CONFIG_NF_NAT_IPV4) &&
588 skb->protocol == htons(ETH_P_IP) &&
Jarno Rajahalme05752522016-03-10 10:54:23 -0800589 ip_hdr(skb)->protocol == IPPROTO_ICMP) {
590 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
591 hooknum))
592 err = NF_DROP;
593 goto push;
Arnd Bergmann99b72482016-03-18 14:33:45 +0100594 } else if (IS_ENABLED(CONFIG_NF_NAT_IPV6) &&
595 skb->protocol == htons(ETH_P_IPV6)) {
Jarno Rajahalme05752522016-03-10 10:54:23 -0800596 __be16 frag_off;
597 u8 nexthdr = ipv6_hdr(skb)->nexthdr;
598 int hdrlen = ipv6_skip_exthdr(skb,
599 sizeof(struct ipv6hdr),
600 &nexthdr, &frag_off);
601
602 if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
603 if (!nf_nat_icmpv6_reply_translation(skb, ct,
604 ctinfo,
605 hooknum,
606 hdrlen))
607 err = NF_DROP;
608 goto push;
609 }
Jarno Rajahalme05752522016-03-10 10:54:23 -0800610 }
611 /* Non-ICMP, fall thru to initialize if needed. */
612 case IP_CT_NEW:
613 /* Seen it before? This can happen for loopback, retrans,
614 * or local packets.
615 */
616 if (!nf_nat_initialized(ct, maniptype)) {
617 /* Initialize according to the NAT action. */
618 err = (range && range->flags & NF_NAT_RANGE_MAP_IPS)
619 /* Action is set up to establish a new
620 * mapping.
621 */
622 ? nf_nat_setup_info(ct, range, maniptype)
623 : nf_nat_alloc_null_binding(ct, hooknum);
624 if (err != NF_ACCEPT)
625 goto push;
626 }
627 break;
628
629 case IP_CT_ESTABLISHED:
630 case IP_CT_ESTABLISHED_REPLY:
631 break;
632
633 default:
634 err = NF_DROP;
635 goto push;
636 }
637
638 err = nf_nat_packet(ct, ctinfo, hooknum, skb);
639push:
640 skb_push(skb, nh_off);
Lance Richardson75f01a42017-01-12 19:33:18 -0500641 skb_postpush_rcsum(skb, skb->data, nh_off);
Jarno Rajahalme05752522016-03-10 10:54:23 -0800642
643 return err;
644}
645
646static void ovs_nat_update_key(struct sw_flow_key *key,
647 const struct sk_buff *skb,
648 enum nf_nat_manip_type maniptype)
649{
650 if (maniptype == NF_NAT_MANIP_SRC) {
651 __be16 src;
652
653 key->ct.state |= OVS_CS_F_SRC_NAT;
654 if (key->eth.type == htons(ETH_P_IP))
655 key->ipv4.addr.src = ip_hdr(skb)->saddr;
656 else if (key->eth.type == htons(ETH_P_IPV6))
657 memcpy(&key->ipv6.addr.src, &ipv6_hdr(skb)->saddr,
658 sizeof(key->ipv6.addr.src));
659 else
660 return;
661
662 if (key->ip.proto == IPPROTO_UDP)
663 src = udp_hdr(skb)->source;
664 else if (key->ip.proto == IPPROTO_TCP)
665 src = tcp_hdr(skb)->source;
666 else if (key->ip.proto == IPPROTO_SCTP)
667 src = sctp_hdr(skb)->source;
668 else
669 return;
670
671 key->tp.src = src;
672 } else {
673 __be16 dst;
674
675 key->ct.state |= OVS_CS_F_DST_NAT;
676 if (key->eth.type == htons(ETH_P_IP))
677 key->ipv4.addr.dst = ip_hdr(skb)->daddr;
678 else if (key->eth.type == htons(ETH_P_IPV6))
679 memcpy(&key->ipv6.addr.dst, &ipv6_hdr(skb)->daddr,
680 sizeof(key->ipv6.addr.dst));
681 else
682 return;
683
684 if (key->ip.proto == IPPROTO_UDP)
685 dst = udp_hdr(skb)->dest;
686 else if (key->ip.proto == IPPROTO_TCP)
687 dst = tcp_hdr(skb)->dest;
688 else if (key->ip.proto == IPPROTO_SCTP)
689 dst = sctp_hdr(skb)->dest;
690 else
691 return;
692
693 key->tp.dst = dst;
694 }
695}
696
697/* Returns NF_DROP if the packet should be dropped, NF_ACCEPT otherwise. */
698static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
699 const struct ovs_conntrack_info *info,
700 struct sk_buff *skb, struct nf_conn *ct,
701 enum ip_conntrack_info ctinfo)
702{
703 enum nf_nat_manip_type maniptype;
704 int err;
705
706 if (nf_ct_is_untracked(ct)) {
707 /* A NAT action may only be performed on tracked packets. */
708 return NF_ACCEPT;
709 }
710
711 /* Add NAT extension if not confirmed yet. */
712 if (!nf_ct_is_confirmed(ct) && !nf_ct_nat_ext_add(ct))
713 return NF_ACCEPT; /* Can't NAT. */
714
715 /* Determine NAT type.
716 * Check if the NAT type can be deduced from the tracked connection.
Jarno Rajahalme5745b0b2016-03-21 11:15:19 -0700717 * Make sure new expected connections (IP_CT_RELATED) are NATted only
718 * when committing.
Jarno Rajahalme05752522016-03-10 10:54:23 -0800719 */
720 if (info->nat & OVS_CT_NAT && ctinfo != IP_CT_NEW &&
721 ct->status & IPS_NAT_MASK &&
Jarno Rajahalme5745b0b2016-03-21 11:15:19 -0700722 (ctinfo != IP_CT_RELATED || info->commit)) {
Jarno Rajahalme05752522016-03-10 10:54:23 -0800723 /* NAT an established or related connection like before. */
724 if (CTINFO2DIR(ctinfo) == IP_CT_DIR_REPLY)
725 /* This is the REPLY direction for a connection
726 * for which NAT was applied in the forward
727 * direction. Do the reverse NAT.
728 */
729 maniptype = ct->status & IPS_SRC_NAT
730 ? NF_NAT_MANIP_DST : NF_NAT_MANIP_SRC;
731 else
732 maniptype = ct->status & IPS_SRC_NAT
733 ? NF_NAT_MANIP_SRC : NF_NAT_MANIP_DST;
734 } else if (info->nat & OVS_CT_SRC_NAT) {
735 maniptype = NF_NAT_MANIP_SRC;
736 } else if (info->nat & OVS_CT_DST_NAT) {
737 maniptype = NF_NAT_MANIP_DST;
738 } else {
739 return NF_ACCEPT; /* Connection is not NATed. */
740 }
741 err = ovs_ct_nat_execute(skb, ct, ctinfo, &info->range, maniptype);
742
743 /* Mark NAT done if successful and update the flow key. */
744 if (err == NF_ACCEPT)
745 ovs_nat_update_key(key, skb, maniptype);
746
747 return err;
748}
749#else /* !CONFIG_NF_NAT_NEEDED */
750static int ovs_ct_nat(struct net *net, struct sw_flow_key *key,
751 const struct ovs_conntrack_info *info,
752 struct sk_buff *skb, struct nf_conn *ct,
753 enum ip_conntrack_info ctinfo)
754{
755 return NF_ACCEPT;
756}
757#endif
758
Jarno Rajahalme9f13ded2016-03-10 10:54:18 -0800759/* Pass 'skb' through conntrack in 'net', using zone configured in 'info', if
Jarno Rajahalme394e9102016-03-10 10:54:19 -0800760 * not done already. Update key with new CT state after passing the packet
761 * through conntrack.
Jarno Rajahalme5e17da62017-02-09 11:21:52 -0800762 * Note that if the packet is deemed invalid by conntrack, skb->_nfct will be
Jarno Rajahalme9f13ded2016-03-10 10:54:18 -0800763 * set to NULL and 0 will be returned.
764 */
Joe Stringer4f0909e2015-10-19 19:18:59 -0700765static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
Joe Stringer7f8a4362015-08-26 11:31:48 -0700766 const struct ovs_conntrack_info *info,
767 struct sk_buff *skb)
768{
769 /* If we are recirculating packets to match on conntrack fields and
770 * committing with a separate conntrack action, then we don't need to
771 * actually run the packet through conntrack twice unless it's for a
772 * different zone.
773 */
Jarno Rajahalme28b6e0c2016-03-10 10:54:22 -0800774 bool cached = skb_nfct_cached(net, key, info, skb);
775 enum ip_conntrack_info ctinfo;
776 struct nf_conn *ct;
777
778 if (!cached) {
Joe Stringer7f8a4362015-08-26 11:31:48 -0700779 struct nf_conn *tmpl = info->ct;
Jarno Rajahalme5b6b9292016-03-10 10:54:21 -0800780 int err;
Joe Stringer7f8a4362015-08-26 11:31:48 -0700781
782 /* Associate skb with specified zone. */
783 if (tmpl) {
Florian Westphalcb9c6832017-01-23 18:21:56 +0100784 if (skb_nfct(skb))
785 nf_conntrack_put(skb_nfct(skb));
Joe Stringer7f8a4362015-08-26 11:31:48 -0700786 nf_conntrack_get(&tmpl->ct_general);
Florian Westphalc74454f2017-01-23 18:21:57 +0100787 nf_ct_set(skb, tmpl, IP_CT_NEW);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700788 }
789
Pablo Neira Ayuso08733a02016-11-03 10:56:43 +0100790 err = nf_conntrack_in(net, info->family,
791 NF_INET_PRE_ROUTING, skb);
Jarno Rajahalme5b6b9292016-03-10 10:54:21 -0800792 if (err != NF_ACCEPT)
Joe Stringer7f8a4362015-08-26 11:31:48 -0700793 return -ENOENT;
Joe Stringercae3a262015-08-26 11:31:53 -0700794
Jarno Rajahalme05752522016-03-10 10:54:23 -0800795 /* Clear CT state NAT flags to mark that we have not yet done
796 * NAT after the nf_conntrack_in() call. We can actually clear
797 * the whole state, as it will be re-initialized below.
798 */
799 key->ct.state = 0;
800
801 /* Update the key, but keep the NAT flags. */
802 ovs_ct_update_key(skb, info, key, true, true);
Jarno Rajahalme28b6e0c2016-03-10 10:54:22 -0800803 }
Jarno Rajahalme394e9102016-03-10 10:54:19 -0800804
Jarno Rajahalme28b6e0c2016-03-10 10:54:22 -0800805 ct = nf_ct_get(skb, &ctinfo);
Jarno Rajahalme05752522016-03-10 10:54:23 -0800806 if (ct) {
807 /* Packets starting a new connection must be NATted before the
808 * helper, so that the helper knows about the NAT. We enforce
809 * this by delaying both NAT and helper calls for unconfirmed
810 * connections until the committing CT action. For later
811 * packets NAT and Helper may be called in either order.
812 *
813 * NAT will be done only if the CT action has NAT, and only
814 * once per packet (per zone), as guarded by the NAT bits in
815 * the key->ct.state.
816 */
817 if (info->nat && !(key->ct.state & OVS_CS_F_NAT_MASK) &&
818 (nf_ct_is_confirmed(ct) || info->commit) &&
819 ovs_ct_nat(net, key, info, skb, ct, ctinfo) != NF_ACCEPT) {
820 return -EINVAL;
821 }
822
Joe Stringer16ec3d42016-05-11 10:29:26 -0700823 /* Userspace may decide to perform a ct lookup without a helper
824 * specified followed by a (recirculate and) commit with one.
825 * Therefore, for unconfirmed connections which we will commit,
826 * we need to attach the helper here.
827 */
828 if (!nf_ct_is_confirmed(ct) && info->commit &&
829 info->helper && !nfct_help(ct)) {
830 int err = __nf_ct_try_assign_helper(ct, info->ct,
831 GFP_ATOMIC);
832 if (err)
833 return err;
834 }
835
Jarno Rajahalme05752522016-03-10 10:54:23 -0800836 /* Call the helper only if:
837 * - nf_conntrack_in() was executed above ("!cached") for a
838 * confirmed connection, or
839 * - When committing an unconfirmed connection.
840 */
841 if ((nf_ct_is_confirmed(ct) ? !cached : info->commit) &&
842 ovs_ct_helper(skb, info->family) != NF_ACCEPT) {
843 return -EINVAL;
844 }
Joe Stringer7f8a4362015-08-26 11:31:48 -0700845 }
846
847 return 0;
848}
849
850/* Lookup connection and read fields into key. */
851static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
852 const struct ovs_conntrack_info *info,
853 struct sk_buff *skb)
854{
855 struct nf_conntrack_expect *exp;
856
Jarno Rajahalme9f13ded2016-03-10 10:54:18 -0800857 /* If we pass an expected packet through nf_conntrack_in() the
858 * expectation is typically removed, but the packet could still be
859 * lost in upcall processing. To prevent this from happening we
860 * perform an explicit expectation lookup. Expected connections are
861 * always new, and will be passed through conntrack only when they are
862 * committed, as it is OK to remove the expectation at that time.
863 */
Joe Stringer7f8a4362015-08-26 11:31:48 -0700864 exp = ovs_ct_expect_find(net, &info->zone, info->family, skb);
865 if (exp) {
866 u8 state;
867
Jarno Rajahalme05752522016-03-10 10:54:23 -0800868 /* NOTE: New connections are NATted and Helped only when
869 * committed, so we are not calling into NAT here.
870 */
Joe Stringer7f8a4362015-08-26 11:31:48 -0700871 state = OVS_CS_F_TRACKED | OVS_CS_F_NEW | OVS_CS_F_RELATED;
Joe Stringer182e3042015-08-26 11:31:49 -0700872 __ovs_ct_update_key(key, state, &info->zone, exp->master);
Samuel Gauthierd913d3a2016-06-28 17:22:26 +0200873 } else {
874 struct nf_conn *ct;
875 int err;
876
877 err = __ovs_ct_lookup(net, key, info, skb);
878 if (err)
879 return err;
880
Florian Westphalcb9c6832017-01-23 18:21:56 +0100881 ct = (struct nf_conn *)skb_nfct(skb);
Samuel Gauthierd913d3a2016-06-28 17:22:26 +0200882 if (ct)
883 nf_ct_deliver_cached_events(ct);
884 }
Joe Stringer7f8a4362015-08-26 11:31:48 -0700885
886 return 0;
887}
888
Joe Stringer33db4122015-10-01 15:00:37 -0700889static bool labels_nonzero(const struct ovs_key_ct_labels *labels)
Joe Stringerc2ac6672015-08-26 11:31:52 -0700890{
891 size_t i;
892
Jarno Rajahalmecb80d582017-02-09 11:21:55 -0800893 for (i = 0; i < OVS_CT_LABELS_LEN_32; i++)
894 if (labels->ct_labels_32[i])
Joe Stringerc2ac6672015-08-26 11:31:52 -0700895 return true;
896
897 return false;
898}
899
Jarno Rajahalme7d904c72016-06-21 14:59:38 -0700900/* Lookup connection and confirm if unconfirmed. */
901static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
902 const struct ovs_conntrack_info *info,
903 struct sk_buff *skb)
904{
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800905 enum ip_conntrack_info ctinfo;
906 struct nf_conn *ct;
Jarno Rajahalme7d904c72016-06-21 14:59:38 -0700907 int err;
908
909 err = __ovs_ct_lookup(net, key, info, skb);
910 if (err)
911 return err;
912
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800913 /* The connection could be invalid, in which case this is a no-op.*/
914 ct = nf_ct_get(skb, &ctinfo);
915 if (!ct)
916 return 0;
917
Jarno Rajahalme7d904c72016-06-21 14:59:38 -0700918 /* Apply changes before confirming the connection so that the initial
919 * conntrack NEW netlink event carries the values given in the CT
920 * action.
921 */
922 if (info->mark.mask) {
Jarno Rajahalme6ffcea72017-02-09 11:21:57 -0800923 err = ovs_ct_set_mark(ct, key, info->mark.value,
Jarno Rajahalme7d904c72016-06-21 14:59:38 -0700924 info->mark.mask);
925 if (err)
926 return err;
927 }
Jarno Rajahalme09aa98a2017-02-09 11:21:58 -0800928 if (!nf_ct_is_confirmed(ct)) {
929 err = ovs_ct_init_labels(ct, key, &info->labels.value,
930 &info->labels.mask);
931 if (err)
932 return err;
933 } else if (labels_nonzero(&info->labels.mask)) {
934 err = ovs_ct_set_labels(ct, key, &info->labels.value,
935 &info->labels.mask);
Jarno Rajahalme7d904c72016-06-21 14:59:38 -0700936 if (err)
937 return err;
938 }
939 /* This will take care of sending queued events even if the connection
940 * is already confirmed.
941 */
942 if (nf_conntrack_confirm(skb) != NF_ACCEPT)
943 return -EINVAL;
944
945 return 0;
946}
947
Joe Stringer74c16612015-10-25 20:21:48 -0700948/* Returns 0 on success, -EINPROGRESS if 'skb' is stolen, or other nonzero
949 * value if 'skb' is freed.
950 */
Joe Stringer7f8a4362015-08-26 11:31:48 -0700951int ovs_ct_execute(struct net *net, struct sk_buff *skb,
952 struct sw_flow_key *key,
953 const struct ovs_conntrack_info *info)
954{
955 int nh_ofs;
956 int err;
957
958 /* The conntrack module expects to be working at L3. */
959 nh_ofs = skb_network_offset(skb);
Lance Richardson75f01a42017-01-12 19:33:18 -0500960 skb_pull_rcsum(skb, nh_ofs);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700961
962 if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
963 err = handle_fragments(net, key, info->zone.id, skb);
964 if (err)
965 return err;
966 }
967
Joe Stringerab38a7b2015-10-06 11:00:01 -0700968 if (info->commit)
Jarno Rajahalme7d904c72016-06-21 14:59:38 -0700969 err = ovs_ct_commit(net, key, info, skb);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700970 else
971 err = ovs_ct_lookup(net, key, info, skb);
972
973 skb_push(skb, nh_ofs);
Lance Richardson75f01a42017-01-12 19:33:18 -0500974 skb_postpush_rcsum(skb, skb->data, nh_ofs);
Joe Stringer74c16612015-10-25 20:21:48 -0700975 if (err)
976 kfree_skb(skb);
Joe Stringer7f8a4362015-08-26 11:31:48 -0700977 return err;
978}
979
Joe Stringercae3a262015-08-26 11:31:53 -0700980static int ovs_ct_add_helper(struct ovs_conntrack_info *info, const char *name,
981 const struct sw_flow_key *key, bool log)
982{
983 struct nf_conntrack_helper *helper;
984 struct nf_conn_help *help;
985
986 helper = nf_conntrack_helper_try_module_get(name, info->family,
987 key->ip.proto);
988 if (!helper) {
989 OVS_NLERR(log, "Unknown helper \"%s\"", name);
990 return -EINVAL;
991 }
992
993 help = nf_ct_helper_ext_add(info->ct, helper, GFP_KERNEL);
994 if (!help) {
995 module_put(helper->me);
996 return -ENOMEM;
997 }
998
999 rcu_assign_pointer(help->helper, helper);
1000 info->helper = helper;
1001 return 0;
1002}
1003
Jarno Rajahalme05752522016-03-10 10:54:23 -08001004#ifdef CONFIG_NF_NAT_NEEDED
1005static int parse_nat(const struct nlattr *attr,
1006 struct ovs_conntrack_info *info, bool log)
1007{
1008 struct nlattr *a;
1009 int rem;
1010 bool have_ip_max = false;
1011 bool have_proto_max = false;
1012 bool ip_vers = (info->family == NFPROTO_IPV6);
1013
1014 nla_for_each_nested(a, attr, rem) {
1015 static const int ovs_nat_attr_lens[OVS_NAT_ATTR_MAX + 1][2] = {
1016 [OVS_NAT_ATTR_SRC] = {0, 0},
1017 [OVS_NAT_ATTR_DST] = {0, 0},
1018 [OVS_NAT_ATTR_IP_MIN] = {sizeof(struct in_addr),
1019 sizeof(struct in6_addr)},
1020 [OVS_NAT_ATTR_IP_MAX] = {sizeof(struct in_addr),
1021 sizeof(struct in6_addr)},
1022 [OVS_NAT_ATTR_PROTO_MIN] = {sizeof(u16), sizeof(u16)},
1023 [OVS_NAT_ATTR_PROTO_MAX] = {sizeof(u16), sizeof(u16)},
1024 [OVS_NAT_ATTR_PERSISTENT] = {0, 0},
1025 [OVS_NAT_ATTR_PROTO_HASH] = {0, 0},
1026 [OVS_NAT_ATTR_PROTO_RANDOM] = {0, 0},
1027 };
1028 int type = nla_type(a);
1029
1030 if (type > OVS_NAT_ATTR_MAX) {
1031 OVS_NLERR(log,
1032 "Unknown NAT attribute (type=%d, max=%d).\n",
1033 type, OVS_NAT_ATTR_MAX);
1034 return -EINVAL;
1035 }
1036
1037 if (nla_len(a) != ovs_nat_attr_lens[type][ip_vers]) {
1038 OVS_NLERR(log,
1039 "NAT attribute type %d has unexpected length (%d != %d).\n",
1040 type, nla_len(a),
1041 ovs_nat_attr_lens[type][ip_vers]);
1042 return -EINVAL;
1043 }
1044
1045 switch (type) {
1046 case OVS_NAT_ATTR_SRC:
1047 case OVS_NAT_ATTR_DST:
1048 if (info->nat) {
1049 OVS_NLERR(log,
1050 "Only one type of NAT may be specified.\n"
1051 );
1052 return -ERANGE;
1053 }
1054 info->nat |= OVS_CT_NAT;
1055 info->nat |= ((type == OVS_NAT_ATTR_SRC)
1056 ? OVS_CT_SRC_NAT : OVS_CT_DST_NAT);
1057 break;
1058
1059 case OVS_NAT_ATTR_IP_MIN:
Haishuang Yanac71b462016-03-28 18:08:59 +08001060 nla_memcpy(&info->range.min_addr, a,
1061 sizeof(info->range.min_addr));
Jarno Rajahalme05752522016-03-10 10:54:23 -08001062 info->range.flags |= NF_NAT_RANGE_MAP_IPS;
1063 break;
1064
1065 case OVS_NAT_ATTR_IP_MAX:
1066 have_ip_max = true;
1067 nla_memcpy(&info->range.max_addr, a,
1068 sizeof(info->range.max_addr));
1069 info->range.flags |= NF_NAT_RANGE_MAP_IPS;
1070 break;
1071
1072 case OVS_NAT_ATTR_PROTO_MIN:
1073 info->range.min_proto.all = htons(nla_get_u16(a));
1074 info->range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
1075 break;
1076
1077 case OVS_NAT_ATTR_PROTO_MAX:
1078 have_proto_max = true;
1079 info->range.max_proto.all = htons(nla_get_u16(a));
1080 info->range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
1081 break;
1082
1083 case OVS_NAT_ATTR_PERSISTENT:
1084 info->range.flags |= NF_NAT_RANGE_PERSISTENT;
1085 break;
1086
1087 case OVS_NAT_ATTR_PROTO_HASH:
1088 info->range.flags |= NF_NAT_RANGE_PROTO_RANDOM;
1089 break;
1090
1091 case OVS_NAT_ATTR_PROTO_RANDOM:
1092 info->range.flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
1093 break;
1094
1095 default:
1096 OVS_NLERR(log, "Unknown nat attribute (%d).\n", type);
1097 return -EINVAL;
1098 }
1099 }
1100
1101 if (rem > 0) {
1102 OVS_NLERR(log, "NAT attribute has %d unknown bytes.\n", rem);
1103 return -EINVAL;
1104 }
1105 if (!info->nat) {
1106 /* Do not allow flags if no type is given. */
1107 if (info->range.flags) {
1108 OVS_NLERR(log,
1109 "NAT flags may be given only when NAT range (SRC or DST) is also specified.\n"
1110 );
1111 return -EINVAL;
1112 }
1113 info->nat = OVS_CT_NAT; /* NAT existing connections. */
1114 } else if (!info->commit) {
1115 OVS_NLERR(log,
1116 "NAT attributes may be specified only when CT COMMIT flag is also specified.\n"
1117 );
1118 return -EINVAL;
1119 }
1120 /* Allow missing IP_MAX. */
1121 if (info->range.flags & NF_NAT_RANGE_MAP_IPS && !have_ip_max) {
1122 memcpy(&info->range.max_addr, &info->range.min_addr,
1123 sizeof(info->range.max_addr));
1124 }
1125 /* Allow missing PROTO_MAX. */
1126 if (info->range.flags & NF_NAT_RANGE_PROTO_SPECIFIED &&
1127 !have_proto_max) {
1128 info->range.max_proto.all = info->range.min_proto.all;
1129 }
1130 return 0;
1131}
1132#endif
1133
Joe Stringer7f8a4362015-08-26 11:31:48 -07001134static const struct ovs_ct_len_tbl ovs_ct_attr_lens[OVS_CT_ATTR_MAX + 1] = {
Joe Stringerab38a7b2015-10-06 11:00:01 -07001135 [OVS_CT_ATTR_COMMIT] = { .minlen = 0, .maxlen = 0 },
Joe Stringer7f8a4362015-08-26 11:31:48 -07001136 [OVS_CT_ATTR_ZONE] = { .minlen = sizeof(u16),
1137 .maxlen = sizeof(u16) },
Joe Stringer182e3042015-08-26 11:31:49 -07001138 [OVS_CT_ATTR_MARK] = { .minlen = sizeof(struct md_mark),
1139 .maxlen = sizeof(struct md_mark) },
Joe Stringer33db4122015-10-01 15:00:37 -07001140 [OVS_CT_ATTR_LABELS] = { .minlen = sizeof(struct md_labels),
1141 .maxlen = sizeof(struct md_labels) },
Joe Stringercae3a262015-08-26 11:31:53 -07001142 [OVS_CT_ATTR_HELPER] = { .minlen = 1,
Jarno Rajahalme05752522016-03-10 10:54:23 -08001143 .maxlen = NF_CT_HELPER_NAME_LEN },
1144#ifdef CONFIG_NF_NAT_NEEDED
1145 /* NAT length is checked when parsing the nested attributes. */
1146 [OVS_CT_ATTR_NAT] = { .minlen = 0, .maxlen = INT_MAX },
1147#endif
Joe Stringer7f8a4362015-08-26 11:31:48 -07001148};
1149
1150static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
Joe Stringercae3a262015-08-26 11:31:53 -07001151 const char **helper, bool log)
Joe Stringer7f8a4362015-08-26 11:31:48 -07001152{
1153 struct nlattr *a;
1154 int rem;
1155
1156 nla_for_each_nested(a, attr, rem) {
1157 int type = nla_type(a);
1158 int maxlen = ovs_ct_attr_lens[type].maxlen;
1159 int minlen = ovs_ct_attr_lens[type].minlen;
1160
1161 if (type > OVS_CT_ATTR_MAX) {
1162 OVS_NLERR(log,
1163 "Unknown conntrack attr (type=%d, max=%d)",
1164 type, OVS_CT_ATTR_MAX);
1165 return -EINVAL;
1166 }
1167 if (nla_len(a) < minlen || nla_len(a) > maxlen) {
1168 OVS_NLERR(log,
1169 "Conntrack attr type has unexpected length (type=%d, length=%d, expected=%d)",
1170 type, nla_len(a), maxlen);
1171 return -EINVAL;
1172 }
1173
1174 switch (type) {
Joe Stringerab38a7b2015-10-06 11:00:01 -07001175 case OVS_CT_ATTR_COMMIT:
1176 info->commit = true;
Joe Stringer7f8a4362015-08-26 11:31:48 -07001177 break;
1178#ifdef CONFIG_NF_CONNTRACK_ZONES
1179 case OVS_CT_ATTR_ZONE:
1180 info->zone.id = nla_get_u16(a);
1181 break;
1182#endif
Joe Stringer182e3042015-08-26 11:31:49 -07001183#ifdef CONFIG_NF_CONNTRACK_MARK
1184 case OVS_CT_ATTR_MARK: {
1185 struct md_mark *mark = nla_data(a);
1186
Joe Stringere754ec62015-10-19 19:19:00 -07001187 if (!mark->mask) {
1188 OVS_NLERR(log, "ct_mark mask cannot be 0");
1189 return -EINVAL;
1190 }
Joe Stringer182e3042015-08-26 11:31:49 -07001191 info->mark = *mark;
1192 break;
1193 }
1194#endif
Joe Stringerc2ac6672015-08-26 11:31:52 -07001195#ifdef CONFIG_NF_CONNTRACK_LABELS
Joe Stringer33db4122015-10-01 15:00:37 -07001196 case OVS_CT_ATTR_LABELS: {
1197 struct md_labels *labels = nla_data(a);
Joe Stringerc2ac6672015-08-26 11:31:52 -07001198
Joe Stringere754ec62015-10-19 19:19:00 -07001199 if (!labels_nonzero(&labels->mask)) {
1200 OVS_NLERR(log, "ct_labels mask cannot be 0");
1201 return -EINVAL;
1202 }
Joe Stringer33db4122015-10-01 15:00:37 -07001203 info->labels = *labels;
Joe Stringerc2ac6672015-08-26 11:31:52 -07001204 break;
1205 }
1206#endif
Joe Stringercae3a262015-08-26 11:31:53 -07001207 case OVS_CT_ATTR_HELPER:
1208 *helper = nla_data(a);
1209 if (!memchr(*helper, '\0', nla_len(a))) {
1210 OVS_NLERR(log, "Invalid conntrack helper");
1211 return -EINVAL;
1212 }
1213 break;
Jarno Rajahalme05752522016-03-10 10:54:23 -08001214#ifdef CONFIG_NF_NAT_NEEDED
1215 case OVS_CT_ATTR_NAT: {
1216 int err = parse_nat(a, info, log);
1217
1218 if (err)
1219 return err;
1220 break;
1221 }
1222#endif
Joe Stringer7f8a4362015-08-26 11:31:48 -07001223 default:
1224 OVS_NLERR(log, "Unknown conntrack attr (%d)",
1225 type);
1226 return -EINVAL;
1227 }
1228 }
1229
Jarno Rajahalme7d904c72016-06-21 14:59:38 -07001230#ifdef CONFIG_NF_CONNTRACK_MARK
1231 if (!info->commit && info->mark.mask) {
1232 OVS_NLERR(log,
1233 "Setting conntrack mark requires 'commit' flag.");
1234 return -EINVAL;
1235 }
1236#endif
1237#ifdef CONFIG_NF_CONNTRACK_LABELS
1238 if (!info->commit && labels_nonzero(&info->labels.mask)) {
1239 OVS_NLERR(log,
1240 "Setting conntrack labels requires 'commit' flag.");
1241 return -EINVAL;
1242 }
1243#endif
Joe Stringer7f8a4362015-08-26 11:31:48 -07001244 if (rem > 0) {
1245 OVS_NLERR(log, "Conntrack attr has %d unknown bytes", rem);
1246 return -EINVAL;
1247 }
1248
1249 return 0;
1250}
1251
Joe Stringerc2ac6672015-08-26 11:31:52 -07001252bool ovs_ct_verify(struct net *net, enum ovs_key_attr attr)
Joe Stringer7f8a4362015-08-26 11:31:48 -07001253{
1254 if (attr == OVS_KEY_ATTR_CT_STATE)
1255 return true;
1256 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
1257 attr == OVS_KEY_ATTR_CT_ZONE)
1258 return true;
Joe Stringer182e3042015-08-26 11:31:49 -07001259 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) &&
1260 attr == OVS_KEY_ATTR_CT_MARK)
1261 return true;
Joe Stringerc2ac6672015-08-26 11:31:52 -07001262 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
Joe Stringer33db4122015-10-01 15:00:37 -07001263 attr == OVS_KEY_ATTR_CT_LABELS) {
Joe Stringerc2ac6672015-08-26 11:31:52 -07001264 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
1265
1266 return ovs_net->xt_label;
1267 }
Joe Stringer7f8a4362015-08-26 11:31:48 -07001268
1269 return false;
1270}
1271
1272int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
1273 const struct sw_flow_key *key,
1274 struct sw_flow_actions **sfa, bool log)
1275{
1276 struct ovs_conntrack_info ct_info;
Joe Stringercae3a262015-08-26 11:31:53 -07001277 const char *helper = NULL;
Joe Stringer7f8a4362015-08-26 11:31:48 -07001278 u16 family;
1279 int err;
1280
1281 family = key_to_nfproto(key);
1282 if (family == NFPROTO_UNSPEC) {
1283 OVS_NLERR(log, "ct family unspecified");
1284 return -EINVAL;
1285 }
1286
1287 memset(&ct_info, 0, sizeof(ct_info));
1288 ct_info.family = family;
1289
1290 nf_ct_zone_init(&ct_info.zone, NF_CT_DEFAULT_ZONE_ID,
1291 NF_CT_DEFAULT_ZONE_DIR, 0);
1292
Joe Stringercae3a262015-08-26 11:31:53 -07001293 err = parse_ct(attr, &ct_info, &helper, log);
Joe Stringer7f8a4362015-08-26 11:31:48 -07001294 if (err)
1295 return err;
1296
1297 /* Set up template for tracking connections in specific zones. */
1298 ct_info.ct = nf_ct_tmpl_alloc(net, &ct_info.zone, GFP_KERNEL);
1299 if (!ct_info.ct) {
1300 OVS_NLERR(log, "Failed to allocate conntrack template");
1301 return -ENOMEM;
1302 }
Joe Stringer90c7afc962015-12-23 14:39:27 -08001303
1304 __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
1305 nf_conntrack_get(&ct_info.ct->ct_general);
1306
Joe Stringercae3a262015-08-26 11:31:53 -07001307 if (helper) {
1308 err = ovs_ct_add_helper(&ct_info, helper, key, log);
1309 if (err)
1310 goto err_free_ct;
1311 }
Joe Stringer7f8a4362015-08-26 11:31:48 -07001312
1313 err = ovs_nla_add_action(sfa, OVS_ACTION_ATTR_CT, &ct_info,
1314 sizeof(ct_info), log);
1315 if (err)
1316 goto err_free_ct;
1317
Joe Stringer7f8a4362015-08-26 11:31:48 -07001318 return 0;
1319err_free_ct:
Joe Stringer2f3ab9f2015-12-09 14:07:39 -08001320 __ovs_ct_free_action(&ct_info);
Joe Stringer7f8a4362015-08-26 11:31:48 -07001321 return err;
1322}
1323
Jarno Rajahalme05752522016-03-10 10:54:23 -08001324#ifdef CONFIG_NF_NAT_NEEDED
1325static bool ovs_ct_nat_to_attr(const struct ovs_conntrack_info *info,
1326 struct sk_buff *skb)
1327{
1328 struct nlattr *start;
1329
1330 start = nla_nest_start(skb, OVS_CT_ATTR_NAT);
1331 if (!start)
1332 return false;
1333
1334 if (info->nat & OVS_CT_SRC_NAT) {
1335 if (nla_put_flag(skb, OVS_NAT_ATTR_SRC))
1336 return false;
1337 } else if (info->nat & OVS_CT_DST_NAT) {
1338 if (nla_put_flag(skb, OVS_NAT_ATTR_DST))
1339 return false;
1340 } else {
1341 goto out;
1342 }
1343
1344 if (info->range.flags & NF_NAT_RANGE_MAP_IPS) {
Arnd Bergmann99b72482016-03-18 14:33:45 +01001345 if (IS_ENABLED(CONFIG_NF_NAT_IPV4) &&
1346 info->family == NFPROTO_IPV4) {
Jarno Rajahalme05752522016-03-10 10:54:23 -08001347 if (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MIN,
1348 info->range.min_addr.ip) ||
1349 (info->range.max_addr.ip
1350 != info->range.min_addr.ip &&
1351 (nla_put_in_addr(skb, OVS_NAT_ATTR_IP_MAX,
1352 info->range.max_addr.ip))))
1353 return false;
Arnd Bergmann99b72482016-03-18 14:33:45 +01001354 } else if (IS_ENABLED(CONFIG_NF_NAT_IPV6) &&
1355 info->family == NFPROTO_IPV6) {
Jarno Rajahalme05752522016-03-10 10:54:23 -08001356 if (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MIN,
1357 &info->range.min_addr.in6) ||
1358 (memcmp(&info->range.max_addr.in6,
1359 &info->range.min_addr.in6,
1360 sizeof(info->range.max_addr.in6)) &&
1361 (nla_put_in6_addr(skb, OVS_NAT_ATTR_IP_MAX,
1362 &info->range.max_addr.in6))))
1363 return false;
Jarno Rajahalme05752522016-03-10 10:54:23 -08001364 } else {
1365 return false;
1366 }
1367 }
1368 if (info->range.flags & NF_NAT_RANGE_PROTO_SPECIFIED &&
1369 (nla_put_u16(skb, OVS_NAT_ATTR_PROTO_MIN,
1370 ntohs(info->range.min_proto.all)) ||
1371 (info->range.max_proto.all != info->range.min_proto.all &&
1372 nla_put_u16(skb, OVS_NAT_ATTR_PROTO_MAX,
1373 ntohs(info->range.max_proto.all)))))
1374 return false;
1375
1376 if (info->range.flags & NF_NAT_RANGE_PERSISTENT &&
1377 nla_put_flag(skb, OVS_NAT_ATTR_PERSISTENT))
1378 return false;
1379 if (info->range.flags & NF_NAT_RANGE_PROTO_RANDOM &&
1380 nla_put_flag(skb, OVS_NAT_ATTR_PROTO_HASH))
1381 return false;
1382 if (info->range.flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY &&
1383 nla_put_flag(skb, OVS_NAT_ATTR_PROTO_RANDOM))
1384 return false;
1385out:
1386 nla_nest_end(skb, start);
1387
1388 return true;
1389}
1390#endif
1391
Joe Stringer7f8a4362015-08-26 11:31:48 -07001392int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info,
1393 struct sk_buff *skb)
1394{
1395 struct nlattr *start;
1396
1397 start = nla_nest_start(skb, OVS_ACTION_ATTR_CT);
1398 if (!start)
1399 return -EMSGSIZE;
1400
Joe Stringerab38a7b2015-10-06 11:00:01 -07001401 if (ct_info->commit && nla_put_flag(skb, OVS_CT_ATTR_COMMIT))
Joe Stringer7f8a4362015-08-26 11:31:48 -07001402 return -EMSGSIZE;
1403 if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) &&
1404 nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id))
1405 return -EMSGSIZE;
Joe Stringere754ec62015-10-19 19:19:00 -07001406 if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask &&
Joe Stringer182e3042015-08-26 11:31:49 -07001407 nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark),
1408 &ct_info->mark))
1409 return -EMSGSIZE;
Joe Stringerc2ac6672015-08-26 11:31:52 -07001410 if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) &&
Joe Stringere754ec62015-10-19 19:19:00 -07001411 labels_nonzero(&ct_info->labels.mask) &&
Joe Stringer33db4122015-10-01 15:00:37 -07001412 nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels),
1413 &ct_info->labels))
Joe Stringerc2ac6672015-08-26 11:31:52 -07001414 return -EMSGSIZE;
Joe Stringercae3a262015-08-26 11:31:53 -07001415 if (ct_info->helper) {
1416 if (nla_put_string(skb, OVS_CT_ATTR_HELPER,
1417 ct_info->helper->name))
1418 return -EMSGSIZE;
1419 }
Jarno Rajahalme05752522016-03-10 10:54:23 -08001420#ifdef CONFIG_NF_NAT_NEEDED
1421 if (ct_info->nat && !ovs_ct_nat_to_attr(ct_info, skb))
1422 return -EMSGSIZE;
1423#endif
Joe Stringer7f8a4362015-08-26 11:31:48 -07001424 nla_nest_end(skb, start);
1425
1426 return 0;
1427}
1428
1429void ovs_ct_free_action(const struct nlattr *a)
1430{
1431 struct ovs_conntrack_info *ct_info = nla_data(a);
1432
Joe Stringer2f3ab9f2015-12-09 14:07:39 -08001433 __ovs_ct_free_action(ct_info);
1434}
1435
1436static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
1437{
Joe Stringercae3a262015-08-26 11:31:53 -07001438 if (ct_info->helper)
1439 module_put(ct_info->helper->me);
Joe Stringer7f8a4362015-08-26 11:31:48 -07001440 if (ct_info->ct)
Joe Stringer76644232016-09-01 18:01:47 -07001441 nf_ct_tmpl_free(ct_info->ct);
Joe Stringer7f8a4362015-08-26 11:31:48 -07001442}
Joe Stringerc2ac6672015-08-26 11:31:52 -07001443
1444void ovs_ct_init(struct net *net)
1445{
Joe Stringer33db4122015-10-01 15:00:37 -07001446 unsigned int n_bits = sizeof(struct ovs_key_ct_labels) * BITS_PER_BYTE;
Joe Stringerc2ac6672015-08-26 11:31:52 -07001447 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
1448
Florian Westphaladff6c62016-04-12 18:14:25 +02001449 if (nf_connlabels_get(net, n_bits - 1)) {
Joe Stringerc2ac6672015-08-26 11:31:52 -07001450 ovs_net->xt_label = false;
1451 OVS_NLERR(true, "Failed to set connlabel length");
1452 } else {
1453 ovs_net->xt_label = true;
1454 }
1455}
1456
1457void ovs_ct_exit(struct net *net)
1458{
1459 struct ovs_net *ovs_net = net_generic(net, ovs_net_id);
1460
1461 if (ovs_net->xt_label)
1462 nf_connlabels_put(net);
1463}