]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Add support for hex strings (Michael Rash)
authorMichael Rash <mbr@cipherdyne.com>
Wed, 26 Feb 2003 17:34:13 +0000 (17:34 +0000)
committerHarald Welte <laforge@gnumonks.org>
Wed, 26 Feb 2003 17:34:13 +0000 (17:34 +0000)
extensions/libipt_string.c

index 20613fdcb2ea7bd3b218bd9b81f5ce8c5253668d..dbed67db3a0d895f92da710020b12f65d33f262b 100644 (file)
@@ -13,6 +13,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <getopt.h>
+#include <ctype.h>
 
 #include <iptables.h>
 #include <linux/netfilter_ipv4/ipt_string.h>
@@ -44,8 +45,70 @@ init(struct ipt_entry_match *m, unsigned int *nfcache)
 static void
 parse_string(const unsigned char *s, struct ipt_string_info *info)
 {      
-        if (strlen(s) <= BM_MAX_NLEN) strcpy(info->string, s);
-       else exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s);
+       int i=0, slen, sindex=0, schar;
+       short hex_f = 0, literal_f = 0;
+       char hextmp[3];
+
+       slen = strlen(s);
+
+       if (slen == 0) {
+               exit_error(PARAMETER_PROBLEM,
+                       "STRING must contain at least one char");
+       }
+
+       while (i < slen) {
+               if (s[i] == '\\' && !hex_f) {
+                       literal_f = 1;
+               } else if (s[i] == '\\') {
+                       exit_error(PARAMETER_PROBLEM,
+                               "Cannot include literals in hex data");
+               } else if (s[i] == '|') {
+                       if (hex_f)
+                               hex_f = 0;
+                       else
+                               hex_f = 1;
+                       if (i+1 >= slen)
+                               break;
+                       else
+                               i++;  /* advance to the next character */
+               }
+
+               if (literal_f) {
+                       if (i+1 >= slen) {
+                               exit_error(PARAMETER_PROBLEM,
+                                       "Bad literal placement at end of string");
+                       }
+                       info->string[sindex] = s[i+1];
+                       i += 2;  /* skip over literal char */
+                       literal_f = 0;
+               } else if (hex_f) {
+                       if (i+1 >= slen) {
+                               exit_error(PARAMETER_PROBLEM,
+                                       "Odd number of hex digits");
+                       }
+                       if (i+2 >= slen) {
+                               /* must end with a "|" */
+                               exit_error(PARAMETER_PROBLEM, "Invalid hex block");
+                       }
+                       hextmp[0] = s[i];
+                       hextmp[1] = s[i+1];
+                       hextmp[2] = '\0';
+                       if (! sscanf(hextmp, "%x", &schar))
+                               exit_error(PARAMETER_PROBLEM,
+                                       "Invalid hex char `%c'", s[i]);
+                       info->string[sindex] = (char) schar;
+                       if (s[i+2] == ' ')
+                               i += 3;  /* spaces included in the hex block */
+                       else
+                               i += 2;
+               } else {  /* the char is not part of hex data, so just copy */
+                       info->string[sindex] = s[i];
+                       i++;
+               }
+               if (sindex > BM_MAX_NLEN)
+                       exit_error(PARAMETER_PROBLEM, "STRING too long `%s'", s);
+               sindex++;
+       }
 }
 
 /* Function which parses command options; returns true if it