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