Home | History | Annotate | Download | only in tc
      1 /*
      2  * p_ip.c		packet editor: IPV4 header
      3  *
      4  *		This program is free software; you can distribute it and/or
      5  *		modify it under the terms of the GNU General Public License
      6  *		as published by the Free Software Foundation; either version
      7  *		2 of the License, or (at your option) any later version.
      8  *
      9  * Authors:  J Hadi Salim (hadi (at) cyberus.ca)
     10  *
     11  */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <unistd.h>
     16 #include <syslog.h>
     17 #include <fcntl.h>
     18 #include <sys/socket.h>
     19 #include <netinet/in.h>
     20 #include <arpa/inet.h>
     21 #include <string.h>
     22 #include "utils.h"
     23 #include "tc_util.h"
     24 #include "m_pedit.h"
     25 
     26 static int
     27 parse_ip(int *argc_p, char ***argv_p,
     28 	 struct m_pedit_sel *sel, struct m_pedit_key *tkey)
     29 {
     30 	int res = -1;
     31 	int argc = *argc_p;
     32 	char **argv = *argv_p;
     33 
     34 	if (argc < 2)
     35 		return -1;
     36 
     37 	tkey->htype = sel->extended ?
     38 		TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 :
     39 		TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK;
     40 
     41 	if (strcmp(*argv, "src") == 0) {
     42 		NEXT_ARG();
     43 		tkey->off = 12;
     44 		res = parse_cmd(&argc, &argv, 4, TIPV4, RU32, sel, tkey);
     45 		goto done;
     46 	}
     47 	if (strcmp(*argv, "dst") == 0) {
     48 		NEXT_ARG();
     49 		tkey->off = 16;
     50 		res = parse_cmd(&argc, &argv, 4, TIPV4, RU32, sel, tkey);
     51 		goto done;
     52 	}
     53 	/* jamal - look at these and make them either old or new
     54 	** scheme given diffserv
     55 	** dont forget the CE bit
     56 	*/
     57 	if (strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) {
     58 		NEXT_ARG();
     59 		tkey->off = 1;
     60 		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
     61 		goto done;
     62 	}
     63 	if (strcmp(*argv, "ihl") == 0) {
     64 		NEXT_ARG();
     65 		tkey->off = 0;
     66 		res = parse_cmd(&argc, &argv, 1, TU32, 0x0f, sel, tkey);
     67 		goto done;
     68 	}
     69 	if (strcmp(*argv, "ttl") == 0) {
     70 		NEXT_ARG();
     71 		tkey->off = 8;
     72 		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
     73 		goto done;
     74 	}
     75 	if (strcmp(*argv, "protocol") == 0) {
     76 		NEXT_ARG();
     77 		tkey->off = 9;
     78 		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
     79 		goto done;
     80 	}
     81 	/* jamal - fix this */
     82 	if (matches(*argv, "precedence") == 0) {
     83 		NEXT_ARG();
     84 		tkey->off = 1;
     85 		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
     86 		goto done;
     87 	}
     88 	/* jamal - validate this at some point */
     89 	if (strcmp(*argv, "nofrag") == 0) {
     90 		NEXT_ARG();
     91 		tkey->off = 6;
     92 		res = parse_cmd(&argc, &argv, 1, TU32, 0x3F, sel, tkey);
     93 		goto done;
     94 	}
     95 	/* jamal - validate this at some point */
     96 	if (strcmp(*argv, "firstfrag") == 0) {
     97 		NEXT_ARG();
     98 		tkey->off = 6;
     99 		res = parse_cmd(&argc, &argv, 1, TU32, 0x1F, sel, tkey);
    100 		goto done;
    101 	}
    102 	if (strcmp(*argv, "ce") == 0) {
    103 		NEXT_ARG();
    104 		tkey->off = 6;
    105 		res = parse_cmd(&argc, &argv, 1, TU32, 0x80, sel, tkey);
    106 		goto done;
    107 	}
    108 	if (strcmp(*argv, "df") == 0) {
    109 		NEXT_ARG();
    110 		tkey->off = 6;
    111 		res = parse_cmd(&argc, &argv, 1, TU32, 0x40, sel, tkey);
    112 		goto done;
    113 	}
    114 	if (strcmp(*argv, "mf") == 0) {
    115 		NEXT_ARG();
    116 		tkey->off = 6;
    117 		res = parse_cmd(&argc, &argv, 1, TU32, 0x20, sel, tkey);
    118 		goto done;
    119 	}
    120 
    121 	if (sel->extended)
    122 		return -1; /* fields located outside IP header should be
    123 			    * addressed using the relevant header type in
    124 			    * extended pedit kABI
    125 			    */
    126 
    127 	if (strcmp(*argv, "dport") == 0) {
    128 		NEXT_ARG();
    129 		tkey->off = 22;
    130 		res = parse_cmd(&argc, &argv, 2, TU32, RU16, sel, tkey);
    131 		goto done;
    132 	}
    133 	if (strcmp(*argv, "sport") == 0) {
    134 		NEXT_ARG();
    135 		tkey->off = 20;
    136 		res = parse_cmd(&argc, &argv, 2, TU32, RU16, sel, tkey);
    137 		goto done;
    138 	}
    139 	if (strcmp(*argv, "icmp_type") == 0) {
    140 		NEXT_ARG();
    141 		tkey->off = 20;
    142 		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
    143 		goto done;
    144 	}
    145 	if (strcmp(*argv, "icmp_code") == 0) {
    146 		NEXT_ARG();
    147 		tkey->off = 20;
    148 		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey);
    149 		goto done;
    150 	}
    151 	return -1;
    152 
    153 done:
    154 	*argc_p = argc;
    155 	*argv_p = argv;
    156 	return res;
    157 }
    158 
    159 struct m_pedit_util p_pedit_ip = {
    160 	NULL,
    161 	"ip",
    162 	parse_ip,
    163 };
    164