]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_pbr.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / zebra / zebra_pbr.c
CommitLineData
942bf97b 1/* Zebra Policy Based Routing (PBR) main handling.
2 * Copyright (C) 2018 Cumulus Networks, Inc.
3 *
4 * This file is part of FRR.
5 *
6 * FRR is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * FRR is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with FRR; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#include <zebra.h>
23
43fe6a2a
DS
24#include <jhash.h>
25#include <hash.h>
f80ec7e3 26#include <memory.h>
73a829f7 27#include <hook.h>
43fe6a2a 28
7f0ea8a4 29#include "zebra/zebra_router.h"
942bf97b 30#include "zebra/zebra_pbr.h"
31#include "zebra/rt.h"
bf094f69 32#include "zebra/zapi_msg.h"
f80ec7e3 33#include "zebra/zebra_memory.h"
c0ea1ae7 34#include "zebra/zserv.h"
f80ec7e3
PG
35
36/* definitions */
37DEFINE_MTYPE_STATIC(ZEBRA, PBR_IPTABLE_IFNAME, "PBR interface list")
942bf97b 38
39/* definitions */
586f4ccf
PG
40static const struct message ipset_type_msg[] = {
41 {IPSET_NET_PORT_NET, "net,port,net"},
42 {IPSET_NET_PORT, "net,port"},
43 {IPSET_NET_NET, "net,net"},
44 {IPSET_NET, "net"},
45 {0}
46};
942bf97b 47
be729dd7
PG
48const struct message icmp_typecode_str[] = {
49 { 0 << 8, "echo-reply"},
50 { 0 << 8, "pong"},
51 { 3 << 8, "network-unreachable"},
52 { (3 << 8) + 1, "host-unreachable"},
53 { (3 << 8) + 2, "protocol-unreachable"},
54 { (3 << 8) + 3, "port-unreachable"},
55 { (3 << 8) + 4, "fragmentation-needed"},
56 { (3 << 8) + 5, "source-route-failed"},
57 { (3 << 8) + 6, "network-unknown"},
58 { (3 << 8) + 7, "host-unknown"},
59 { (3 << 8) + 9, "network-prohibited"},
60 { (3 << 8) + 10, "host-prohibited"},
61 { (3 << 8) + 11, "TOS-network-unreachable"},
62 { (3 << 8) + 12, "TOS-host-unreachable"},
63 { (3 << 8) + 13, "communication-prohibited"},
64 { (3 << 8) + 14, "host-precedence-violation"},
65 { (3 << 8) + 15, "precedence-cutoff"},
66 { 4 << 8, "source-quench"},
67 { 5 << 8, "network-redirect"},
68 { (5 << 8) + 1, "host-redirect"},
69 { (5 << 8) + 2, "TOS-network-redirect"},
70 { (5 << 8) + 3, "TOS-host-redirect"},
71 { 8 << 8, "echo-request"},
72 { 8 << 8, "ping"},
73 { 9 << 8, "router-advertisement"},
74 { 10 << 8, "router-solicitation"},
75 { 11 << 8, "ttl-zero-during-transit"},
76 { (11 << 8) + 1, "ttl-zero-during-reassembly"},
77 { 12 << 8, "ip-header-bad"},
78 { (12 << 8) + 1, "required-option-missing"},
79 { 13 << 8, "timestamp-request"},
80 { 14 << 8, "timestamp-reply"},
81 { 17 << 8, "address-mask-request"},
82 { 18 << 8, "address-mask-reply"},
83 {0}
84};
85
dc993e76
PG
86/* definitions */
87static const struct message tcp_value_str[] = {
88 {TCP_HEADER_FIN, "FIN"},
89 {TCP_HEADER_SYN, "SYN"},
90 {TCP_HEADER_RST, "RST"},
91 {TCP_HEADER_PSH, "PSH"},
92 {TCP_HEADER_ACK, "ACK"},
93 {TCP_HEADER_URG, "URG"},
94 {0}
95};
96
5ac5b7cc
PG
97static const struct message fragment_value_str[] = {
98 {1, "dont-fragment"},
99 {2, "is-fragment"},
100 {4, "first-fragment"},
101 {8, "last-fragment"},
102 {0}
103};
104
942bf97b 105/* static function declarations */
1c6fca1f 106DEFINE_HOOK(zebra_pbr_ipset_entry_get_stat,
62f20a52
DS
107 (struct zebra_pbr_ipset_entry *ipset, uint64_t *pkts,
108 uint64_t *bytes),
109 (ipset, pkts, bytes))
110
1c6fca1f 111DEFINE_HOOK(zebra_pbr_iptable_get_stat,
62f20a52
DS
112 (struct zebra_pbr_iptable *iptable, uint64_t *pkts,
113 uint64_t *bytes),
114 (iptable, pkts, bytes))
115
1c6fca1f 116DEFINE_HOOK(zebra_pbr_iptable_update,
62f20a52
DS
117 (int cmd, struct zebra_pbr_iptable *iptable), (cmd, iptable));
118
1c6fca1f 119DEFINE_HOOK(zebra_pbr_ipset_entry_update,
62f20a52
DS
120 (int cmd, struct zebra_pbr_ipset_entry *ipset), (cmd, ipset));
121
1c6fca1f 122DEFINE_HOOK(zebra_pbr_ipset_update,
62f20a52 123 (int cmd, struct zebra_pbr_ipset *ipset), (cmd, ipset));
942bf97b 124
125/* Private functions */
126
127/* Public functions */
43fe6a2a 128void zebra_pbr_rules_free(void *arg)
1fbfe5a5 129{
43fe6a2a
DS
130 struct zebra_pbr_rule *rule;
131
132 rule = (struct zebra_pbr_rule *)arg;
133
ebecd649 134 (void)kernel_del_pbr_rule(rule);
43fe6a2a
DS
135 XFREE(MTYPE_TMP, rule);
136}
137
138uint32_t zebra_pbr_rules_hash_key(void *arg)
139{
140 struct zebra_pbr_rule *rule;
141 uint32_t key;
142
143 rule = (struct zebra_pbr_rule *)arg;
5dd0722d
PG
144 key = jhash_3words(rule->rule.seq, rule->rule.priority,
145 rule->rule.action.table,
146 prefix_hash_key(&rule->rule.filter.src_ip));
a0321978
DS
147 if (rule->ifp)
148 key = jhash_1word(rule->ifp->ifindex, key);
149 else
150 key = jhash_1word(0, key);
151
5dd0722d
PG
152 if (rule->rule.filter.fwmark)
153 key = jhash_1word(rule->rule.filter.fwmark, key);
1907e4b8
PG
154 else
155 key = jhash_1word(0, key);
7f0ea8a4
DS
156
157 key = jhash_1word(rule->vrf_id, key);
158
5dd0722d
PG
159 return jhash_3words(rule->rule.filter.src_port,
160 rule->rule.filter.dst_port,
161 prefix_hash_key(&rule->rule.filter.dst_ip),
162 jhash_1word(rule->rule.unique, key));
43fe6a2a
DS
163}
164
74df8d6d 165bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
43fe6a2a
DS
166{
167 const struct zebra_pbr_rule *r1, *r2;
168
169 r1 = (const struct zebra_pbr_rule *)arg1;
170 r2 = (const struct zebra_pbr_rule *)arg2;
171
5dd0722d 172 if (r1->rule.seq != r2->rule.seq)
74df8d6d 173 return false;
43fe6a2a 174
5dd0722d 175 if (r1->rule.priority != r2->rule.priority)
74df8d6d 176 return false;
43fe6a2a 177
5dd0722d 178 if (r1->rule.unique != r2->rule.unique)
74df8d6d 179 return false;
b6c5d343 180
5dd0722d 181 if (r1->rule.action.table != r2->rule.action.table)
74df8d6d 182 return false;
43fe6a2a 183
5dd0722d 184 if (r1->rule.filter.src_port != r2->rule.filter.src_port)
74df8d6d 185 return false;
43fe6a2a 186
5dd0722d 187 if (r1->rule.filter.dst_port != r2->rule.filter.dst_port)
74df8d6d 188 return false;
43fe6a2a 189
5dd0722d 190 if (r1->rule.filter.fwmark != r2->rule.filter.fwmark)
74df8d6d 191 return false;
1907e4b8 192
5dd0722d 193 if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip))
74df8d6d 194 return false;
43fe6a2a 195
5dd0722d 196 if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip))
74df8d6d 197 return false;
43fe6a2a 198
a0321978 199 if (r1->ifp != r2->ifp)
74df8d6d 200 return false;
a0321978 201
7f0ea8a4
DS
202 if (r1->vrf_id != r2->vrf_id)
203 return false;
204
74df8d6d 205 return true;
43fe6a2a
DS
206}
207
f46bbab4 208struct pbr_rule_unique_lookup {
8c3cd6c6
DS
209 struct zebra_pbr_rule *rule;
210 uint32_t unique;
37c606ff 211 struct interface *ifp;
7f0ea8a4 212 vrf_id_t vrf_id;
8c3cd6c6
DS
213};
214
215static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data)
216{
f46bbab4 217 struct pbr_rule_unique_lookup *pul = data;
8c3cd6c6
DS
218 struct zebra_pbr_rule *rule = b->data;
219
7f0ea8a4
DS
220 if (pul->unique == rule->rule.unique
221 && pul->ifp == rule->ifp
222 && pul->vrf_id == rule->vrf_id) {
8c3cd6c6
DS
223 pul->rule = rule;
224 return HASHWALK_ABORT;
225 }
226
227 return HASHWALK_CONTINUE;
228}
229
62f20a52
DS
230static struct zebra_pbr_rule *
231pbr_rule_lookup_unique(struct zebra_pbr_rule *zrule)
8c3cd6c6 232{
f46bbab4 233 struct pbr_rule_unique_lookup pul;
8c3cd6c6 234
7f0ea8a4
DS
235 pul.unique = zrule->rule.unique;
236 pul.ifp = zrule->ifp;
8c3cd6c6 237 pul.rule = NULL;
7f0ea8a4
DS
238 pul.vrf_id = zrule->vrf_id;
239 hash_walk(zrouter.rules_hash, &pbr_rule_lookup_unique_walker, &pul);
8c3cd6c6
DS
240
241 return pul.rule;
242}
243
7661461a
PG
244void zebra_pbr_ipset_free(void *arg)
245{
246 struct zebra_pbr_ipset *ipset;
247
248 ipset = (struct zebra_pbr_ipset *)arg;
1c6fca1f 249 hook_call(zebra_pbr_ipset_update, 0, ipset);
7661461a
PG
250 XFREE(MTYPE_TMP, ipset);
251}
252
253uint32_t zebra_pbr_ipset_hash_key(void *arg)
254{
255 struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg;
425bdd6b 256 uint32_t *pnt = (uint32_t *)&ipset->ipset_name;
62f20a52 257 uint32_t key = jhash_1word(ipset->vrf_id, 0x63ab42de);
7661461a 258
62f20a52 259 return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, key);
7661461a
PG
260}
261
74df8d6d 262bool zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2)
7661461a
PG
263{
264 const struct zebra_pbr_ipset *r1, *r2;
265
266 r1 = (const struct zebra_pbr_ipset *)arg1;
267 r2 = (const struct zebra_pbr_ipset *)arg2;
268
269 if (r1->type != r2->type)
74df8d6d 270 return false;
7661461a 271 if (r1->unique != r2->unique)
74df8d6d 272 return false;
62f20a52
DS
273 if (r1->vrf_id != r2->vrf_id)
274 return false;
275
7661461a
PG
276 if (strncmp(r1->ipset_name, r2->ipset_name,
277 ZEBRA_IPSET_NAME_SIZE))
74df8d6d
DS
278 return false;
279 return true;
7661461a
PG
280}
281
282void zebra_pbr_ipset_entry_free(void *arg)
283{
284 struct zebra_pbr_ipset_entry *ipset;
285
286 ipset = (struct zebra_pbr_ipset_entry *)arg;
73a829f7 287
1c6fca1f 288 hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
7661461a
PG
289
290 XFREE(MTYPE_TMP, ipset);
291}
292
293uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
294{
295 struct zebra_pbr_ipset_entry *ipset;
296 uint32_t key;
297
298 ipset = (struct zebra_pbr_ipset_entry *)arg;
299 key = prefix_hash_key(&ipset->src);
300 key = jhash_1word(ipset->unique, key);
301 key = jhash_1word(prefix_hash_key(&ipset->dst), key);
25d760c5
PG
302 key = jhash(&ipset->dst_port_min, 2, key);
303 key = jhash(&ipset->dst_port_max, 2, key);
304 key = jhash(&ipset->src_port_min, 2, key);
305 key = jhash(&ipset->src_port_max, 2, key);
306 key = jhash(&ipset->proto, 1, key);
7661461a
PG
307
308 return key;
309}
310
74df8d6d 311bool zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
7661461a
PG
312{
313 const struct zebra_pbr_ipset_entry *r1, *r2;
314
315 r1 = (const struct zebra_pbr_ipset_entry *)arg1;
316 r2 = (const struct zebra_pbr_ipset_entry *)arg2;
317
318 if (r1->unique != r2->unique)
74df8d6d 319 return false;
7661461a
PG
320
321 if (!prefix_same(&r1->src, &r2->src))
74df8d6d 322 return false;
7661461a
PG
323
324 if (!prefix_same(&r1->dst, &r2->dst))
74df8d6d 325 return false;
7661461a 326
25d760c5 327 if (r1->src_port_min != r2->src_port_min)
74df8d6d 328 return false;
25d760c5
PG
329
330 if (r1->src_port_max != r2->src_port_max)
74df8d6d 331 return false;
25d760c5
PG
332
333 if (r1->dst_port_min != r2->dst_port_min)
74df8d6d 334 return false;
25d760c5
PG
335
336 if (r1->dst_port_max != r2->dst_port_max)
74df8d6d 337 return false;
25d760c5
PG
338
339 if (r1->proto != r2->proto)
74df8d6d
DS
340 return false;
341 return true;
7661461a
PG
342}
343
7abd6c4f
PG
344void zebra_pbr_iptable_free(void *arg)
345{
346 struct zebra_pbr_iptable *iptable;
f80ec7e3
PG
347 struct listnode *node, *nnode;
348 char *name;
7abd6c4f
PG
349
350 iptable = (struct zebra_pbr_iptable *)arg;
1c6fca1f 351 hook_call(zebra_pbr_iptable_update, 0, iptable);
7abd6c4f 352
f80ec7e3
PG
353 for (ALL_LIST_ELEMENTS(iptable->interface_name_list,
354 node, nnode, name)) {
355 XFREE(MTYPE_PBR_IPTABLE_IFNAME, name);
356 list_delete_node(iptable->interface_name_list,
357 node);
358 }
7abd6c4f
PG
359 XFREE(MTYPE_TMP, iptable);
360}
361
362uint32_t zebra_pbr_iptable_hash_key(void *arg)
363{
364 struct zebra_pbr_iptable *iptable = (struct zebra_pbr_iptable *)arg;
365 uint32_t *pnt = (uint32_t *)&(iptable->ipset_name);
366 uint32_t key;
367
368 key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE,
369 0x63ab42de);
370 key = jhash_1word(iptable->fwmark, key);
e7f7dad4
PG
371 key = jhash_1word(iptable->pkt_len_min, key);
372 key = jhash_1word(iptable->pkt_len_max, key);
dc993e76
PG
373 key = jhash_1word(iptable->tcp_flags, key);
374 key = jhash_1word(iptable->tcp_mask_flags, key);
4977bd6c 375 key = jhash_1word(iptable->dscp_value, key);
5ac5b7cc 376 key = jhash_1word(iptable->fragment, key);
62f20a52
DS
377 key = jhash_1word(iptable->vrf_id, key);
378
7abd6c4f
PG
379 return jhash_3words(iptable->filter_bm, iptable->type,
380 iptable->unique, key);
381}
382
74df8d6d 383bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
7abd6c4f
PG
384{
385 const struct zebra_pbr_iptable *r1, *r2;
386
387 r1 = (const struct zebra_pbr_iptable *)arg1;
388 r2 = (const struct zebra_pbr_iptable *)arg2;
389
62f20a52
DS
390 if (r1->vrf_id != r2->vrf_id)
391 return 0;
7abd6c4f 392 if (r1->type != r2->type)
74df8d6d 393 return false;
7abd6c4f 394 if (r1->unique != r2->unique)
74df8d6d 395 return false;
7abd6c4f 396 if (r1->filter_bm != r2->filter_bm)
74df8d6d 397 return false;
7abd6c4f 398 if (r1->fwmark != r2->fwmark)
74df8d6d 399 return false;
7abd6c4f 400 if (r1->action != r2->action)
74df8d6d 401 return false;
7abd6c4f
PG
402 if (strncmp(r1->ipset_name, r2->ipset_name,
403 ZEBRA_IPSET_NAME_SIZE))
74df8d6d 404 return false;
e7f7dad4 405 if (r1->pkt_len_min != r2->pkt_len_min)
74df8d6d 406 return false;
e7f7dad4 407 if (r1->pkt_len_max != r2->pkt_len_max)
74df8d6d 408 return false;
dc993e76 409 if (r1->tcp_flags != r2->tcp_flags)
74df8d6d 410 return false;
dc993e76 411 if (r1->tcp_mask_flags != r2->tcp_mask_flags)
74df8d6d 412 return false;
4977bd6c 413 if (r1->dscp_value != r2->dscp_value)
74df8d6d 414 return false;
5ac5b7cc 415 if (r1->fragment != r2->fragment)
74df8d6d
DS
416 return false;
417 return true;
7abd6c4f
PG
418}
419
43fe6a2a
DS
420static void *pbr_rule_alloc_intern(void *arg)
421{
422 struct zebra_pbr_rule *zpr;
423 struct zebra_pbr_rule *new;
424
425 zpr = (struct zebra_pbr_rule *)arg;
426
427 new = XCALLOC(MTYPE_TMP, sizeof(*new));
428
429 memcpy(new, zpr, sizeof(*zpr));
430
431 return new;
432}
433
7f0ea8a4 434void zebra_pbr_add_rule(struct zebra_pbr_rule *rule)
43fe6a2a 435{
8c3cd6c6 436 struct zebra_pbr_rule *unique =
7f0ea8a4 437 pbr_rule_lookup_unique(rule);
8c3cd6c6 438
7f0ea8a4 439 (void)hash_get(zrouter.rules_hash, rule, pbr_rule_alloc_intern);
ebecd649 440 (void)kernel_add_pbr_rule(rule);
8c3cd6c6
DS
441 /*
442 * Rule Replace semantics, if we have an old, install the
443 * new rule, look above, and then delete the old
444 */
445 if (unique)
7f0ea8a4 446 zebra_pbr_del_rule(unique);
1fbfe5a5
DS
447}
448
7f0ea8a4 449void zebra_pbr_del_rule(struct zebra_pbr_rule *rule)
1fbfe5a5 450{
43fe6a2a
DS
451 struct zebra_pbr_rule *lookup;
452
7f0ea8a4 453 lookup = hash_lookup(zrouter.rules_hash, rule);
ebecd649 454 (void)kernel_del_pbr_rule(rule);
43fe6a2a 455
d5c52f76 456 if (lookup) {
7f0ea8a4 457 hash_release(zrouter.rules_hash, lookup);
43fe6a2a 458 XFREE(MTYPE_TMP, lookup);
d5c52f76 459 } else
9df414fe
QY
460 zlog_debug("%s: Rule being deleted we know nothing about",
461 __PRETTY_FUNCTION__);
1fbfe5a5
DS
462}
463
e69aa084
DS
464static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data)
465{
e69aa084
DS
466 struct zebra_pbr_rule *rule = b->data;
467 int *sock = data;
468
469 if (rule->sock == *sock) {
ebecd649 470 (void)kernel_del_pbr_rule(rule);
7f0ea8a4 471 hash_release(zrouter.rules_hash, rule);
d5c52f76 472 XFREE(MTYPE_TMP, rule);
e69aa084
DS
473 }
474}
475
c2ef5232
PG
476static void zebra_pbr_cleanup_ipset(struct hash_backet *b, void *data)
477{
c2ef5232
PG
478 struct zebra_pbr_ipset *ipset = b->data;
479 int *sock = data;
480
73a829f7 481 if (ipset->sock == *sock) {
1c6fca1f 482 hook_call(zebra_pbr_ipset_update, 0, ipset);
62f20a52 483 hash_release(zrouter.ipset_hash, ipset);
73a829f7 484 }
c2ef5232
PG
485}
486
487static void zebra_pbr_cleanup_ipset_entry(struct hash_backet *b, void *data)
488{
c2ef5232
PG
489 struct zebra_pbr_ipset_entry *ipset = b->data;
490 int *sock = data;
491
73a829f7 492 if (ipset->sock == *sock) {
1c6fca1f 493 hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
62f20a52 494 hash_release(zrouter.ipset_entry_hash, ipset);
73a829f7 495 }
c2ef5232
PG
496}
497
498static void zebra_pbr_cleanup_iptable(struct hash_backet *b, void *data)
499{
c2ef5232
PG
500 struct zebra_pbr_iptable *iptable = b->data;
501 int *sock = data;
502
73a829f7 503 if (iptable->sock == *sock) {
1c6fca1f 504 hook_call(zebra_pbr_iptable_update, 0, iptable);
62f20a52 505 hash_release(zrouter.iptable_hash, iptable);
73a829f7 506 }
c2ef5232
PG
507}
508
4c0ec639 509static int zebra_pbr_client_close_cleanup(struct zserv *client)
e69aa084 510{
4c0ec639 511 int sock = client->sock;
e69aa084 512
4c0ec639
PG
513 if (!sock)
514 return 0;
7f0ea8a4 515 hash_iterate(zrouter.rules_hash, zebra_pbr_cleanup_rules, &sock);
62f20a52
DS
516 hash_iterate(zrouter.iptable_hash, zebra_pbr_cleanup_iptable, &sock);
517 hash_iterate(zrouter.ipset_entry_hash, zebra_pbr_cleanup_ipset_entry,
518 &sock);
519 hash_iterate(zrouter.ipset_hash, zebra_pbr_cleanup_ipset, &sock);
4c0ec639
PG
520 return 1;
521}
522
523void zebra_pbr_init(void)
524{
c0ea1ae7 525 hook_register(zserv_client_close, zebra_pbr_client_close_cleanup);
e69aa084
DS
526}
527
7661461a
PG
528static void *pbr_ipset_alloc_intern(void *arg)
529{
530 struct zebra_pbr_ipset *zpi;
531 struct zebra_pbr_ipset *new;
532
533 zpi = (struct zebra_pbr_ipset *)arg;
534
535 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset));
536
537 memcpy(new, zpi, sizeof(*zpi));
538
539 return new;
540}
541
62f20a52 542void zebra_pbr_create_ipset(struct zebra_pbr_ipset *ipset)
7661461a 543{
73a829f7
PG
544 int ret;
545
62f20a52 546 (void)hash_get(zrouter.ipset_hash, ipset, pbr_ipset_alloc_intern);
1c6fca1f 547 ret = hook_call(zebra_pbr_ipset_update, 1, ipset);
73a829f7 548 kernel_pbr_ipset_add_del_status(ipset,
ea1c14f6
MS
549 ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
550 : ZEBRA_DPLANE_INSTALL_FAILURE);
7661461a
PG
551}
552
62f20a52 553void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset)
7661461a
PG
554{
555 struct zebra_pbr_ipset *lookup;
556
62f20a52 557 lookup = hash_lookup(zrouter.ipset_hash, ipset);
1c6fca1f 558 hook_call(zebra_pbr_ipset_update, 0, ipset);
de67547d 559 if (lookup) {
62f20a52 560 hash_release(zrouter.ipset_hash, lookup);
7661461a 561 XFREE(MTYPE_TMP, lookup);
de67547d 562 } else
9df414fe
QY
563 zlog_debug(
564 "%s: IPSet Entry being deleted we know nothing about",
565 __PRETTY_FUNCTION__);
7661461a
PG
566}
567
ed78b7c8
PG
568struct pbr_ipset_name_lookup {
569 struct zebra_pbr_ipset *ipset;
570 char ipset_name[ZEBRA_IPSET_NAME_SIZE];
571};
572
5b0d92b8 573const char *zebra_pbr_ipset_type2str(uint32_t type)
586f4ccf
PG
574{
575 return lookup_msg(ipset_type_msg, type,
576 "Unrecognized IPset Type");
577}
578
ed78b7c8
PG
579static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg)
580{
581 struct pbr_ipset_name_lookup *pinl =
582 (struct pbr_ipset_name_lookup *)arg;
583 struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
584
585 if (!strncmp(pinl->ipset_name, zpi->ipset_name,
586 ZEBRA_IPSET_NAME_SIZE)) {
587 pinl->ipset = zpi;
588 return HASHWALK_ABORT;
589 }
590 return HASHWALK_CONTINUE;
591}
592
62f20a52 593struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(char *ipsetname)
d59c13af 594{
ed78b7c8
PG
595 struct pbr_ipset_name_lookup pinl;
596 struct pbr_ipset_name_lookup *ptr = &pinl;
597
d59c13af
PG
598 if (!ipsetname)
599 return NULL;
ed78b7c8
PG
600 memset(ptr, 0, sizeof(struct pbr_ipset_name_lookup));
601 snprintf((char *)ptr->ipset_name, ZEBRA_IPSET_NAME_SIZE, "%s",
602 ipsetname);
62f20a52 603 hash_walk(zrouter.ipset_hash, zebra_pbr_ipset_pername_walkcb, ptr);
ed78b7c8 604 return ptr->ipset;
d59c13af
PG
605}
606
7661461a
PG
607static void *pbr_ipset_entry_alloc_intern(void *arg)
608{
609 struct zebra_pbr_ipset_entry *zpi;
610 struct zebra_pbr_ipset_entry *new;
611
612 zpi = (struct zebra_pbr_ipset_entry *)arg;
613
614 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry));
615
616 memcpy(new, zpi, sizeof(*zpi));
617
618 return new;
619}
620
62f20a52 621void zebra_pbr_add_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
7661461a 622{
73a829f7
PG
623 int ret;
624
62f20a52 625 (void)hash_get(zrouter.ipset_entry_hash, ipset,
7661461a 626 pbr_ipset_entry_alloc_intern);
1c6fca1f 627 ret = hook_call(zebra_pbr_ipset_entry_update, 1, ipset);
73a829f7 628 kernel_pbr_ipset_entry_add_del_status(ipset,
ea1c14f6
MS
629 ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
630 : ZEBRA_DPLANE_INSTALL_FAILURE);
7661461a
PG
631}
632
62f20a52 633void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
7661461a
PG
634{
635 struct zebra_pbr_ipset_entry *lookup;
636
62f20a52 637 lookup = hash_lookup(zrouter.ipset_entry_hash, ipset);
1c6fca1f 638 hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
de67547d 639 if (lookup) {
62f20a52 640 hash_release(zrouter.ipset_entry_hash, lookup);
7661461a 641 XFREE(MTYPE_TMP, lookup);
de67547d 642 } else
9df414fe
QY
643 zlog_debug("%s: IPSet being deleted we know nothing about",
644 __PRETTY_FUNCTION__);
7661461a
PG
645}
646
7abd6c4f
PG
647static void *pbr_iptable_alloc_intern(void *arg)
648{
649 struct zebra_pbr_iptable *zpi;
650 struct zebra_pbr_iptable *new;
651
652 zpi = (struct zebra_pbr_iptable *)arg;
653
654 new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
655
656 memcpy(new, zpi, sizeof(*zpi));
657
658 return new;
659}
660
62f20a52 661void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable)
7abd6c4f 662{
73a829f7
PG
663 int ret;
664
62f20a52 665 (void)hash_get(zrouter.iptable_hash, iptable, pbr_iptable_alloc_intern);
1c6fca1f 666 ret = hook_call(zebra_pbr_iptable_update, 1, iptable);
73a829f7 667 kernel_pbr_iptable_add_del_status(iptable,
ea1c14f6
MS
668 ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
669 : ZEBRA_DPLANE_INSTALL_FAILURE);
7abd6c4f
PG
670}
671
62f20a52 672void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
7abd6c4f 673{
f80ec7e3 674 struct zebra_pbr_iptable *lookup;
7abd6c4f 675
62f20a52 676 lookup = hash_lookup(zrouter.iptable_hash, iptable);
1c6fca1f 677 hook_call(zebra_pbr_iptable_update, 0, iptable);
f80ec7e3
PG
678 if (lookup) {
679 struct listnode *node, *nnode;
680 char *name;
681
62f20a52 682 hash_release(zrouter.iptable_hash, lookup);
f80ec7e3
PG
683 for (ALL_LIST_ELEMENTS(iptable->interface_name_list,
684 node, nnode, name)) {
685 XFREE(MTYPE_PBR_IPTABLE_IFNAME, name);
686 list_delete_node(iptable->interface_name_list,
687 node);
688 }
7abd6c4f 689 XFREE(MTYPE_TMP, lookup);
f80ec7e3 690 } else
9df414fe
QY
691 zlog_debug("%s: IPTable being deleted we know nothing about",
692 __PRETTY_FUNCTION__);
7abd6c4f
PG
693}
694
942bf97b 695/*
696 * Handle success or failure of rule (un)install in the kernel.
697 */
698void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
ea1c14f6 699 enum zebra_dplane_status res)
942bf97b 700{
b6c5d343 701 switch (res) {
ea1c14f6 702 case ZEBRA_DPLANE_INSTALL_SUCCESS:
b6c5d343
DS
703 zsend_rule_notify_owner(rule, ZAPI_RULE_INSTALLED);
704 break;
ea1c14f6 705 case ZEBRA_DPLANE_INSTALL_FAILURE:
b6c5d343
DS
706 zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_INSTALL);
707 break;
ea1c14f6 708 case ZEBRA_DPLANE_DELETE_SUCCESS:
0f03639d 709 zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
b6c5d343 710 break;
ea1c14f6 711 case ZEBRA_DPLANE_DELETE_FAILURE:
34d9d5be 712 zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_REMOVE);
b6c5d343 713 break;
ea1c14f6
MS
714 case ZEBRA_DPLANE_STATUS_NONE:
715 break;
b6c5d343 716 }
942bf97b 717}
718
425bdd6b
PG
719/*
720 * Handle success or failure of ipset (un)install in the kernel.
721 */
722void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset,
ea1c14f6 723 enum zebra_dplane_status res)
425bdd6b
PG
724{
725 switch (res) {
ea1c14f6 726 case ZEBRA_DPLANE_INSTALL_SUCCESS:
425bdd6b
PG
727 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_INSTALLED);
728 break;
ea1c14f6 729 case ZEBRA_DPLANE_INSTALL_FAILURE:
425bdd6b
PG
730 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL);
731 break;
ea1c14f6 732 case ZEBRA_DPLANE_DELETE_SUCCESS:
4c550bcf
PG
733 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_REMOVED);
734 break;
ea1c14f6 735 case ZEBRA_DPLANE_DELETE_FAILURE:
34d9d5be 736 zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_REMOVE);
425bdd6b 737 break;
ea1c14f6
MS
738 case ZEBRA_DPLANE_STATUS_NONE:
739 break;
425bdd6b
PG
740 }
741}
742
743/*
744 * Handle success or failure of ipset (un)install in the kernel.
745 */
746void kernel_pbr_ipset_entry_add_del_status(
747 struct zebra_pbr_ipset_entry *ipset,
ea1c14f6 748 enum zebra_dplane_status res)
425bdd6b
PG
749{
750 switch (res) {
ea1c14f6 751 case ZEBRA_DPLANE_INSTALL_SUCCESS:
425bdd6b
PG
752 zsend_ipset_entry_notify_owner(ipset,
753 ZAPI_IPSET_ENTRY_INSTALLED);
754 break;
ea1c14f6 755 case ZEBRA_DPLANE_INSTALL_FAILURE:
425bdd6b
PG
756 zsend_ipset_entry_notify_owner(ipset,
757 ZAPI_IPSET_ENTRY_FAIL_INSTALL);
758 break;
ea1c14f6 759 case ZEBRA_DPLANE_DELETE_SUCCESS:
4c550bcf
PG
760 zsend_ipset_entry_notify_owner(ipset,
761 ZAPI_IPSET_ENTRY_REMOVED);
762 break;
ea1c14f6 763 case ZEBRA_DPLANE_DELETE_FAILURE:
4c550bcf 764 zsend_ipset_entry_notify_owner(ipset,
34d9d5be 765 ZAPI_IPSET_ENTRY_FAIL_REMOVE);
425bdd6b 766 break;
ea1c14f6
MS
767 case ZEBRA_DPLANE_STATUS_NONE:
768 break;
425bdd6b
PG
769 }
770}
771
7abd6c4f
PG
772/*
773 * Handle success or failure of ipset (un)install in the kernel.
774 */
775void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
ea1c14f6 776 enum zebra_dplane_status res)
7abd6c4f
PG
777{
778 switch (res) {
ea1c14f6 779 case ZEBRA_DPLANE_INSTALL_SUCCESS:
7abd6c4f
PG
780 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_INSTALLED);
781 break;
ea1c14f6 782 case ZEBRA_DPLANE_INSTALL_FAILURE:
7abd6c4f
PG
783 zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL);
784 break;
ea1c14f6 785 case ZEBRA_DPLANE_DELETE_SUCCESS:
4c550bcf
PG
786 zsend_iptable_notify_owner(iptable,
787 ZAPI_IPTABLE_REMOVED);
788 break;
ea1c14f6 789 case ZEBRA_DPLANE_DELETE_FAILURE:
4c550bcf 790 zsend_iptable_notify_owner(iptable,
34d9d5be 791 ZAPI_IPTABLE_FAIL_REMOVE);
7abd6c4f 792 break;
ea1c14f6
MS
793 case ZEBRA_DPLANE_STATUS_NONE:
794 break;
7abd6c4f
PG
795 }
796}
797
942bf97b 798/*
799 * Handle rule delete notification from kernel.
800 */
a0321978 801int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
942bf97b 802{
803 return 0;
804}
586f4ccf
PG
805
806struct zebra_pbr_ipset_entry_unique_display {
807 struct zebra_pbr_ipset *zpi;
808 struct vty *vty;
73a829f7 809 struct zebra_ns *zns;
586f4ccf
PG
810};
811
812struct zebra_pbr_env_display {
813 struct zebra_ns *zns;
814 struct vty *vty;
7929821a 815 char *name;
586f4ccf
PG
816};
817
818static const char *zebra_pbr_prefix2str(union prefixconstptr pu,
819 char *str, int size)
820{
821 const struct prefix *p = pu.p;
822 char buf[PREFIX2STR_BUFFER];
823
824 if (p->family == AF_INET && p->prefixlen == IPV4_MAX_PREFIXLEN) {
825 snprintf(str, size, "%s", inet_ntop(p->family, &p->u.prefix,
826 buf, PREFIX2STR_BUFFER));
827 return str;
828 }
829 return prefix2str(pu, str, size);
830}
831
be729dd7
PG
832static void zebra_pbr_display_icmp(struct vty *vty,
833 struct zebra_pbr_ipset_entry *zpie)
834{
835 char decoded_str[20];
836 uint16_t port;
837
838 /* range icmp type */
839 if (zpie->src_port_max || zpie->dst_port_max) {
840 vty_out(vty, ":icmp:[type <%d:%d>;code <%d:%d>",
841 zpie->src_port_min, zpie->src_port_max,
842 zpie->dst_port_min, zpie->dst_port_max);
843 } else {
844 port = ((zpie->src_port_min << 8) & 0xff00) +
845 (zpie->dst_port_min & 0xff);
846 memset(decoded_str, 0, sizeof(decoded_str));
847 sprintf(decoded_str, "%d/%d",
848 zpie->src_port_min,
849 zpie->dst_port_min);
850 vty_out(vty, ":icmp:%s",
851 lookup_msg(icmp_typecode_str,
852 port, decoded_str));
853 }
854}
855
25d760c5
PG
856static void zebra_pbr_display_port(struct vty *vty, uint32_t filter_bm,
857 uint16_t port_min, uint16_t port_max,
858 uint8_t proto)
859{
860 if (!(filter_bm & PBR_FILTER_PROTO)) {
861 if (port_max)
862 vty_out(vty, ":udp/tcp:%d-%d",
863 port_min, port_max);
864 else
865 vty_out(vty, ":udp/tcp:%d",
866 port_min);
867 } else {
868 if (port_max)
869 vty_out(vty, ":proto %d:%d-%d",
870 proto, port_min, port_max);
871 else
872 vty_out(vty, ":proto %d:%d",
873 proto, port_min);
874 }
875}
876
586f4ccf
PG
877static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
878 void *arg)
879{
880 struct zebra_pbr_ipset_entry_unique_display *unique =
881 (struct zebra_pbr_ipset_entry_unique_display *)arg;
882 struct zebra_pbr_ipset *zpi = unique->zpi;
883 struct vty *vty = unique->vty;
884 struct zebra_pbr_ipset_entry *zpie =
885 (struct zebra_pbr_ipset_entry *)backet->data;
73a829f7 886 uint64_t pkts = 0, bytes = 0;
73a829f7 887 int ret = 0;
586f4ccf
PG
888
889 if (zpie->backpointer != zpi)
890 return HASHWALK_CONTINUE;
891
25d760c5
PG
892 if ((zpi->type == IPSET_NET_NET) ||
893 (zpi->type == IPSET_NET_PORT_NET)) {
586f4ccf
PG
894 char buf[PREFIX_STRLEN];
895
896 zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
897 vty_out(vty, "\tfrom %s", buf);
be729dd7
PG
898 if (zpie->filter_bm & PBR_FILTER_SRC_PORT &&
899 zpie->proto != IPPROTO_ICMP)
25d760c5
PG
900 zebra_pbr_display_port(vty, zpie->filter_bm,
901 zpie->src_port_min,
902 zpie->src_port_max,
903 zpie->proto);
586f4ccf
PG
904 vty_out(vty, " to ");
905 zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
906 vty_out(vty, "%s", buf);
be729dd7
PG
907 if (zpie->filter_bm & PBR_FILTER_DST_PORT &&
908 zpie->proto != IPPROTO_ICMP)
25d760c5
PG
909 zebra_pbr_display_port(vty, zpie->filter_bm,
910 zpie->dst_port_min,
911 zpie->dst_port_max,
912 zpie->proto);
be729dd7
PG
913 if (zpie->proto == IPPROTO_ICMP)
914 zebra_pbr_display_icmp(vty, zpie);
25d760c5
PG
915 } else if ((zpi->type == IPSET_NET) ||
916 (zpi->type == IPSET_NET_PORT)) {
586f4ccf
PG
917 char buf[PREFIX_STRLEN];
918
919 if (zpie->filter_bm & PBR_FILTER_SRC_IP) {
920 zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
921 vty_out(vty, "\tfrom %s", buf);
922 }
be729dd7
PG
923 if (zpie->filter_bm & PBR_FILTER_SRC_PORT &&
924 zpie->proto != IPPROTO_ICMP)
25d760c5
PG
925 zebra_pbr_display_port(vty, zpie->filter_bm,
926 zpie->src_port_min,
927 zpie->src_port_max,
928 zpie->proto);
586f4ccf
PG
929 if (zpie->filter_bm & PBR_FILTER_DST_IP) {
930 zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
931 vty_out(vty, "\tto %s", buf);
932 }
be729dd7
PG
933 if (zpie->filter_bm & PBR_FILTER_DST_PORT &&
934 zpie->proto != IPPROTO_ICMP)
25d760c5
PG
935 zebra_pbr_display_port(vty, zpie->filter_bm,
936 zpie->dst_port_min,
937 zpie->dst_port_max,
938 zpie->proto);
be729dd7
PG
939 if (zpie->proto == IPPROTO_ICMP)
940 zebra_pbr_display_icmp(vty, zpie);
586f4ccf
PG
941 }
942 vty_out(vty, " (%u)\n", zpie->unique);
943
1c6fca1f 944 ret = hook_call(zebra_pbr_ipset_entry_get_stat, zpie, &pkts,
62f20a52 945 &bytes);
73a829f7
PG
946 if (ret && pkts > 0)
947 vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n",
948 pkts, bytes);
586f4ccf
PG
949 return HASHWALK_CONTINUE;
950}
951
952static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg)
953{
954 struct zebra_pbr_env_display *uniqueipset =
955 (struct zebra_pbr_env_display *)arg;
956 struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
957 struct zebra_pbr_ipset_entry_unique_display unique;
958 struct vty *vty = uniqueipset->vty;
959 struct zebra_ns *zns = uniqueipset->zns;
960
961 vty_out(vty, "IPset %s type %s\n", zpi->ipset_name,
962 zebra_pbr_ipset_type2str(zpi->type));
963 unique.vty = vty;
964 unique.zpi = zpi;
73a829f7 965 unique.zns = zns;
62f20a52 966 hash_walk(zrouter.ipset_entry_hash, zebra_pbr_show_ipset_entry_walkcb,
586f4ccf
PG
967 &unique);
968 vty_out(vty, "\n");
969 return HASHWALK_CONTINUE;
970}
971
dc993e76
PG
972size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len,
973 uint16_t tcp_val)
974{
975 size_t len_written = 0;
976 static struct message nt = {0};
977 const struct message *pnt;
978 int incr = 0;
979
980 for (pnt = tcp_value_str;
981 memcmp(pnt, &nt, sizeof(struct message)); pnt++)
982 if (pnt->key & tcp_val) {
983 len_written += snprintf(buffer + len_written,
984 len - len_written,
985 "%s%s", incr ?
986 ",":"", pnt->str);
987 incr++;
988 }
989 return len_written;
990}
991
586f4ccf
PG
992/*
993 */
994void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname)
995{
996 struct zebra_pbr_ipset *zpi;
997 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
998 struct zebra_pbr_ipset_entry_unique_display unique;
999 struct zebra_pbr_env_display uniqueipset;
1000
1001 if (ipsetname) {
62f20a52 1002 zpi = zebra_pbr_lookup_ipset_pername(ipsetname);
586f4ccf
PG
1003 if (!zpi) {
1004 vty_out(vty, "No IPset %s found\n", ipsetname);
1005 return;
1006 }
1007 vty_out(vty, "IPset %s type %s\n", ipsetname,
1008 zebra_pbr_ipset_type2str(zpi->type));
1009
1010 unique.vty = vty;
1011 unique.zpi = zpi;
73a829f7 1012 unique.zns = zns;
62f20a52
DS
1013 hash_walk(zrouter.ipset_entry_hash,
1014 zebra_pbr_show_ipset_entry_walkcb, &unique);
586f4ccf
PG
1015 return;
1016 }
1017 uniqueipset.zns = zns;
1018 uniqueipset.vty = vty;
7929821a 1019 uniqueipset.name = NULL;
62f20a52 1020 hash_walk(zrouter.ipset_hash, zebra_pbr_show_ipset_walkcb,
586f4ccf
PG
1021 &uniqueipset);
1022}
1023
1024struct pbr_rule_fwmark_lookup {
1025 struct zebra_pbr_rule *ptr;
1026 uint32_t fwmark;
1027};
1028
1029static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_backet *backet,
1030 void *arg)
1031{
1032 struct pbr_rule_fwmark_lookup *iprule =
1033 (struct pbr_rule_fwmark_lookup *)arg;
1034 struct zebra_pbr_rule *zpr = (struct zebra_pbr_rule *)backet->data;
1035
1036 if (iprule->fwmark == zpr->rule.filter.fwmark) {
1037 iprule->ptr = zpr;
1038 return HASHWALK_ABORT;
1039 }
1040 return HASHWALK_CONTINUE;
1041}
1042
7929821a
PG
1043static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable,
1044 struct vty *vty,
1045 struct zebra_ns *zns)
586f4ccf 1046{
73a829f7
PG
1047 int ret;
1048 uint64_t pkts = 0, bytes = 0;
586f4ccf
PG
1049
1050 vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name,
1051 iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect",
1052 iptable->unique);
0b328d3f
PG
1053 if (iptable->type == IPSET_NET_PORT ||
1054 iptable->type == IPSET_NET_PORT_NET) {
1055 if (!(iptable->filter_bm & MATCH_ICMP_SET)) {
1056 if (iptable->filter_bm & PBR_FILTER_DST_PORT)
1057 vty_out(vty, "\t lookup dst port\n");
1058 else if (iptable->filter_bm & PBR_FILTER_SRC_PORT)
1059 vty_out(vty, "\t lookup src port\n");
1060 }
1061 }
e7f7dad4
PG
1062 if (iptable->pkt_len_min || iptable->pkt_len_max) {
1063 if (!iptable->pkt_len_max)
1064 vty_out(vty, "\t pkt len %u\n",
1065 iptable->pkt_len_min);
1066 else
1067 vty_out(vty, "\t pkt len [%u;%u]\n",
1068 iptable->pkt_len_min,
1069 iptable->pkt_len_max);
1070 }
dc993e76
PG
1071 if (iptable->tcp_flags || iptable->tcp_mask_flags) {
1072 char tcp_flag_str[64];
1073 char tcp_flag_mask_str[64];
1074
1075 zebra_pbr_tcpflags_snprintf(tcp_flag_str,
1076 sizeof(tcp_flag_str),
1077 iptable->tcp_flags);
1078 zebra_pbr_tcpflags_snprintf(tcp_flag_mask_str,
1079 sizeof(tcp_flag_mask_str),
1080 iptable->tcp_mask_flags);
1081 vty_out(vty, "\t tcpflags [%s/%s]\n",
1082 tcp_flag_str, tcp_flag_mask_str);
1083 }
69214c57
PG
1084 if (iptable->filter_bm & (MATCH_DSCP_SET | MATCH_DSCP_INVERSE_SET)) {
1085 vty_out(vty, "\t dscp %s %d\n",
1086 iptable->filter_bm & MATCH_DSCP_INVERSE_SET ?
1087 "not" : "", iptable->dscp_value);
1088 }
5ac5b7cc
PG
1089 if (iptable->fragment) {
1090 char val_str[10];
1091
1092 sprintf(val_str, "%d", iptable->fragment);
1093 vty_out(vty, "\t fragment%s %s\n",
1094 iptable->filter_bm & MATCH_FRAGMENT_INVERSE_SET ?
1095 " not" : "", lookup_msg(fragment_value_str,
1096 iptable->fragment, val_str));
1097 }
1c6fca1f 1098 ret = hook_call(zebra_pbr_iptable_get_stat, iptable, &pkts,
62f20a52 1099 &bytes);
73a829f7
PG
1100 if (ret && pkts > 0)
1101 vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n",
1102 pkts, bytes);
586f4ccf
PG
1103 if (iptable->action != ZEBRA_IPTABLES_DROP) {
1104 struct pbr_rule_fwmark_lookup prfl;
1105
1106 prfl.fwmark = iptable->fwmark;
1107 prfl.ptr = NULL;
7f0ea8a4 1108 hash_walk(zrouter.rules_hash,
586f4ccf
PG
1109 &zebra_pbr_rule_lookup_fwmark_walkcb, &prfl);
1110 if (prfl.ptr) {
1111 struct zebra_pbr_rule *zpr = prfl.ptr;
1112
1113 vty_out(vty, "\t table %u, fwmark %u\n",
1114 zpr->rule.action.table,
1115 prfl.fwmark);
1116 }
1117 }
7929821a
PG
1118}
1119
1120static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg)
1121{
1122 struct zebra_pbr_iptable *iptable =
1123 (struct zebra_pbr_iptable *)backet->data;
1124 struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg;
1125 struct vty *vty = env->vty;
1126 struct zebra_ns *zns = env->zns;
1127 char *iptable_name = env->name;
1128
1129 if (!iptable_name)
1130 zebra_pbr_show_iptable_unit(iptable, vty, zns);
1131 else if (!strncmp(iptable_name,
1132 iptable->ipset_name,
1133 ZEBRA_IPSET_NAME_SIZE))
1134 zebra_pbr_show_iptable_unit(iptable, vty, zns);
586f4ccf
PG
1135 return HASHWALK_CONTINUE;
1136}
1137
7929821a 1138void zebra_pbr_show_iptable(struct vty *vty, char *iptable_name)
586f4ccf
PG
1139{
1140 struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
1141 struct zebra_pbr_env_display env;
1142
1143 env.vty = vty;
1144 env.zns = zns;
7929821a 1145 env.name = iptable_name;
62f20a52 1146 hash_walk(zrouter.iptable_hash, zebra_pbr_show_iptable_walkcb, &env);
586f4ccf 1147}
f80ec7e3
PG
1148
1149void zebra_pbr_iptable_update_interfacelist(struct stream *s,
1150 struct zebra_pbr_iptable *zpi)
1151{
1152 uint32_t i = 0, index;
1153 struct interface *ifp;
1154 char *name;
1155
1156 for (i = 0; i < zpi->nb_interface; i++) {
1157 STREAM_GETL(s, index);
1158 ifp = if_lookup_by_index(index, zpi->vrf_id);
1159 if (!ifp)
1160 continue;
1161 name = XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME, ifp->name);
1162 listnode_add(zpi->interface_name_list, name);
1163 }
1164stream_failure:
1165 return;
1166}