summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorKiran Kumar <immidi_kiran@yahoo.com>2004-03-02 18:38:27 +0000
committerHarald Welte <laforge@gnumonks.org>2004-03-02 18:38:27 +0000
commit54924023ee598e626423ef9c222eff0e8d28dfac (patch)
tree5c8de06e07687a320e917eee637309d28fe05d6b /extensions
parentdd6dd3ec5390807bf52e1afe7f4ec9489fc4dcb4 (diff)
update for matching chunk flags (Kiran Kumar)
Diffstat (limited to 'extensions')
-rw-r--r--extensions/libipt_sctp.c161
1 files changed, 133 insertions, 28 deletions
diff --git a/extensions/libipt_sctp.c b/extensions/libipt_sctp.c
index d47719f8..f12403c5 100644
--- a/extensions/libipt_sctp.c
+++ b/extensions/libipt_sctp.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <getopt.h>
#include <netdb.h>
+#include <ctype.h>
#include <iptables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
@@ -24,21 +25,22 @@
#define DEBUGP(format, fist...)
#endif
-/*static void
-print_chunks(u_int32_t chunk_match_type, const u_int32_t *chunkmap, int numeric);*/
+static void
+print_chunk(u_int32_t chunknum, int numeric);
/* Initialize the match. */
static void
init(struct ipt_entry_match *m,
unsigned int *nfcache)
{
+ int i;
struct ipt_sctp_info *einfo = (struct ipt_sctp_info *)m->data;
- einfo->flags = einfo->invflags = 0;
+ memset(einfo, 0, sizeof(struct ipt_sctp_info));
- /*einfo->spts[0] = einfo->dpts[0] = 0;
- einfo->spts[1] = einfo->dpts[1] = 0xFFFF;
- SCTP_CHUNKMAP_RESET(einfo->chunkmap);*/
+ for (i = 0; i < IPT_NUM_SCTP_FLAGS; i++) {
+ einfo->flag_info[i].chunktype = -1;
+ }
}
static void help(void)
@@ -118,37 +120,76 @@ parse_sctp_ports(const char *portstring,
struct sctp_chunk_names {
const char *name;
unsigned int chunk_type;
+ const char *valid_flags;
};
/*'ALL' and 'NONE' will be treated specially. */
static struct sctp_chunk_names sctp_chunk_names[]
-= { { .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 },
+= { { .name = "DATA", .chunk_type = 0, .valid_flags = "-----UBE"},
+ { .name = "INIT", .chunk_type = 1, .valid_flags = "--------"},
+ { .name = "INIT_ACK", .chunk_type = 2, .valid_flags = "--------"},
+ { .name = "SACK", .chunk_type = 3, .valid_flags = "--------"},
+ { .name = "HEARTBEAT", .chunk_type = 4, .valid_flags = "--------"},
+ { .name = "HEARTBEAT_ACK", .chunk_type = 5, .valid_flags = "--------"},
+ { .name = "ABORT", .chunk_type = 6, .valid_flags = "-------T"},
+ { .name = "SHUTDOWN", .chunk_type = 7, .valid_flags = "--------"},
+ { .name = "SHUTDOWN_ACK", .chunk_type = 8, .valid_flags = "--------"},
+ { .name = "ERROR", .chunk_type = 9, .valid_flags = "--------"},
+ { .name = "COOKIE_ECHO", .chunk_type = 10, .valid_flags = "--------"},
+ { .name = "COOKIE_ACK", .chunk_type = 11, .valid_flags = "--------"},
+ { .name = "ECN_ECNE", .chunk_type = 12, .valid_flags = "--------"},
+ { .name = "ECN_CWR", .chunk_type = 13, .valid_flags = "--------"},
+ { .name = "SHUTDOWN_COMPLETE", .chunk_type = 14, .valid_flags = "-------T"},
+ { .name = "ASCONF", .chunk_type = 31, .valid_flags = "--------"},
+ { .name = "ASCONF_ACK", .chunk_type = 30, .valid_flags = "--------"},
};
static void
+save_chunk_flag_info(struct ipt_sctp_flag_info *flag_info,
+ int *flag_count,
+ int chunktype,
+ int bit,
+ int set)
+{
+ int i;
+
+ for (i = 0; i < *flag_count; i++) {
+ if (flag_info[i].chunktype == chunktype) {
+ DEBUGP("Previous match found\n");
+ flag_info[i].chunktype = chunktype;
+ flag_info[i].flag_mask |= (1 << bit);
+ if (set) {
+ flag_info[i].flag |= (1 << bit);
+ }
+
+ return;
+ }
+ }
+
+ if (*flag_count == IPT_NUM_SCTP_FLAGS) {
+ exit_error (PARAMETER_PROBLEM,
+ "Number of chunk types with flags exceeds currently allowed limit."
+ "Increasing this limit involves changing IPT_NUM_SCTP_FLAGS and"
+ "recompiling both the kernel space and user space modules\n");
+ }
+
+ flag_info[*flag_count].chunktype = chunktype;
+ flag_info[*flag_count].flag_mask |= (1 << bit);
+ if (set) {
+ flag_info[*flag_count].flag |= (1 << bit);
+ }
+ (*flag_count)++;
+}
+
+static void
parse_sctp_chunk(struct ipt_sctp_info *einfo,
const char *chunks)
{
char *ptr;
char *buffer;
- unsigned int i;
+ unsigned int i, j;
int found = 0;
+ char *chunk_flags;
buffer = strdup(chunks);
DEBUGP("Buffer: %s\n", buffer);
@@ -168,6 +209,11 @@ parse_sctp_chunk(struct ipt_sctp_info *einfo,
for (ptr = strtok(buffer, ","); ptr; ptr = strtok(NULL, ",")) {
found = 0;
DEBUGP("Next Chunk type %s\n", ptr);
+
+ if ((chunk_flags = strchr(ptr, ':')) != NULL) {
+ *chunk_flags++ = 0;
+ }
+
for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
if (strcasecmp(sctp_chunk_names[i].name, ptr) == 0) {
DEBUGP("Chunk num %d\n", sctp_chunk_names[i].chunk_type);
@@ -180,6 +226,27 @@ parse_sctp_chunk(struct ipt_sctp_info *einfo,
if (!found)
exit_error(PARAMETER_PROBLEM,
"Unknown sctp chunk `%s'", ptr);
+
+ if (chunk_flags) {
+ DEBUGP("Chunk flags %s\n", chunk_flags);
+ for (j = 0; j < strlen(chunk_flags); j++) {
+ char *p;
+ int bit;
+
+ if ((p = strchr(sctp_chunk_names[i].valid_flags,
+ toupper(chunk_flags[j]))) != NULL) {
+ bit = p - sctp_chunk_names[i].valid_flags;
+ bit = 7 - bit;
+
+ save_chunk_flag_info(einfo->flag_info,
+ &(einfo->flag_count), i, bit,
+ isupper(chunk_flags[j]));
+ } else {
+ exit_error(PARAMETER_PROBLEM,
+ "Invalid flags for chunk type %d\n", i);
+ }
+ }
+ }
}
out:
free(buffer);
@@ -316,22 +383,52 @@ print_ports(const char *name, u_int16_t min, u_int16_t max,
}
static void
+print_chunk_flags(u_int32_t chunknum, u_int8_t chunk_flags, u_int8_t chunk_flags_mask)
+{
+ int i;
+
+ DEBUGP("type: %d\tflags: %x\tflag mask: %x\n", chunknum, chunk_flags,
+ chunk_flags_mask);
+
+ if (chunk_flags_mask) {
+ printf(":");
+ }
+
+ for (i = 7; i >= 0; i--) {
+ if (chunk_flags_mask & (1 << i)) {
+ if (chunk_flags & (1 << i)) {
+ printf("%c", sctp_chunk_names[chunknum].valid_flags[7-i]);
+ } else {
+ printf("%c", tolower(sctp_chunk_names[chunknum].valid_flags[7-i]));
+ }
+ }
+ }
+}
+
+static void
print_chunk(u_int32_t chunknum, int numeric)
{
if (numeric) {
printf("0x%04X", chunknum);
}
else {
- printf("%s", sctp_chunk_names[chunknum].name);
+ int i;
+
+ for (i = 0; i < ELEMCOUNT(sctp_chunk_names); i++) {
+ if (sctp_chunk_names[i].chunk_type == chunknum)
+ printf("%s", sctp_chunk_names[chunknum].name);
+ }
}
}
static void
print_chunks(u_int32_t chunk_match_type,
const u_int32_t *chunkmap,
+ const struct ipt_sctp_flag_info *flag_info,
+ int flag_count,
int numeric)
{
- int i;
+ int i, j;
int flag;
switch (chunk_match_type) {
@@ -357,6 +454,12 @@ print_chunks(u_int32_t chunk_match_type,
flag && printf(",");
flag = 1;
print_chunk(i, numeric);
+ for (j = 0; j < flag_count; j++) {
+ if (flag_info[j].chunktype == i) {
+ print_chunk_flags(i, flag_info[j].flag,
+ flag_info[j].flag_mask);
+ }
+ }
}
}
@@ -394,7 +497,8 @@ print(const struct ipt_ip *ip,
if (einfo->invflags & IPT_SCTP_CHUNK_TYPES) {
printf("! ");
}
- print_chunks(einfo->chunk_match_type, einfo->chunkmap, numeric);
+ print_chunks(einfo->chunk_match_type, einfo->chunkmap,
+ einfo->flag_info, einfo->flag_count, numeric);
}
}
@@ -431,7 +535,8 @@ save(const struct ipt_ip *ip,
printf("! ");
printf("--chunk-types ");
- print_chunks(einfo->chunk_match_type, einfo->chunkmap, 0);
+ print_chunks(einfo->chunk_match_type, einfo->chunkmap,
+ einfo->flag_info, einfo->flag_count, 0);
}
}