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