ip_fw_table_algo.c (269988) | ip_fw_table_algo.c (270001) |
---|---|
1/*- 2 * Copyright (c) 2004 Ruslan Ermilov and Vsevolod Lobko. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 34 unchanged lines hidden (view full) --- 43#include <sys/malloc.h> 44#include <sys/kernel.h> 45#include <sys/lock.h> 46#include <sys/rwlock.h> 47#include <sys/socket.h> 48#include <sys/queue.h> 49#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */ 50#include <net/radix.h> | 1/*- 2 * Copyright (c) 2004 Ruslan Ermilov and Vsevolod Lobko. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 34 unchanged lines hidden (view full) --- 43#include <sys/malloc.h> 44#include <sys/kernel.h> 45#include <sys/lock.h> 46#include <sys/rwlock.h> 47#include <sys/socket.h> 48#include <sys/queue.h> 49#include <net/if.h> /* ip_fw.h requires IFNAMSIZ */ 50#include <net/radix.h> |
51#include <net/route.h> |
|
51 52#include <netinet/in.h> 53#include <netinet/ip_var.h> /* struct ipfw_rule_ref */ 54#include <netinet/ip_fw.h> 55 56#include <netpfil/ipfw/ip_fw_private.h> 57#include <netpfil/ipfw/ip_fw_table.h> 58 --- 3455 unchanged lines hidden (view full) --- 3514 .dump_tinfo = ta_dump_fhash_tinfo, 3515 .need_modify = ta_need_modify_fhash, 3516 .prepare_mod = ta_prepare_mod_fhash, 3517 .fill_mod = ta_fill_mod_fhash, 3518 .modify = ta_modify_fhash, 3519 .flush_mod = ta_flush_mod_fhash, 3520}; 3521 | 52 53#include <netinet/in.h> 54#include <netinet/ip_var.h> /* struct ipfw_rule_ref */ 55#include <netinet/ip_fw.h> 56 57#include <netpfil/ipfw/ip_fw_private.h> 58#include <netpfil/ipfw/ip_fw_table.h> 59 --- 3455 unchanged lines hidden (view full) --- 3515 .dump_tinfo = ta_dump_fhash_tinfo, 3516 .need_modify = ta_need_modify_fhash, 3517 .prepare_mod = ta_prepare_mod_fhash, 3518 .fill_mod = ta_fill_mod_fhash, 3519 .modify = ta_modify_fhash, 3520 .flush_mod = ta_flush_mod_fhash, 3521}; 3522 |
3523/* 3524 * Kernel fibs bindings. 3525 * 3526 * Implementation: 3527 * 3528 * Runtime part: 3529 * - fully relies on route API 3530 * - fib number is stored in ti->data 3531 * 3532 */ 3533 3534static struct rtentry * 3535lookup_kfib(void *key, int keylen, int fib) 3536{ 3537 struct sockaddr *s; 3538 3539 if (keylen == 4) { 3540 struct sockaddr_in sin; 3541 bzero(&sin, sizeof(sin)); 3542 sin.sin_len = sizeof(struct sockaddr_in); 3543 sin.sin_family = AF_INET; 3544 sin.sin_addr.s_addr = *(in_addr_t *)key; 3545 s = (struct sockaddr *)&sin; 3546 } else { 3547 struct sockaddr_in6 sin6; 3548 bzero(&sin6, sizeof(sin6)); 3549 sin6.sin6_len = sizeof(struct sockaddr_in6); 3550 sin6.sin6_family = AF_INET6; 3551 sin6.sin6_addr = *(struct in6_addr *)key; 3552 s = (struct sockaddr *)&sin6; 3553 } 3554 3555 return (rtalloc1_fib(s, 0, 0, fib)); 3556} 3557 3558static int 3559ta_lookup_kfib(struct table_info *ti, void *key, uint32_t keylen, 3560 uint32_t *val) 3561{ 3562 struct rtentry *rte; 3563 3564 if ((rte = lookup_kfib(key, keylen, ti->data)) == NULL) 3565 return (0); 3566 3567 *val = 0; 3568 RTFREE_LOCKED(rte); 3569 3570 return (1); 3571} 3572 3573/* Parse 'fib=%d' */ 3574static int 3575kfib_parse_opts(int *pfib, char *data) 3576{ 3577 char *pdel, *pend, *s; 3578 int fibnum; 3579 3580 if (data == NULL) 3581 return (0); 3582 if ((pdel = strchr(data, ' ')) == NULL) 3583 return (0); 3584 while (*pdel == ' ') 3585 pdel++; 3586 if (strncmp(pdel, "fib=", 4) != 0) 3587 return (EINVAL); 3588 if ((s = strchr(pdel, ' ')) != NULL) 3589 *s++ = '\0'; 3590 3591 pdel += 4; 3592 /* Need \d+ */ 3593 fibnum = strtol(pdel, &pend, 10); 3594 if (*pend != '\0') 3595 return (EINVAL); 3596 3597 *pfib = fibnum; 3598 3599 return (0); 3600} 3601 3602static void 3603ta_print_kfib_config(void *ta_state, struct table_info *ti, char *buf, 3604 size_t bufsize) 3605{ 3606 3607 if (ti->data != 0) 3608 snprintf(buf, bufsize, "%s fib=%lu", "cidr:kfib", ti->data); 3609 else 3610 snprintf(buf, bufsize, "%s", "cidr:kfib"); 3611} 3612 3613static int 3614ta_init_kfib(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti, 3615 char *data, uint8_t tflags) 3616{ 3617 int error, fibnum; 3618 3619 fibnum = 0; 3620 if ((error = kfib_parse_opts(&fibnum, data)) != 0) 3621 return (error); 3622 3623 if (fibnum >= rt_numfibs) 3624 return (E2BIG); 3625 3626 ti->data = fibnum; 3627 ti->lookup = ta_lookup_kfib; 3628 3629 return (0); 3630} 3631 3632/* 3633 * Destroys table @ti 3634 */ 3635static void 3636ta_destroy_kfib(void *ta_state, struct table_info *ti) 3637{ 3638 3639} 3640 3641/* 3642 * Provide algo-specific table info 3643 */ 3644static void 3645ta_dump_kfib_tinfo(void *ta_state, struct table_info *ti, ipfw_ta_tinfo *tinfo) 3646{ 3647 3648 tinfo->flags = IPFW_TATFLAGS_AFDATA; 3649 tinfo->taclass4 = IPFW_TACLASS_RADIX; 3650 tinfo->count4 = 0; 3651 tinfo->itemsize4 = sizeof(struct rtentry); 3652 tinfo->taclass6 = IPFW_TACLASS_RADIX; 3653 tinfo->count6 = 0; 3654 tinfo->itemsize6 = sizeof(struct rtentry); 3655} 3656 3657static int 3658contigmask(uint8_t *p, int len) 3659{ 3660 int i, n; 3661 3662 for (i = 0; i < len ; i++) 3663 if ( (p[i/8] & (1 << (7 - (i%8)))) == 0) /* first bit unset */ 3664 break; 3665 for (n= i + 1; n < len; n++) 3666 if ( (p[n/8] & (1 << (7 - (n % 8)))) != 0) 3667 return (-1); /* mask not contiguous */ 3668 return (i); 3669} 3670 3671 3672static int 3673ta_dump_kfib_tentry(void *ta_state, struct table_info *ti, void *e, 3674 ipfw_obj_tentry *tent) 3675{ 3676 struct rtentry *rte; 3677 struct sockaddr_in *addr, *mask; 3678 struct sockaddr_in6 *addr6, *mask6; 3679 int len; 3680 3681 rte = (struct rtentry *)e; 3682 addr = (struct sockaddr_in *)rt_key(rte); 3683 mask = (struct sockaddr_in *)rt_mask(rte); 3684 len = 0; 3685 3686 /* Guess IPv4/IPv6 radix by sockaddr family */ 3687 if (addr->sin_family == AF_INET) { 3688 tent->k.addr.s_addr = addr->sin_addr.s_addr; 3689 len = 32; 3690 if (mask != NULL) 3691 len = contigmask((uint8_t *)&mask->sin_addr, 32); 3692 if (len == -1) 3693 len = 0; 3694 tent->masklen = len; 3695 tent->subtype = AF_INET; 3696 tent->value = 0; /* Do we need to put GW here? */ 3697#ifdef INET6 3698 } else if (addr->sin_family == AF_INET6) { 3699 addr6 = (struct sockaddr_in6 *)addr; 3700 mask6 = (struct sockaddr_in6 *)mask; 3701 memcpy(&tent->k, &addr6->sin6_addr, sizeof(struct in6_addr)); 3702 len = 128; 3703 if (mask6 != NULL) 3704 len = contigmask((uint8_t *)&mask6->sin6_addr, 128); 3705 if (len == -1) 3706 len = 0; 3707 tent->masklen = len; 3708 tent->subtype = AF_INET6; 3709 tent->value = 0; 3710#endif 3711 } 3712 3713 return (0); 3714} 3715 3716static int 3717ta_find_kfib_tentry(void *ta_state, struct table_info *ti, 3718 ipfw_obj_tentry *tent) 3719{ 3720 struct rtentry *rte; 3721 void *key; 3722 int keylen; 3723 3724 if (tent->subtype == AF_INET) { 3725 key = &tent->k.addr; 3726 keylen = sizeof(struct in_addr); 3727 } else { 3728 key = &tent->k.addr6; 3729 keylen = sizeof(struct in6_addr); 3730 } 3731 3732 if ((rte = lookup_kfib(key, keylen, ti->data)) == NULL) 3733 return (0); 3734 3735 if (rte != NULL) { 3736 ta_dump_kfib_tentry(ta_state, ti, rte, tent); 3737 RTFREE_LOCKED(rte); 3738 return (0); 3739 } 3740 3741 return (ENOENT); 3742} 3743 3744static void 3745ta_foreach_kfib(void *ta_state, struct table_info *ti, ta_foreach_f *f, 3746 void *arg) 3747{ 3748 struct radix_node_head *rnh; 3749 int error; 3750 3751 rnh = rt_tables_get_rnh(ti->data, AF_INET); 3752 if (rnh != NULL) { 3753 RADIX_NODE_HEAD_RLOCK(rnh); 3754 error = rnh->rnh_walktree(rnh, (walktree_f_t *)f, arg); 3755 RADIX_NODE_HEAD_RUNLOCK(rnh); 3756 } 3757 3758 rnh = rt_tables_get_rnh(ti->data, AF_INET6); 3759 if (rnh != NULL) { 3760 RADIX_NODE_HEAD_RLOCK(rnh); 3761 error = rnh->rnh_walktree(rnh, (walktree_f_t *)f, arg); 3762 RADIX_NODE_HEAD_RUNLOCK(rnh); 3763 } 3764} 3765 3766struct table_algo cidr_kfib = { 3767 .name = "cidr:kfib", 3768 .type = IPFW_TABLE_CIDR, 3769 .flags = TA_FLAG_READONLY, 3770 .ta_buf_size = 0, 3771 .init = ta_init_kfib, 3772 .destroy = ta_destroy_kfib, 3773 .foreach = ta_foreach_kfib, 3774 .dump_tentry = ta_dump_kfib_tentry, 3775 .find_tentry = ta_find_kfib_tentry, 3776 .dump_tinfo = ta_dump_kfib_tinfo, 3777 .print_config = ta_print_kfib_config, 3778}; 3779 |
|
3522void 3523ipfw_table_algo_init(struct ip_fw_chain *ch) 3524{ 3525 size_t sz; 3526 3527 /* 3528 * Register all algorithms presented here. 3529 */ 3530 sz = sizeof(struct table_algo); 3531 ipfw_add_table_algo(ch, &cidr_radix, sz, &cidr_radix.idx); 3532 ipfw_add_table_algo(ch, &cidr_hash, sz, &cidr_hash.idx); 3533 ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx); 3534 ipfw_add_table_algo(ch, &number_array, sz, &number_array.idx); 3535 ipfw_add_table_algo(ch, &flow_hash, sz, &flow_hash.idx); | 3780void 3781ipfw_table_algo_init(struct ip_fw_chain *ch) 3782{ 3783 size_t sz; 3784 3785 /* 3786 * Register all algorithms presented here. 3787 */ 3788 sz = sizeof(struct table_algo); 3789 ipfw_add_table_algo(ch, &cidr_radix, sz, &cidr_radix.idx); 3790 ipfw_add_table_algo(ch, &cidr_hash, sz, &cidr_hash.idx); 3791 ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx); 3792 ipfw_add_table_algo(ch, &number_array, sz, &number_array.idx); 3793 ipfw_add_table_algo(ch, &flow_hash, sz, &flow_hash.idx); |
3794 ipfw_add_table_algo(ch, &cidr_kfib, sz, &cidr_kfib.idx); |
|
3536} 3537 3538void 3539ipfw_table_algo_destroy(struct ip_fw_chain *ch) 3540{ 3541 3542 ipfw_del_table_algo(ch, cidr_radix.idx); 3543 ipfw_del_table_algo(ch, cidr_hash.idx); 3544 ipfw_del_table_algo(ch, iface_idx.idx); 3545 ipfw_del_table_algo(ch, number_array.idx); 3546 ipfw_del_table_algo(ch, flow_hash.idx); | 3795} 3796 3797void 3798ipfw_table_algo_destroy(struct ip_fw_chain *ch) 3799{ 3800 3801 ipfw_del_table_algo(ch, cidr_radix.idx); 3802 ipfw_del_table_algo(ch, cidr_hash.idx); 3803 ipfw_del_table_algo(ch, iface_idx.idx); 3804 ipfw_del_table_algo(ch, number_array.idx); 3805 ipfw_del_table_algo(ch, flow_hash.idx); |
3806 ipfw_del_table_algo(ch, cidr_kfib.idx); |
|
3547} 3548 3549 | 3807} 3808 3809 |