From: "Rémi Denis-Courmont" <rdenis@simphalempin.com>
To: Yasuyuki KOZAKAI <yasuyuki.kozakai@toshiba.co.jp>
Cc: ljlane@debian.org, netfilter-devel@lists.netfilter.org
Subject: Re: [PATCH] iptables: ip6table version support and libip6t_multiport.fix
Date: Tue, 3 Oct 2006 22:58:28 +0300 [thread overview]
Message-ID: <200610032258.30338@auguste.remlab.net> (raw)
In-Reply-To: <200610031430.k93EUJgA008197@toshiba.co.jp>
Le mardi 3 octobre 2006 17:30, vous avez écrit :
> IPv4 multiport match (and policy match, too) would help you. It has
> the line
>
> #include ../../include/netfilter_ipv4/ipt_multiport.h
>
> and definitions for old kernel are included in the header.
Ok. This time there is no trace of (xt|XT)_ at all:
diff -Nru iptables-1.3.5.orig/extensions/libip6t_multiport.c
iptables-1.3.5/extensions/libip6t_multiport.c
--- iptables-1.3.5.orig/extensions/libip6t_multiport.c 2005-02-19
21:19:17.000000000 +0200
+++ iptables-1.3.5/extensions/libip6t_multiport.c 2006-08-27
13:03:36.000000000 +0300
@@ -20,6 +20,23 @@
" --dports ...\n"
" match destination port(s)\n"
" --ports port[,port,port]\n"
+" match both source and destination port(s)\n"
+" NOTE: this kernel does not support port ranges in multiport.\n",
+IPTABLES_VERSION);
+}
+
+static void
+help_v1(void)
+{
+ printf(
+"multiport v%s options:\n"
+" --source-ports [!] port[,port:port,port...]\n"
+" --sports ...\n"
+" match source port(s)\n"
+" --destination-ports [!] port[,port:port,port...]\n"
+" --dports ...\n"
+" match destination port(s)\n"
+" --ports [!] port[,port:port,port]\n"
" match both source and destination port(s)\n",
IPTABLES_VERSION);
}
@@ -49,7 +66,7 @@
{
unsigned int portnum;
- if ((string_to_number(port, 0, 65535, &portnum)) != -1 ||
+ if (string_to_number(port, 0, 65535, &portnum) != -1 ||
(portnum = service_to_port(port, proto)) != -1)
return (u_int16_t)portnum;
@@ -77,6 +94,46 @@
return i;
}
+static void
+parse_multi_ports_v1(const char *portstring,
+ struct xt_multiport_v1 *multiinfo,
+ const char *proto)
+{
+ char *buffer, *cp, *next, *range;
+ unsigned int i;
+ u_int16_t m;
+
+ buffer = strdup(portstring);
+ if (!buffer) exit_error(OTHER_PROBLEM, "strdup failed");
+
+ for (i=0; i<XT_MULTI_PORTS; i++)
+ multiinfo->pflags[i] = 0;
+
+ for (cp=buffer, i=0; cp && i<XT_MULTI_PORTS; cp=next, i++) {
+ next=strchr(cp, ',');
+ if (next) *next++='\0';
+ range = strchr(cp, ':');
+ if (range) {
+ if (i == XT_MULTI_PORTS-1)
+ exit_error(PARAMETER_PROBLEM,
+ "too many ports specified");
+ *range++ = '\0';
+ }
+ multiinfo->ports[i] = parse_port(cp, proto);
+ if (range) {
+ multiinfo->pflags[i] = 1;
+ multiinfo->ports[++i] = parse_port(range, proto);
+ if (multiinfo->ports[i-1] >= multiinfo->ports[i])
+ exit_error(PARAMETER_PROBLEM,
+ "invalid portrange specified");
+ m <<= 1;
+ }
+ }
+ multiinfo->count = i;
+ if (cp) exit_error(PARAMETER_PROBLEM, "too many ports specified");
+ free(buffer);
+}
+
/* Initialize the match. */
static void
init(struct ip6t_entry_match *m, unsigned int *nfcache)
@@ -150,6 +207,52 @@
return 1;
}
+static int
+parse_v1(int c, char **argv, int invert, unsigned int *flags,
+ const struct ip6t_entry *entry,
+ unsigned int *nfcache,
+ struct ip6t_entry_match **match)
+{
+ const char *proto;
+ struct xt_multiport_v1 *multiinfo
+ = (struct xt_multiport_v1 *)(*match)->data;
+
+ switch (c) {
+ case '1':
+ check_inverse(argv[optind-1], &invert, &optind, 0);
+ proto = check_proto(entry);
+ parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
+ multiinfo->flags = IP6T_MULTIPORT_SOURCE;
+ break;
+
+ case '2':
+ check_inverse(argv[optind-1], &invert, &optind, 0);
+ proto = check_proto(entry);
+ parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
+ multiinfo->flags = IP6T_MULTIPORT_DESTINATION;
+ break;
+
+ case '3':
+ check_inverse(argv[optind-1], &invert, &optind, 0);
+ proto = check_proto(entry);
+ parse_multi_ports_v1(argv[optind-1], multiinfo, proto);
+ multiinfo->flags = IP6T_MULTIPORT_EITHER;
+ break;
+
+ default:
+ return 0;
+ }
+
+ if (invert)
+ multiinfo->invert = 1;
+
+ if (*flags)
+ exit_error(PARAMETER_PROBLEM,
+ "multiport can only have one option");
+ *flags = 1;
+ return 1;
+}
+
/* Final check; must specify something. */
static void
final_check(unsigned int flags)
@@ -218,6 +321,49 @@
printf(" ");
}
+static void
+print_v1(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_match *match,
+ int numeric)
+{
+ const struct xt_multiport_v1 *multiinfo
+ = (const struct xt_multiport_v1 *)match->data;
+ unsigned int i;
+
+ printf("multiport ");
+
+ switch (multiinfo->flags) {
+ case IP6T_MULTIPORT_SOURCE:
+ printf("sports ");
+ break;
+
+ case IP6T_MULTIPORT_DESTINATION:
+ printf("dports ");
+ break;
+
+ case IP6T_MULTIPORT_EITHER:
+ printf("ports ");
+ break;
+
+ default:
+ printf("ERROR ");
+ break;
+ }
+
+ if (multiinfo->invert)
+ printf("! ");
+
+ for (i=0; i < multiinfo->count; i++) {
+ printf("%s", i ? "," : "");
+ print_port(multiinfo->ports[i], ip->proto, numeric);
+ if (multiinfo->pflags[i]) {
+ printf(":");
+ print_port(multiinfo->ports[++i], ip->proto, numeric);
+ }
+ }
+ printf(" ");
+}
+
/* Saves the union ip6t_matchinfo in parsable form to stdout. */
static void save(const struct ip6t_ip6 *ip, const struct
ip6t_entry_match *match)
{
@@ -246,6 +392,41 @@
printf(" ");
}
+static void save_v1(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_match *match)
+{
+ const struct xt_multiport_v1 *multiinfo
+ = (const struct xt_multiport_v1 *)match->data;
+ unsigned int i;
+
+ switch (multiinfo->flags) {
+ case IP6T_MULTIPORT_SOURCE:
+ printf("--sports ");
+ break;
+
+ case IP6T_MULTIPORT_DESTINATION:
+ printf("--dports ");
+ break;
+
+ case IP6T_MULTIPORT_EITHER:
+ printf("--ports ");
+ break;
+ }
+
+ if (multiinfo->invert)
+ printf("! ");
+
+ for (i=0; i < multiinfo->count; i++) {
+ printf("%s", i ? "," : "");
+ print_port(multiinfo->ports[i], ip->proto, 1);
+ if (multiinfo->pflags[i]) {
+ printf(":");
+ print_port(multiinfo->ports[++i], ip->proto, 1);
+ }
+ }
+ printf(" ");
+}
+
static struct ip6tables_match multiport = {
.name = "multiport",
.version = IPTABLES_VERSION,
@@ -260,8 +441,25 @@
.extra_opts = opts,
};
+static struct ip6tables_match multiport_v1 = {
+ .next = NULL,
+ .name = "multiport",
+ .revision = 1,
+ .version = IPTABLES_VERSION,
+ .size = IP6T_ALIGN(sizeof(struct xt_multiport_v1)),
+ .userspacesize = IP6T_ALIGN(sizeof(struct xt_multiport_v1)),
+ .help = &help_v1,
+ .init = &init,
+ .parse = &parse_v1,
+ .final_check = &final_check,
+ .print = &print_v1,
+ .save = &save_v1,
+ .extra_opts = opts
+};
+
void
_init(void)
{
register_match6(&multiport);
+ register_match6(&multiport_v1);
}
diff -Nru iptables-1.3.5.orig/include/ip6tables.h
iptables-1.3.5/include/ip6tables.h
--- iptables-1.3.5.orig/include/ip6tables.h 2006-01-30
10:43:09.000000000 +0200
+++ iptables-1.3.5/include/ip6tables.h 2006-08-27 13:02:55.000000000
+0300
@@ -22,6 +22,9 @@
ip6t_chainlabel name;
+ /* Revision of match (0 by default). */
+ u_int8_t revision;
+
const char *version;
/* Size of match data. */
diff -Nru iptables-1.3.5.orig/ip6tables.c iptables-1.3.5/ip6tables.c
--- iptables-1.3.5.orig/ip6tables.c 2006-01-30 10:43:12.000000000 +0200
+++ iptables-1.3.5/ip6tables.c 2006-08-27 13:13:37.000000000 +0300
@@ -193,6 +193,8 @@
const char *program_name;
char *lib_dir;
+int kernel_version;
+
/* Keeping track of external matches and targets: linked lists. */
struct ip6tables_match *ip6tables_matches = NULL;
struct ip6tables_target *ip6tables_targets = NULL;
@@ -1047,10 +1049,51 @@
return merge;
}
+static int compatible_revision(const char *name, u_int8_t revision, int
opt)
+{
+ struct ip6t_get_revision rev;
+ socklen_t s = sizeof(rev);
+ int max_rev, sockfd;
+
+ sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
+ if (sockfd < 0) {
+ fprintf(stderr, "Could not open socket to kernel: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+
+ strcpy(rev.name, name);
+ rev.revision = revision;
+
+ max_rev = getsockopt(sockfd, IPPROTO_IPV6, opt, &rev, &s);
+ if (max_rev < 0) {
+ /* Definitely don't support this? */
+ if (errno == EPROTONOSUPPORT) {
+ close(sockfd);
+ return 0;
+ } else if (errno == ENOPROTOOPT) {
+ close(sockfd);
+ /* Assume only revision 0 support (old kernel) */
+ return (revision == 0);
+ } else {
+ fprintf(stderr, "getsockopt failed strangely: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ }
+ close(sockfd);
+ return 1;
+}
+
+static int compatible_match_revision(const char *name, u_int8_t
revision)
+{
+ return compatible_revision(name, revision,
IP6T_SO_GET_REVISION_MATCH);
+}
+
void
register_match6(struct ip6tables_match *me)
{
- struct ip6tables_match **i;
+ struct ip6tables_match **i, *old;
if (strcmp(me->version, program_version) != 0) {
fprintf(stderr, "%s: match `%s' v%s (I'm v%s).\n",
@@ -1058,12 +1101,36 @@
exit(1);
}
- if (find_match(me->name, DURING_LOAD, NULL)) {
- fprintf(stderr, "%s: match `%s' already registered.\n",
+ /* Revision field stole a char from name. */
+ if (strlen(me->name) >= IP6T_FUNCTION_MAXNAMELEN-1) {
+ fprintf(stderr, "%s: target `%s' has invalid name\n",
program_name, me->name);
exit(1);
}
+ old = find_match(me->name, DURING_LOAD, NULL);
+ if (old) {
+ if (old->revision == me->revision) {
+ fprintf(stderr,
+ "%s: match `%s' already registered.\n",
+ program_name, me->name);
+ exit(1);
+ }
+
+ /* Now we have two (or more) options, check compatibility. */
+ if (compatible_match_revision(old->name, old->revision)
+ && old->revision > me->revision)
+ return;
+
+ /* Replace if compatible. */
+ if (!compatible_match_revision(me->name, me->revision))
+ return;
+
+ /* Delete old one. */
+ for (i = &ip6tables_matches; *i!=old; i = &(*i)->next);
+ *i = old->next;
+ }
+
if (me->size != IP6T_ALIGN(me->size)) {
fprintf(stderr, "%s: match `%s' has invalid size %u.\n",
program_name, me->name, (unsigned int)me->size);
@@ -1700,6 +1767,14 @@
*matches = NULL;
}
+static void set_revision(char *name, u_int8_t revision)
+{
+ /* Old kernel sources don't have ".revision" field,
+ but we stole a byte from name. */
+ name[IP6T_FUNCTION_MAXNAMELEN - 2] = '\0';
+ name[IP6T_FUNCTION_MAXNAMELEN - 1] = revision;
+}
+
int do_command6(int argc, char *argv[], char **table, ip6tc_handle_t
*handle)
{
struct ip6t_entry fw, *e = NULL;
@@ -1978,6 +2053,7 @@
m->m = fw_calloc(1, size);
m->m->u.match_size = size;
strcpy(m->m->u.user.name, m->name);
+ set_revision(m->m->u.user.name, m->revision);
if (m->init != NULL)
m->init(m->m, &fw.nfcache);
opts = merge_options(opts, m->extra_opts, &m->option_offset);
@@ -2120,6 +2196,8 @@
m->m = fw_calloc(1, size);
m->m->u.match_size = size;
strcpy(m->m->u.user.name, m->name);
+ set_revision(m->m->u.user.name,
+ m->revision);
if (m->init != NULL)
m->init(m->m, &fw.nfcache);
--
Rémi Denis-Courmont
http://www.remlab.net/
next prev parent reply other threads:[~2006-10-03 19:58 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-11 1:06 [PATCH] iptables: ip6table version support and libip6t_multiport.fix Laurence J. Lane
2006-10-02 1:37 ` Laurence J. Lane
2006-10-02 4:46 ` Yasuyuki KOZAKAI
2006-10-02 14:47 ` Rémi Denis-Courmont
2006-10-03 14:30 ` Yasuyuki KOZAKAI
[not found] ` <200610031430.k93EUJgA008197@toshiba.co.jp>
2006-10-03 19:58 ` Rémi Denis-Courmont [this message]
2006-10-12 8:11 ` Yasuyuki KOZAKAI
[not found] ` <200610120811.k9C8B4Pg002384@toshiba.co.jp>
2006-10-12 14:29 ` Rémi Denis-Courmont
2006-10-13 0:50 ` Yasuyuki KOZAKAI
[not found] ` <200610190606.k9J66kRd002796@toshiba.co.jp>
2006-10-20 10:06 ` Patrick McHardy
2006-10-20 11:48 ` Yasuyuki KOZAKAI
-- strict thread matches above, loose matches on Subject: below --
2006-10-06 18:41 Compiling 1.3.6 Jorge Bastos
2006-10-08 22:21 ` Pablo Neira Ayuso
2006-10-09 15:23 ` Patrick McHardy
2006-10-09 15:36 ` Pablo Neira Ayuso
2006-10-09 15:44 ` Pablo Neira Ayuso
2006-10-09 15:58 ` Marco Berizzi
2006-10-09 16:02 ` Patrick McHardy
2006-10-09 16:10 ` Marco Berizzi
2006-10-09 17:23 ` Patrick McHardy
2006-10-09 17:57 ` Jorge Bastos
2006-10-09 16:02 ` Patrick McHardy
2006-10-19 6:06 ` [PATCH] iptables: ip6table version support and libip6t_multiport.fix Yasuyuki KOZAKAI
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200610032258.30338@auguste.remlab.net \
--to=rdenis@simphalempin.com \
--cc=ljlane@debian.org \
--cc=netfilter-devel@lists.netfilter.org \
--cc=yasuyuki.kozakai@toshiba.co.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.