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