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