summaryrefslogtreecommitdiffstats
path: root/tc/p_ip.c
blob: 7f66ef3143fb947c3a9a0fcec0c496bec2c0f5d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * p_ip.c		packet editor: IPV4 header
 *
 * Authors:  J Hadi Salim (hadi@cyberus.ca)
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "utils.h"
#include "tc_util.h"
#include "m_pedit.h"

static int
parse_ip(int *argc_p, char ***argv_p,
	 struct m_pedit_sel *sel, struct m_pedit_key *tkey)
{
	int res = -1;
	int argc = *argc_p;
	char **argv = *argv_p;

	if (argc < 2)
		return -1;

	tkey->htype = sel->extended ?
		TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 :
		TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK;

	if (strcmp(*argv, "src") == 0) {
		NEXT_ARG();
		tkey->off = 12;
		res = parse_cmd(&argc, &argv, 4, TIPV4, RU32, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "dst") == 0) {
		NEXT_ARG();
		tkey->off = 16;
		res = parse_cmd(&argc, &argv, 4, TIPV4, RU32, sel, tkey, 0);
		goto done;
	}
	/* jamal - look at these and make them either old or new
	** scheme given diffserv
	** don't forget the CE bit
	*/
	if (strcmp(*argv, "tos") == 0 || matches(*argv, "dsfield") == 0) {
		NEXT_ARG();
		tkey->off = 1;
		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "ihl") == 0) {
		NEXT_ARG();
		tkey->off = 0;
		res = parse_cmd(&argc, &argv, 1, TU32, 0x0f, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "ttl") == 0) {
		NEXT_ARG();
		tkey->off = 8;
		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, PEDIT_ALLOW_DEC);
		goto done;
	}
	if (strcmp(*argv, "protocol") == 0) {
		NEXT_ARG();
		tkey->off = 9;
		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0);
		goto done;
	}
	/* jamal - fix this */
	if (matches(*argv, "precedence") == 0) {
		NEXT_ARG();
		tkey->off = 1;
		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0);
		goto done;
	}
	/* jamal - validate this at some point */
	if (strcmp(*argv, "nofrag") == 0) {
		NEXT_ARG();
		tkey->off = 6;
		res = parse_cmd(&argc, &argv, 1, TU32, 0x3F, sel, tkey, 0);
		goto done;
	}
	/* jamal - validate this at some point */
	if (strcmp(*argv, "firstfrag") == 0) {
		NEXT_ARG();
		tkey->off = 6;
		res = parse_cmd(&argc, &argv, 1, TU32, 0x1F, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "ce") == 0) {
		NEXT_ARG();
		tkey->off = 6;
		res = parse_cmd(&argc, &argv, 1, TU32, 0x80, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "df") == 0) {
		NEXT_ARG();
		tkey->off = 6;
		res = parse_cmd(&argc, &argv, 1, TU32, 0x40, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "mf") == 0) {
		NEXT_ARG();
		tkey->off = 6;
		res = parse_cmd(&argc, &argv, 1, TU32, 0x20, sel, tkey, 0);
		goto done;
	}

	if (sel->extended)
		return -1; /* fields located outside IP header should be
			    * addressed using the relevant header type in
			    * extended pedit kABI
			    */

	if (strcmp(*argv, "dport") == 0) {
		NEXT_ARG();
		tkey->off = 22;
		res = parse_cmd(&argc, &argv, 2, TU32, RU16, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "sport") == 0) {
		NEXT_ARG();
		tkey->off = 20;
		res = parse_cmd(&argc, &argv, 2, TU32, RU16, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "icmp_type") == 0) {
		NEXT_ARG();
		tkey->off = 20;
		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0);
		goto done;
	}
	if (strcmp(*argv, "icmp_code") == 0) {
		NEXT_ARG();
		tkey->off = 20;
		res = parse_cmd(&argc, &argv, 1, TU32, RU8, sel, tkey, 0);
		goto done;
	}
	return -1;

done:
	*argc_p = argc;
	*argv_p = argv;
	return res;
}

struct m_pedit_util p_pedit_ip = {
	.id = "ip",
	.parse_peopt = parse_ip,
};