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