Deleted Added
full compact
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