From ff87172709d0fff1ac43183c38c05732ff2b8c9a Mon Sep 17 00:00:00 2001 From: Bart De Schuymer Date: Tue, 3 Jun 2003 18:47:33 +0000 Subject: module versioning --- kernel/linux2.5/net/bridge/netfilter/ebt_arp.c | 7 ++- kernel/linux2.5/net/bridge/netfilter/ebt_dnat.c | 7 ++- kernel/linux2.5/net/bridge/netfilter/ebt_ip.c | 7 ++- kernel/linux2.5/net/bridge/netfilter/ebt_log.c | 35 +++++++----- kernel/linux2.5/net/bridge/netfilter/ebt_mark.c | 7 ++- kernel/linux2.5/net/bridge/netfilter/ebt_mark_m.c | 7 ++- kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c | 8 ++- .../linux2.5/net/bridge/netfilter/ebt_redirect.c | 8 ++- kernel/linux2.5/net/bridge/netfilter/ebt_snat.c | 7 ++- kernel/linux2.5/net/bridge/netfilter/ebt_vlan.c | 18 +++--- kernel/linux2.5/net/bridge/netfilter/ebtables.c | 64 ++++++++++++++++++---- 11 files changed, 133 insertions(+), 42 deletions(-) (limited to 'kernel/linux2.5/net') diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c b/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c index d63d720..16cec6d 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_arp.c @@ -94,13 +94,17 @@ static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in return EBT_MATCH; } +static struct ebt_match filter_arp; static int ebt_arp_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_arp_info *info = (struct ebt_arp_info *)data; if (datalen != sizeof(struct ebt_arp_info)) return -EINVAL; + if (ebt_check_version(version, filter_arp.version, filter_arp.name)) + return -EINVAL; if ((e->ethproto != __constant_htons(ETH_P_ARP) && e->ethproto != __constant_htons(ETH_P_RARP)) || e->invflags & EBT_IPROTO) @@ -116,6 +120,7 @@ static struct ebt_match filter_arp = .match = ebt_filter_arp, .check = ebt_arp_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_dnat.c b/kernel/linux2.5/net/bridge/netfilter/ebt_dnat.c index fd9a624..ffc986a 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_dnat.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_dnat.c @@ -24,8 +24,10 @@ static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr, return info->target; } +static struct ebt_target dnat; static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_nat_info *info = (struct ebt_nat_info *)data; @@ -38,6 +40,8 @@ static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask, return -EINVAL; if (datalen != sizeof(struct ebt_nat_info)) return -EINVAL; + if (ebt_check_version(version, dnat.version, dnat.name)) + return -EINVAL; if (INVALID_TARGET) return -EINVAL; return 0; @@ -49,6 +53,7 @@ static struct ebt_target dnat = .target = ebt_target_dnat, .check = ebt_target_dnat_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c b/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c index 7ef0662..9dc311a 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_ip.c @@ -70,13 +70,17 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in, return EBT_MATCH; } +static struct ebt_match filter_ip; static int ebt_ip_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_ip_info *info = (struct ebt_ip_info *)data; if (datalen != sizeof(struct ebt_ip_info)) return -EINVAL; + if (ebt_check_version(version, filter_ip.version, filter_ip.name)) + return -EINVAL; if (e->ethproto != __constant_htons(ETH_P_IP) || e->invflags & EBT_IPROTO) return -EINVAL; @@ -102,6 +106,7 @@ static struct ebt_match filter_ip = .match = ebt_filter_ip, .check = ebt_ip_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_log.c b/kernel/linux2.5/net/bridge/netfilter/ebt_log.c index e7a3ef4..72dec1e 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_log.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_log.c @@ -17,21 +17,6 @@ static spinlock_t ebt_log_lock = SPIN_LOCK_UNLOCKED; -static int ebt_log_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) -{ - struct ebt_log_info *info = (struct ebt_log_info *)data; - - if (datalen != sizeof(struct ebt_log_info)) - return -EINVAL; - if (info->bitmask & ~EBT_LOG_MASK) - return -EINVAL; - if (info->loglevel >= 8) - return -EINVAL; - info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; - return 0; -} - struct tcpudphdr { uint16_t src; @@ -135,12 +120,32 @@ out: spin_unlock_bh(&ebt_log_lock); } +static struct ebt_watcher log; +static int ebt_log_check(const char *tablename, unsigned int hookmask, + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) +{ + struct ebt_log_info *info = (struct ebt_log_info *)data; + + if (datalen != sizeof(struct ebt_log_info)) + return -EINVAL; + if (ebt_check_version(version, log.version, log.name)) + return -EINVAL; + if (info->bitmask & ~EBT_LOG_MASK) + return -EINVAL; + if (info->loglevel >= 8) + return -EINVAL; + info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0'; + return 0; +} + static struct ebt_watcher log = { .name = EBT_LOG_WATCHER, .watcher = ebt_log, .check = ebt_log_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_mark.c b/kernel/linux2.5/net/bridge/netfilter/ebt_mark.c index b7a87f6..3a60cea 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_mark.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_mark.c @@ -30,13 +30,17 @@ static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr, return info->target; } +static struct ebt_target mark_target; static int ebt_target_mark_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data; if (datalen != sizeof(struct ebt_mark_t_info)) return -EINVAL; + if (ebt_check_version(version, mark_target.version, mark_target.name)) + return -EINVAL; if (BASE_CHAIN && info->target == EBT_RETURN) return -EINVAL; CLEAR_BASE_CHAIN_BIT; @@ -51,6 +55,7 @@ static struct ebt_target mark_target = .target = ebt_target_mark, .check = ebt_target_mark_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_mark_m.c b/kernel/linux2.5/net/bridge/netfilter/ebt_mark_m.c index c710b4e..0bb5a74 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_mark_m.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_mark_m.c @@ -23,13 +23,17 @@ static int ebt_filter_mark(const struct sk_buff *skb, return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert); } +static struct ebt_match filter_mark; static int ebt_mark_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data; if (datalen != sizeof(struct ebt_mark_m_info)) return -EINVAL; + if (ebt_check_version(version, filter_mark.version, filter_mark.name)) + return -EINVAL; if (info->bitmask & ~EBT_MARK_MASK) return -EINVAL; if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND)) @@ -45,6 +49,7 @@ static struct ebt_match filter_mark = .match = ebt_filter_mark, .check = ebt_mark_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c b/kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c index f6458ad..50e6641 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_pkttype.c @@ -23,13 +23,18 @@ static int ebt_filter_pkttype(const struct sk_buff *skb, return (skb->pkt_type != info->pkt_type) ^ info->invert; } +static struct ebt_match filter_pkttype; static int ebt_pkttype_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data; if (datalen != sizeof(struct ebt_pkttype_info)) return -EINVAL; + if (ebt_check_version(version, filter_pkttype.version, + filter_pkttype.name)) + return -EINVAL; if (info->invert != 0 && info->invert != 1) return -EINVAL; /* Allow any pkt_type value */ @@ -42,6 +47,7 @@ static struct ebt_match filter_pkttype = .match = ebt_filter_pkttype, .check = ebt_pkttype_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_redirect.c b/kernel/linux2.5/net/bridge/netfilter/ebt_redirect.c index d482b3d..73b1e49 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_redirect.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_redirect.c @@ -31,13 +31,18 @@ static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr, return info->target; } +static struct ebt_target redirect_target; static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_redirect_info *info = (struct ebt_redirect_info *)data; if (datalen != sizeof(struct ebt_redirect_info)) return -EINVAL; + if (ebt_check_version(version, redirect_target.version, + redirect_target.name)) + return -EINVAL; if (BASE_CHAIN && info->target == EBT_RETURN) return -EINVAL; CLEAR_BASE_CHAIN_BIT; @@ -55,6 +60,7 @@ static struct ebt_target redirect_target = .target = ebt_target_redirect, .check = ebt_target_redirect_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_snat.c b/kernel/linux2.5/net/bridge/netfilter/ebt_snat.c index 3c0a650..b457dad 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_snat.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_snat.c @@ -23,13 +23,17 @@ static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr, return info->target; } +static struct ebt_target snat; static int ebt_target_snat_check(const char *tablename, unsigned int hookmask, - const struct ebt_entry *e, void *data, unsigned int datalen) + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_nat_info *info = (struct ebt_nat_info *) data; if (datalen != sizeof(struct ebt_nat_info)) return -EINVAL; + if (ebt_check_version(version, snat.version, snat.name)) + return -EINVAL; if (BASE_CHAIN && info->target == EBT_RETURN) return -EINVAL; CLEAR_BASE_CHAIN_BIT; @@ -48,6 +52,7 @@ static struct ebt_target snat = .target = ebt_target_snat, .check = ebt_target_snat_check, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebt_vlan.c b/kernel/linux2.5/net/bridge/netfilter/ebt_vlan.c index 54120a7..5e20e88 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebt_vlan.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebt_vlan.c @@ -42,10 +42,8 @@ MODULE_LICENSE("GPL"); #define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return EBT_NOMATCH;} static int -ebt_filter_vlan(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const void *data, unsigned int datalen) +ebt_filter_vlan(const struct sk_buff *skb, const struct net_device *in, + const struct net_device *out, const void *data, unsigned int datalen) { struct ebt_vlan_info *info = (struct ebt_vlan_info *) data; struct vlan_ethhdr frame; @@ -86,10 +84,11 @@ ebt_filter_vlan(const struct sk_buff *skb, return EBT_MATCH; } +static struct ebt_match filter_vlan; static int -ebt_check_vlan(const char *tablename, - unsigned int hooknr, - const struct ebt_entry *e, void *data, unsigned int datalen) +ebt_check_vlan(const char *tablename, unsigned int hooknr, + const struct ebt_entry *e, void *data, unsigned int datalen, + unsigned int version) { struct ebt_vlan_info *info = (struct ebt_vlan_info *) data; @@ -101,6 +100,10 @@ ebt_check_vlan(const char *tablename, return -EINVAL; } + if (ebt_check_version(version, filter_vlan.version, + filter_vlan.name)) + return -EINVAL; + /* Is it 802.1Q frame checked? */ if (e->ethproto != __constant_htons(ETH_P_8021Q)) { DEBUG_MSG @@ -174,6 +177,7 @@ static struct ebt_match filter_vlan = { .match = ebt_filter_vlan, .check = ebt_check_vlan, .me = THIS_MODULE, + .version = VERSIONIZE(1,0), }; static int __init init(void) diff --git a/kernel/linux2.5/net/bridge/netfilter/ebtables.c b/kernel/linux2.5/net/bridge/netfilter/ebtables.c index 7f32804..ea2dc75 100644 --- a/kernel/linux2.5/net/bridge/netfilter/ebtables.c +++ b/kernel/linux2.5/net/bridge/netfilter/ebtables.c @@ -35,24 +35,59 @@ #define ASSERT_WRITE_LOCK(x) #include -#if 0 -/* use this for remote debugging - * Copyright (C) 1998 by Ori Pomerantz +/* Copyright (C) 1998 by Ori Pomerantz * Print the string to the appropriate tty, the one - * the current task uses + * the current task uses. + * Unlike prink, this function will print text on xterms and ssh connections. + * Useful for telling the user she did something wrong, without it being logged. */ -static void print_string(char *str) +void ebt_print_string(const char *fmt, ...) { struct tty_struct *my_tty; + static char print_buf[PRINT_BUFFER_LENGTH]; /* The tty for the current task */ my_tty = current->tty; if (my_tty != NULL) { - my_tty->driver->write(my_tty, 0, str, strlen(str)); + va_list args; + int printed_len; + + va_start(args, fmt); + printed_len = vsnprintf(print_buf, sizeof(print_buf), fmt, args); + va_end(args); + my_tty->driver->write(my_tty, 0, print_buf, printed_len); my_tty->driver->write(my_tty, 0, "\015\012", 2); } } +/* different major number implies incompatibility. Same major number + * but userspace minor number > kernel minor number also implies + * incompatibility. + * Minor numbers can be used when adding new functionality while + * compatibility with older versions with the same major number is + * guaranteed. + */ +int ebt_check_version(unsigned int u,unsigned int k, const char *n) +{ + int ret = 0; + unsigned int uma = u >> NR_MINORS; + unsigned int umi = u - (uma << NR_MINORS); + unsigned int kma = k >> NR_MINORS; + unsigned int kmi = k - (kma << NR_MINORS); + + if (uma != kma || umi > kmi) { + ret = 1; + ebt_print_string("Conflicting version between the \'%s\'" + " userspace and kernel module: the userspace module version" + " is %d.%d, the kernel module version is %d.%d", + n, uma, umi, kma, kmi); + } + return ret; +} + + +#if 0 +/* use this for remote debugging */ #define BUGPRINT(args) print_string(args); #else #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ @@ -87,7 +122,9 @@ static LIST_HEAD(ebt_matches); static LIST_HEAD(ebt_watchers); static struct ebt_target ebt_standard_target = -{ {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL}; +{ + .name = EBT_STANDARD_TARGET, +}; static inline int ebt_do_watcher (struct ebt_entry_watcher *w, const struct sk_buff *skb, const struct net_device *in, @@ -366,8 +403,8 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e, } up(&ebt_mutex); if (match->check && - match->check(name, hookmask, e, m->data, m->match_size) != 0) { - BUGPRINT("match->check failed\n"); + match->check(name, hookmask, e, m->data, m->match_size, + m->version) != 0) { module_put(match->me); return -EINVAL; } @@ -395,8 +432,8 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, } up(&ebt_mutex); if (watcher->check && - watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) { - BUGPRINT("watcher->check failed\n"); + watcher->check(name, hookmask, e, w->data, w->watcher_size, + w->version) != 0) { module_put(watcher->me); return -EINVAL; } @@ -653,7 +690,8 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, } else if ((e->target_offset + t->target_size + sizeof(struct ebt_entry_target) > e->next_offset) || (t->u.target->check && - t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){ + t->u.target->check(name, hookmask, e, t->data, t->target_size, + t->version) != 0)) { module_put(t->u.target->me); ret = -EFAULT; goto cleanup_watchers; @@ -1495,6 +1533,8 @@ EXPORT_SYMBOL(ebt_unregister_watcher); EXPORT_SYMBOL(ebt_register_target); EXPORT_SYMBOL(ebt_unregister_target); EXPORT_SYMBOL(ebt_do_table); +EXPORT_SYMBOL(ebt_print_string); +EXPORT_SYMBOL(ebt_check_version); module_init(init); module_exit(fini); MODULE_LICENSE("GPL"); -- cgit v1.2.3