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