]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
add userspace part of SCTP match
authorHarald Welte <laforge@gnumonks.org>
Sat, 21 Feb 2004 09:20:34 +0000 (09:20 +0000)
committerHarald Welte <laforge@gnumonks.org>
Sat, 21 Feb 2004 09:20:34 +0000 (09:20 +0000)
CURRENT_ISSUES
extensions/Makefile
extensions/libipt_sctp.c
include/linux/netfilter_ipv4/ipt_sctp.h
iptables-save.c
iptables.c

index 181c83a33b877e2da693c741f49f549f302f57f3..cdec36fa36f186d615d999b4056bfcfb4c16eea4 100644 (file)
@@ -15,8 +15,6 @@ SLOG target
        - needs to be integrated with recent nfnetlink/ctnetlink
 loop detection / nf_hipac (mail from dec 15
        - need time
-reject --with-admin-prohibited
-       - most compatible version needs to be used
 IPv6 REJECT target fix
        - important, it's a pity that it's still broken
 bi-directional ftp state tracking
@@ -28,9 +26,5 @@ expectations allegedly don't work on sparc64
        - is this in bugzilla yet?
 new bytelimit match
        - unify it with 'limit' for 2.5.x
-new hash (abcdx/...) for conntrack
-       - put patch in p-o-m, do testing, submit to kernel
-PPTP reverse key lookup <3E40CA1F.1080205@snapgear.com>
-       - ?
 boolean MARK operations
        - patch by Anders Fugmann, needs 64bit testing
index 2a45ea028b5ddec43548ee72552268f2096440e0..17a1c0090c1f3ddb86019683fe2c7c5a91e57d4f 100644 (file)
@@ -5,7 +5,7 @@
 # header files are present in the include/linux directory of this iptables
 # package (HW)
 #
-PF_EXT_SLIB:=ah connlimit connmark conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
+PF_EXT_SLIB:=ah connlimit connmark conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
 PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner standard tcp udp HL LOG MARK TRACE
 
 # Optionals
index d512fa6356a68d2ba0f35beee10f38c429b2e4d4..d47719f892cf1433a59af31d05d81190541de196 100644 (file)
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_sctp.h>
 
+#if 0
+#define DEBUGP(format, first...) printf(format, ##first)
+#define static
+#else
+#define DEBUGP(format, fist...) 
+#endif
+
+/*static void
+print_chunks(u_int32_t chunk_match_type, const u_int32_t *chunkmap, int numeric);*/
+
 /* Initialize the match. */
 static void
-init(struct ipt_entry_match *m, unsigned int *nfcache)
+init(struct ipt_entry_match *m, 
+     unsigned int *nfcache)
 {
        struct ipt_sctp_info *einfo = (struct ipt_sctp_info *)m->data;
 
+       einfo->flags = einfo->invflags = 0;
+
+       /*einfo->spts[0] = einfo->dpts[0] = 0;
        einfo->spts[1] = einfo->dpts[1] = 0xFFFF;
+       SCTP_CHUNKMAP_RESET(einfo->chunkmap);*/
 }
 
-static void help(void) 
+static void help(void)
 {
        printf(
 "SCTP match v%s options\n"
-" --sctp-chunks [!] mask comp  match when SCTP chunks & mask == comp\n"
-" --source-port [!] port[:port]\n"
+" --source-port [!] port[:port]                          match source port(s)\n"
 " --sport ...\n"
-"                               match source port(s)"
-" --destination-port [!] port[:port]\n"
-" --dport ...\n\n",
+" --destination-port [!] port[:port]                     match destination port(s)\n"
+" --dport ...\n" 
+" --chunk-types [!] (all|any|none) (chunktype[:flags])+        match if all, any or none of\n"
+"                                                      chunktypes are present\n"
+"chunktypes - DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK ALL NONE\n",
        IPTABLES_VERSION);
 }
 
@@ -44,7 +60,7 @@ static struct option opts[] = {
        { .name = "sport", .has_arg = 1, .flag = 0, .val = '1' },
        { .name = "destination-port", .has_arg = 1, .flag = 0, .val = '2' },
        { .name = "dport", .has_arg = 1, .flag = 0, .val = '2' },
-       { .name = "sctp-chunks", .has_arg = 1, .flag = 0, .val = '3' },
+       { .name = "chunk-types", .has_arg = 1, .flag = 0, .val = '3' },
        { .name = 0 }
 };
 
@@ -64,24 +80,27 @@ parse_sctp_port(const char *port)
 {
        unsigned int portnum;
 
+       DEBUGP("%s\n", port);
        if (string_to_number(port, 0, 65535, &portnum) != -1 ||
            (portnum = service_to_port(port)) != -1)
                return (u_int16_t)portnum;
 
        exit_error(PARAMETER_PROBLEM,
-                  "invalid TCP port/service `%s' specified", port);
+                  "invalid SCTP port/service `%s' specified", port);
 }
 
-
 static void
-parse_sctp_ports(const char *portstring, u_int16_t *ports)
+parse_sctp_ports(const char *portstring, 
+                u_int16_t *ports)
 {
        char *buffer;
        char *cp;
 
        buffer = strdup(portstring);
-       if ((cp = strchr(buffer, ':')) == NULL)
+       DEBUGP("%s\n", portstring);
+       if ((cp = strchr(buffer, ':')) == NULL) {
                ports[0] = ports[1] = parse_sctp_port(buffer);
+       }
        else {
                *cp = '\0';
                cp++;
@@ -98,51 +117,62 @@ parse_sctp_ports(const char *portstring, u_int16_t *ports)
 
 struct sctp_chunk_names {
        const char *name;
-       unsigned int flag;
+       unsigned int chunk_type;
 };
 
-/* FIXME: */
-#define ALL_CHUNKS     0xabcdef
+/*'ALL' and 'NONE' will be treated specially. */
 static struct sctp_chunk_names sctp_chunk_names[]
-= { { .name = "DATA",          .flag = (1 << 0) },
-    { .name = "INIT",          .flag = (1 << 1) },
-    { .name = "INIT_ACK",      .flag = (1 << 2) },
-    { .name = "SACK",          .flag = (1 << 3) },
-    { .name = "HEARTBEAT",     .flag = (1 << 4) },
-    { .name = "HEARTBEAT_ACK", .flag = (1 << 5) },
-    { .name = "ABORT",         .flag = (1 << 6) },
-    { .name = "SHUTDOWN",      .flag = (1 << 7) },
-    { .name = "SHUTDOWN_ACK",  .flag = (1 << 8) },
-    { .name = "ERROR",         .flag = (1 << 9) },
-    { .name = "COOKIE_ECHO",   .flag = (1 << 10) },
-    { .name = "COOKIE_ACK",    .flag = (1 << 11) },
-    { .name = "ECN_ECNE",      .flag = (1 << 12) },
-    { .name = "ECN_CWR",       .flag = (1 << 13) },
-    { .name = "SHUTDOWN_COMPLETE", .flag = (1 << 14) },
-    { .name = "ASCONF",                .flag = (1 << 31) },
-    { .name = "ASCONF_ACK",    .flag = (1 << 30) },
-    { .name = "ALL",           .flag = ALL_CHUNKS },
-    { .name = "NONE",          .flag = 0 },
+= { { .name = "DATA",          .chunk_type = 0 },
+    { .name = "INIT",          .chunk_type = 1 },
+    { .name = "INIT_ACK",      .chunk_type = 2 },
+    { .name = "SACK",          .chunk_type = 3 },
+    { .name = "HEARTBEAT",     .chunk_type = 4 },
+    { .name = "HEARTBEAT_ACK", .chunk_type = 5 },
+    { .name = "ABORT",         .chunk_type = 6 },
+    { .name = "SHUTDOWN",      .chunk_type = 7 },
+    { .name = "SHUTDOWN_ACK",  .chunk_type = 8 },
+    { .name = "ERROR",         .chunk_type = 9 },
+    { .name = "COOKIE_ECHO",   .chunk_type = 10 },
+    { .name = "COOKIE_ACK",    .chunk_type = 11 },
+    { .name = "ECN_ECNE",      .chunk_type = 12 },
+    { .name = "ECN_CWR",       .chunk_type = 13 },
+    { .name = "SHUTDOWN_COMPLETE", .chunk_type = 14 },
+    { .name = "ASCONF",                .chunk_type = 31 },
+    { .name = "ASCONF_ACK",    .chunk_type = 30 },
 };
 
-
-static unsigned int
-parse_sctp_chunk(const char *flags)
+static void
+parse_sctp_chunk(struct ipt_sctp_info *einfo, 
+                const char *chunks)
 {
-       unsigned int ret = 0;
        char *ptr;
        char *buffer;
+       unsigned int i;
+       int found = 0;
+
+       buffer = strdup(chunks);
+       DEBUGP("Buffer: %s\n", buffer);
 
-       buffer = strdup(flags);
+       SCTP_CHUNKMAP_RESET(einfo->chunkmap);
+
+       if (!strcasecmp(buffer, "ALL")) {
+               SCTP_CHUNKMAP_SET_ALL(einfo->chunkmap);
+               goto out;
+       }
+       
+       if (!strcasecmp(buffer, "NONE")) {
+               SCTP_CHUNKMAP_RESET(einfo->chunkmap);
+               goto out;
+       }
 
        for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
-               unsigned int i;
-               int found = 0;
-               for (i = 0;
-                    i < sizeof(sctp_chunk_names)/sizeof(struct sctp_chunk_names);
-                    i++) {
+               found = 0;
+               DEBUGP("Next Chunk type %s\n", ptr);
+               for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
                        if (strcasecmp(sctp_chunk_names[i].name, ptr) == 0) {
-                               ret |= sctp_chunk_names[i].flag;
+                               DEBUGP("Chunk num %d\n", sctp_chunk_names[i].chunk_type);
+                               SCTP_CHUNKMAP_SET(einfo->chunkmap, 
+                                       sctp_chunk_names[i].chunk_type);
                                found = 1;
                                break;
                        }
@@ -151,28 +181,31 @@ parse_sctp_chunk(const char *flags)
                        exit_error(PARAMETER_PROBLEM,
                                   "Unknown sctp chunk `%s'", ptr);
        }
-
+out:
        free(buffer);
-       return ret;
 }
 
 static void
 parse_sctp_chunks(struct ipt_sctp_info *einfo,
-               const char *mask,
-               const char *cmp,
-               int invert)
+                 const char *match_type,
+                 const char *chunks)
 {
-       einfo->chunks = parse_sctp_chunk(mask);
-       einfo->chunk_mask = parse_sctp_chunk(cmp);
+       DEBUGP("Match type: %s Chunks: %s\n", match_type, chunks);
+       if (!strcasecmp(match_type, "ANY")) {
+               einfo->chunk_match_type = SCTP_CHUNK_MATCH_ANY;
+       } else  if (!strcasecmp(match_type, "ALL")) {
+               einfo->chunk_match_type = SCTP_CHUNK_MATCH_ALL;
+       } else  if (!strcasecmp(match_type, "ONLY")) {
+               einfo->chunk_match_type = SCTP_CHUNK_MATCH_ONLY;
+       } else {
+               exit_error (PARAMETER_PROBLEM, 
+                       "Match type has to be one of \"ALL\", \"ANY\" or \"ONLY\"");
+       }
 
-       if (invert)
-               einfo->invflags |= IPT_SCTP_INV_CHUNKS;
+       SCTP_CHUNKMAP_RESET(einfo->chunkmap);
+       parse_sctp_chunk(einfo, chunks);
 }
 
-#define SCTP_SRC_PORTS 0x01
-#define SCTP_DST_PORTS 0x02
-#define SCTP_CHUNKS    0x03
-
 static int
 parse(int c, char **argv, int invert, unsigned int *flags,
       const struct ipt_entry *entry,
@@ -184,48 +217,53 @@ parse(int c, char **argv, int invert, unsigned int *flags,
 
        switch (c) {
        case '1':
-               if (*flags & SCTP_SRC_PORTS)
+               if (*flags & IPT_SCTP_SRC_PORTS)
                        exit_error(PARAMETER_PROBLEM,
                                   "Only one `--source-port' allowed");
+               einfo->flags |= IPT_SCTP_SRC_PORTS;
                check_inverse(optarg, &invert, &optind, 0);
                parse_sctp_ports(argv[optind-1], einfo->spts);
                if (invert)
-                       einfo->invflags |= IPT_SCTP_INV_SRCPT;
-               *flags |= SCTP_SRC_PORTS;
+                       einfo->invflags |= IPT_SCTP_SRC_PORTS;
+               *flags |= IPT_SCTP_SRC_PORTS;
                *nfcache |= NFC_IP_SRC_PT;
                break;
 
        case '2':
-               if (*flags & SCTP_DST_PORTS)
+               if (*flags & IPT_SCTP_DEST_PORTS)
                        exit_error(PARAMETER_PROBLEM,
                                   "Only one `--destination-port' allowed");
+               einfo->flags |= IPT_SCTP_DEST_PORTS;
                check_inverse(optarg, &invert, &optind, 0);
                parse_sctp_ports(argv[optind-1], einfo->dpts);
                if (invert)
-                       einfo->invflags |= IPT_SCTP_INV_DSTPT;
-               *flags |= SCTP_DST_PORTS;
+                       einfo->invflags |= IPT_SCTP_DEST_PORTS;
+               *flags |= IPT_SCTP_DEST_PORTS;
                *nfcache |= NFC_IP_DST_PT;
                break;
 
        case '3':
-               if (*flags & SCTP_CHUNKS)
+               if (*flags & IPT_SCTP_CHUNK_TYPES)
                        exit_error(PARAMETER_PROBLEM,
-                                  "Only one `--sctp-chunks' allowed");
+                                  "Only one `--chunk-types' allowed");
                check_inverse(optarg, &invert, &optind, 0);
 
                if (!argv[optind] 
                    || argv[optind][0] == '-' || argv[optind][0] == '!')
                        exit_error(PARAMETER_PROBLEM,
-                                  "--sctp-chunks requires two args");
+                                  "--chunk-types requires two args");
 
-               parse_sctp_chunks(einfo, argv[optind-1], argv[optind], invert);
+               einfo->flags |= IPT_SCTP_CHUNK_TYPES;
+               parse_sctp_chunks(einfo, argv[optind-1], argv[optind]);
+               if (invert)
+                       einfo->invflags |= IPT_SCTP_CHUNK_TYPES;
                optind++;
-               *flags |= SCTP_CHUNKS;
+               *flags |= IPT_SCTP_CHUNK_TYPES;
                break;
+
        default:
                return 0;
        }
-
        return 1;
 }
 
@@ -278,41 +316,53 @@ print_ports(const char *name, u_int16_t min, u_int16_t max,
 }
 
 static void
-print_chunk(u_int32_t chunks)
+print_chunk(u_int32_t chunknum, int numeric)
 {
-       unsigned int have_flag = 0;
-
-       while (chunks) {
-               unsigned int i;
-
-               for (i = 0; (chunks & sctp_chunk_names[i].flag) == 0; i++);
-
-               if (have_flag)
-                       printf(",");
-               printf("%s", sctp_chunk_names[i].name);
-               have_flag = 1;
-
-               chunks &= ~sctp_chunk_names[i].flag;
+       if (numeric) {
+               printf("0x%04X", chunknum);
+       }
+       else {
+               printf("%s", sctp_chunk_names[chunknum].name);
        }
-
-       if (!have_flag)
-               printf("NONE");
 }
 
 static void
-print_chunks(u_int32_t mask, u_int32_t cmp, int invert, int numeric)
+print_chunks(u_int32_t chunk_match_type, 
+            const u_int32_t *chunkmap, 
+            int numeric)
 {
-       if (mask || invert) {
-               printf("flags:%s", invert ? "!" : "");
-               if (numeric)
-                       printf("0x%04X/0x%04X ", mask, cmp);
-               else {
-                       print_chunk(mask);
-                       printf("/");
-                       print_chunk(cmp);
-                       printf(" ");
+       int i;
+       int flag;
+
+       switch (chunk_match_type) {
+               case SCTP_CHUNK_MATCH_ANY:      printf("any "); break;
+               case SCTP_CHUNK_MATCH_ALL:      printf("all "); break;
+               case SCTP_CHUNK_MATCH_ONLY:     printf("only "); break;
+               default:        printf("Never reach herer\n"); break;
+       }
+
+       if (SCTP_CHUNKMAP_IS_CLEAR(chunkmap)) {
+               printf("NONE ");
+               goto out;
+       }
+       
+       if (SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)) {
+               printf("ALL ");
+               goto out;
+       }
+       
+       flag = 0;
+       for (i = 0; i < 256; i++) {
+               if (SCTP_CHUNKMAP_IS_SET(chunkmap, i)) {
+                       flag && printf(",");
+                       flag = 1;
+                       print_chunk(i, numeric);
                }
        }
+
+       flag && printf(" ");
+out:
+       return;
 }
 
 /* Prints out the matchinfo. */
@@ -326,28 +376,38 @@ print(const struct ipt_ip *ip,
 
        printf("sctp ");
 
-       print_ports("spt", einfo->spts[0], einfo->spts[1],
-                   einfo->invflags & IPT_SCTP_INV_SRCPT,
-                   numeric);
-       print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
-                   einfo->invflags & IPT_SCTP_INV_DSTPT,
-                   numeric);
+       if (einfo->flags & IPT_SCTP_SRC_PORTS) {
+               print_ports("spt", einfo->spts[0], einfo->spts[1],
+                       einfo->invflags & IPT_SCTP_SRC_PORTS,
+                       numeric);
+       }
+
+       if (einfo->flags & IPT_SCTP_DEST_PORTS) {
+               print_ports("dpt", einfo->dpts[0], einfo->dpts[1],
+                       einfo->invflags & IPT_SCTP_DEST_PORTS,
+                       numeric);
+       }
 
-       print_chunks(einfo->chunks, einfo->chunk_mask,
-                    einfo->invflags & ~IPT_SCTP_INV_MASK,
-                    numeric);
+       if (einfo->flags & IPT_SCTP_CHUNK_TYPES) {
+               /* FIXME: print_chunks() is used in save() where the printing of '!'
+               s taken care of, so we need to do that here as well */
+               if (einfo->invflags & IPT_SCTP_CHUNK_TYPES) {
+                       printf("! ");
+               }
+               print_chunks(einfo->chunk_match_type, einfo->chunkmap, numeric);
+       }
 }
 
 /* Saves the union ipt_matchinfo in parsable form to stdout. */
 static void
-save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+save(const struct ipt_ip *ip, 
+     const struct ipt_entry_match *match)
 {
        const struct ipt_sctp_info *einfo =
                (const struct ipt_sctp_info *)match->data;
 
-       if (einfo->spts[0] != 0
-           || einfo->spts[1] != 0xFFFF) {
-               if (einfo->invflags & IPT_SCTP_INV_SRCPT)
+       if (einfo->flags & IPT_SCTP_SRC_PORTS) {
+               if (einfo->invflags & IPT_SCTP_SRC_PORTS)
                        printf("! ");
                if (einfo->spts[0] != einfo->spts[1])
                        printf("--sport %u:%u ", 
@@ -356,9 +416,8 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
                        printf("--sport %u ", einfo->spts[0]);
        }
 
-       if (einfo->dpts[0] != 0
-           || einfo->dpts[1] != 0xFFFF) {
-               if (einfo->invflags & IPT_SCTP_INV_DSTPT)
+       if (einfo->flags & IPT_SCTP_DEST_PORTS) {
+               if (einfo->invflags & IPT_SCTP_DEST_PORTS)
                        printf("! ");
                if (einfo->dpts[0] != einfo->dpts[1])
                        printf("--dport %u:%u ",
@@ -367,17 +426,12 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
                        printf("--dport %u ", einfo->dpts[0]);
        }
 
-       if (einfo->chunks
-           || (einfo->invflags & IPT_SCTP_INV_CHUNKS)) {
-               if (einfo->invflags & IPT_SCTP_INV_CHUNKS)
+       if (einfo->flags & IPT_SCTP_CHUNK_TYPES) {
+               if (einfo->invflags & IPT_SCTP_CHUNK_TYPES)
                        printf("! ");
-               printf("--sctp-chunks ");
-               if (einfo->chunks != ALL_CHUNKS) {
-                       print_chunk(einfo->chunks);
-               }
-               printf(" ");
-               print_chunk(einfo->chunk_mask);
-               printf(" ");
+               printf("--chunk-types ");
+
+               print_chunks(einfo->chunk_match_type, einfo->chunkmap, 0);
        }
 }
 
@@ -400,3 +454,4 @@ void _init(void)
 {
        register_match(&sctp);
 }
+
index 54c58fab58391c32dffac6e20655d015a2959827..575c6720ed9cc702c3a7e9936a81127cb12e4387 100644 (file)
@@ -1,25 +1,96 @@
-/* iptables module for matching the SCTP header
- *
- * (C) 2003 Harald Welte <laforge@gnumonks.org>
- *
- * This software is distributed under GNU GPL v2, 1991
- *
- * $Id$
- */
-#ifndef _IPT_SCTP_H
-#define _IPT_SCTP_H
+#ifndef _IPT_SCTP_H_
+#define _IPT_SCTP_H_
+
+#define IPT_SCTP_SRC_PORTS             0x01
+#define IPT_SCTP_DEST_PORTS            0x02
+#define IPT_SCTP_CHUNK_TYPES           0x04
+
+#define IPT_SCTP_VALID_FLAGS           0x07
+
+#define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0]))
 
 struct ipt_sctp_info {
-       u_int16_t spts[2];                      /* Souce port range */
-       u_int16_t dpts[2];                      /* Destination port range */
-       u_int32_t chunks;                       /* chunks to be matched */
-       u_int32_t chunk_mask;                   /* chunk mask to be matched */
-       u_int8_t invflags;                      /* Inverse flags */
+       u_int16_t dpts[2];  /* Min, Max */
+       u_int16_t spts[2];  /* Min, Max */
+
+       u_int32_t chunkmap[256 / sizeof (u_int32_t)];  /* Bit mask of chunks to be matched according to RFC 2960 */
+
+#define SCTP_CHUNK_MATCH_ANY   0x01  /* Match if any of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ALL   0x02  /* Match if all of the chunk types are present */
+#define SCTP_CHUNK_MATCH_ONLY  0x04  /* Match if these are the only chunk types present */
+
+       u_int32_t chunk_match_type;
+
+       u_int32_t flags;
+       u_int32_t invflags;
 };
 
-#define IPT_SCTP_INV_SRCPT     0x01    /* Invert the sense of source ports */
-#define IPT_SCTP_INV_DSTPT     0x02    /* Invert the sense of dest ports */
-#define IPT_SCTP_INV_CHUNKS    0x03    /* Invert the sense of chunks */
-#define IPT_SCTP_INV_MASK      0x03    /* All possible flags */
+#define bytes(type) (sizeof(type) * 8)
+
+#define SCTP_CHUNKMAP_SET(chunkmap, type)              \
+       do {                                            \
+               chunkmap[type / bytes(u_int32_t)] |=    \
+                       1 << (type % bytes(u_int32_t)); \
+       } while (0)
+
+#define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
+       do {                                                    \
+               chunkmap[type / bytes(u_int32_t)] &=            \
+                       ~(1 << (type % bytes(u_int32_t)));      \
+       } while (0)
+
+#define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
+({                                                             \
+       (chunkmap[type / bytes (u_int32_t)] &                   \
+               (1 << (type % bytes (u_int32_t)))) ? 1: 0;      \
+})
+
+#define SCTP_CHUNKMAP_RESET(chunkmap)                          \
+       do {                                                    \
+               int i;                                          \
+               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
+                       chunkmap[i] = 0;                        \
+       } while (0)
+
+#define SCTP_CHUNKMAP_SET_ALL(chunkmap)                        \
+       do {                                                    \
+               int i;                                          \
+               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
+                       chunkmap[i] = ~0;                       \
+       } while (0)
+
+#define SCTP_CHUNKMAP_COPY(destmap, srcmap)                    \
+       do {                                                    \
+               int i;                                          \
+               for (i = 0; i < ELEMCOUNT(chunkmap); i++)       \
+                       destmap[i] = srcmap[i];                 \
+       } while (0)
+
+#define SCTP_CHUNKMAP_IS_CLEAR(chunkmap)               \
+({                                                     \
+       int i;                                          \
+       int flag = 1;                                   \
+       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
+               if (chunkmap[i]) {                      \
+                       flag = 0;                       \
+                       break;                          \
+               }                                       \
+       }                                               \
+        flag;                                          \
+})
+
+#define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap)             \
+({                                                     \
+       int i;                                          \
+       int flag = 1;                                   \
+       for (i = 0; i < ELEMCOUNT(chunkmap); i++) {     \
+               if (chunkmap[i] != ~0) {                \
+                       flag = 0;                       \
+                               break;                  \
+               }                                       \
+       }                                               \
+        flag;                                          \
+})
+
+#endif /* _IPT_SCTP_H_ */
 
-#endif /* _IPT_SCTP_H */
index 41173eaddf3438a74d671c94555d6828a74da3a2..cdedfbf39ff130f864a016a80564685c9639ac0b 100644 (file)
@@ -75,6 +75,7 @@ static const struct pprot chain_protos[] = {
        { "icmp", IPPROTO_ICMP },
        { "esp", IPPROTO_ESP },
        { "ah", IPPROTO_AH },
+       { "sctp", IPPROTO_SCTP },
 };
 
 static void print_proto(u_int16_t proto, int invert)
index 2c6282a59c0fa3505bdaac617b9b5bb6e779139d..ae6538c049437c3880a089e360286246fb37df3b 100644 (file)
@@ -235,6 +235,7 @@ static const struct pprot chain_protos[] = {
        { "icmp", IPPROTO_ICMP },
        { "esp", IPPROTO_ESP },
        { "ah", IPPROTO_AH },
+       { "sctp", IPPROTO_SCTP },
        { "all", 0 },
 };