1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * m_skbedit.c SKB Editing module
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * Copyright (c) 2008, Intel Corporation.
5*de1e4e89SAndroid Build Coastguard Worker *
6*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify it
7*de1e4e89SAndroid Build Coastguard Worker * under the terms and conditions of the GNU General Public License,
8*de1e4e89SAndroid Build Coastguard Worker * version 2, as published by the Free Software Foundation.
9*de1e4e89SAndroid Build Coastguard Worker *
10*de1e4e89SAndroid Build Coastguard Worker * This program is distributed in the hope it will be useful, but WITHOUT
11*de1e4e89SAndroid Build Coastguard Worker * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12*de1e4e89SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13*de1e4e89SAndroid Build Coastguard Worker * more details.
14*de1e4e89SAndroid Build Coastguard Worker *
15*de1e4e89SAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
16*de1e4e89SAndroid Build Coastguard Worker * along with this program; if not, see <http://www.gnu.org/licenses>.
17*de1e4e89SAndroid Build Coastguard Worker *
18*de1e4e89SAndroid Build Coastguard Worker * Authors: Alexander Duyck <[email protected]>
19*de1e4e89SAndroid Build Coastguard Worker *
20*de1e4e89SAndroid Build Coastguard Worker */
21*de1e4e89SAndroid Build Coastguard Worker
22*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
25*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
26*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
27*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
28*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_skbedit.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_packet.h>
30*de1e4e89SAndroid Build Coastguard Worker
explain(void)31*de1e4e89SAndroid Build Coastguard Worker static void explain(void)
32*de1e4e89SAndroid Build Coastguard Worker {
33*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT]>\n"
34*de1e4e89SAndroid Build Coastguard Worker "QM = queue_mapping QUEUE_MAPPING\n"
35*de1e4e89SAndroid Build Coastguard Worker "PM = priority PRIORITY\n"
36*de1e4e89SAndroid Build Coastguard Worker "MM = mark MARK\n"
37*de1e4e89SAndroid Build Coastguard Worker "PT = ptype PACKETYPE\n"
38*de1e4e89SAndroid Build Coastguard Worker "PACKETYPE = is one of:\n"
39*de1e4e89SAndroid Build Coastguard Worker " host, otherhost, broadcast, multicast\n"
40*de1e4e89SAndroid Build Coastguard Worker "QUEUE_MAPPING = device transmit queue to use\n"
41*de1e4e89SAndroid Build Coastguard Worker "PRIORITY = classID to assign to priority field\n"
42*de1e4e89SAndroid Build Coastguard Worker "MARK = firewall mark to set\n");
43*de1e4e89SAndroid Build Coastguard Worker }
44*de1e4e89SAndroid Build Coastguard Worker
45*de1e4e89SAndroid Build Coastguard Worker static void
usage(void)46*de1e4e89SAndroid Build Coastguard Worker usage(void)
47*de1e4e89SAndroid Build Coastguard Worker {
48*de1e4e89SAndroid Build Coastguard Worker explain();
49*de1e4e89SAndroid Build Coastguard Worker exit(-1);
50*de1e4e89SAndroid Build Coastguard Worker }
51*de1e4e89SAndroid Build Coastguard Worker
52*de1e4e89SAndroid Build Coastguard Worker static int
parse_skbedit(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)53*de1e4e89SAndroid Build Coastguard Worker parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
54*de1e4e89SAndroid Build Coastguard Worker struct nlmsghdr *n)
55*de1e4e89SAndroid Build Coastguard Worker {
56*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
57*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
58*de1e4e89SAndroid Build Coastguard Worker int ok = 0;
59*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tail;
60*de1e4e89SAndroid Build Coastguard Worker unsigned int tmp;
61*de1e4e89SAndroid Build Coastguard Worker __u16 queue_mapping, ptype;
62*de1e4e89SAndroid Build Coastguard Worker __u32 flags = 0, priority, mark;
63*de1e4e89SAndroid Build Coastguard Worker struct tc_skbedit sel = { 0 };
64*de1e4e89SAndroid Build Coastguard Worker
65*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "skbedit") != 0)
66*de1e4e89SAndroid Build Coastguard Worker return -1;
67*de1e4e89SAndroid Build Coastguard Worker
68*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
69*de1e4e89SAndroid Build Coastguard Worker
70*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
71*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "queue_mapping") == 0) {
72*de1e4e89SAndroid Build Coastguard Worker flags |= SKBEDIT_F_QUEUE_MAPPING;
73*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
74*de1e4e89SAndroid Build Coastguard Worker if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
75*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal queue_mapping\n");
76*de1e4e89SAndroid Build Coastguard Worker return -1;
77*de1e4e89SAndroid Build Coastguard Worker }
78*de1e4e89SAndroid Build Coastguard Worker queue_mapping = tmp;
79*de1e4e89SAndroid Build Coastguard Worker ok++;
80*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "priority") == 0) {
81*de1e4e89SAndroid Build Coastguard Worker flags |= SKBEDIT_F_PRIORITY;
82*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
83*de1e4e89SAndroid Build Coastguard Worker if (get_tc_classid(&priority, *argv)) {
84*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal priority\n");
85*de1e4e89SAndroid Build Coastguard Worker return -1;
86*de1e4e89SAndroid Build Coastguard Worker }
87*de1e4e89SAndroid Build Coastguard Worker ok++;
88*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "mark") == 0) {
89*de1e4e89SAndroid Build Coastguard Worker flags |= SKBEDIT_F_MARK;
90*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
91*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&mark, *argv, 0)) {
92*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal mark\n");
93*de1e4e89SAndroid Build Coastguard Worker return -1;
94*de1e4e89SAndroid Build Coastguard Worker }
95*de1e4e89SAndroid Build Coastguard Worker ok++;
96*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "ptype") == 0) {
97*de1e4e89SAndroid Build Coastguard Worker
98*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
99*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "host") == 0) {
100*de1e4e89SAndroid Build Coastguard Worker ptype = PACKET_HOST;
101*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "broadcast") == 0) {
102*de1e4e89SAndroid Build Coastguard Worker ptype = PACKET_BROADCAST;
103*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "multicast") == 0) {
104*de1e4e89SAndroid Build Coastguard Worker ptype = PACKET_MULTICAST;
105*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "otherhost") == 0) {
106*de1e4e89SAndroid Build Coastguard Worker ptype = PACKET_OTHERHOST;
107*de1e4e89SAndroid Build Coastguard Worker } else {
108*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal ptype (%s)\n",
109*de1e4e89SAndroid Build Coastguard Worker *argv);
110*de1e4e89SAndroid Build Coastguard Worker return -1;
111*de1e4e89SAndroid Build Coastguard Worker }
112*de1e4e89SAndroid Build Coastguard Worker flags |= SKBEDIT_F_PTYPE;
113*de1e4e89SAndroid Build Coastguard Worker ok++;
114*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "help") == 0) {
115*de1e4e89SAndroid Build Coastguard Worker usage();
116*de1e4e89SAndroid Build Coastguard Worker } else {
117*de1e4e89SAndroid Build Coastguard Worker break;
118*de1e4e89SAndroid Build Coastguard Worker }
119*de1e4e89SAndroid Build Coastguard Worker argc--;
120*de1e4e89SAndroid Build Coastguard Worker argv++;
121*de1e4e89SAndroid Build Coastguard Worker }
122*de1e4e89SAndroid Build Coastguard Worker
123*de1e4e89SAndroid Build Coastguard Worker parse_action_control_dflt(&argc, &argv, &sel.action,
124*de1e4e89SAndroid Build Coastguard Worker false, TC_ACT_PIPE);
125*de1e4e89SAndroid Build Coastguard Worker
126*de1e4e89SAndroid Build Coastguard Worker if (argc) {
127*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "index") == 0) {
128*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
129*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&sel.index, *argv, 10)) {
130*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Pedit: Illegal \"index\"\n");
131*de1e4e89SAndroid Build Coastguard Worker return -1;
132*de1e4e89SAndroid Build Coastguard Worker }
133*de1e4e89SAndroid Build Coastguard Worker argc--;
134*de1e4e89SAndroid Build Coastguard Worker argv++;
135*de1e4e89SAndroid Build Coastguard Worker ok++;
136*de1e4e89SAndroid Build Coastguard Worker }
137*de1e4e89SAndroid Build Coastguard Worker }
138*de1e4e89SAndroid Build Coastguard Worker
139*de1e4e89SAndroid Build Coastguard Worker if (!ok) {
140*de1e4e89SAndroid Build Coastguard Worker explain();
141*de1e4e89SAndroid Build Coastguard Worker return -1;
142*de1e4e89SAndroid Build Coastguard Worker }
143*de1e4e89SAndroid Build Coastguard Worker
144*de1e4e89SAndroid Build Coastguard Worker
145*de1e4e89SAndroid Build Coastguard Worker tail = NLMSG_TAIL(n);
146*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, tca_id, NULL, 0);
147*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
148*de1e4e89SAndroid Build Coastguard Worker if (flags & SKBEDIT_F_QUEUE_MAPPING)
149*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
150*de1e4e89SAndroid Build Coastguard Worker &queue_mapping, sizeof(queue_mapping));
151*de1e4e89SAndroid Build Coastguard Worker if (flags & SKBEDIT_F_PRIORITY)
152*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
153*de1e4e89SAndroid Build Coastguard Worker &priority, sizeof(priority));
154*de1e4e89SAndroid Build Coastguard Worker if (flags & SKBEDIT_F_MARK)
155*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK,
156*de1e4e89SAndroid Build Coastguard Worker &mark, sizeof(mark));
157*de1e4e89SAndroid Build Coastguard Worker if (flags & SKBEDIT_F_PTYPE)
158*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE,
159*de1e4e89SAndroid Build Coastguard Worker &ptype, sizeof(ptype));
160*de1e4e89SAndroid Build Coastguard Worker tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
161*de1e4e89SAndroid Build Coastguard Worker
162*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
163*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
164*de1e4e89SAndroid Build Coastguard Worker return 0;
165*de1e4e89SAndroid Build Coastguard Worker }
166*de1e4e89SAndroid Build Coastguard Worker
print_skbedit(struct action_util * au,FILE * f,struct rtattr * arg)167*de1e4e89SAndroid Build Coastguard Worker static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
168*de1e4e89SAndroid Build Coastguard Worker {
169*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[TCA_SKBEDIT_MAX + 1];
170*de1e4e89SAndroid Build Coastguard Worker
171*de1e4e89SAndroid Build Coastguard Worker SPRINT_BUF(b1);
172*de1e4e89SAndroid Build Coastguard Worker __u32 *priority;
173*de1e4e89SAndroid Build Coastguard Worker __u32 *mark;
174*de1e4e89SAndroid Build Coastguard Worker __u16 *queue_mapping, *ptype;
175*de1e4e89SAndroid Build Coastguard Worker struct tc_skbedit *p = NULL;
176*de1e4e89SAndroid Build Coastguard Worker
177*de1e4e89SAndroid Build Coastguard Worker if (arg == NULL)
178*de1e4e89SAndroid Build Coastguard Worker return -1;
179*de1e4e89SAndroid Build Coastguard Worker
180*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(tb, TCA_SKBEDIT_MAX, arg);
181*de1e4e89SAndroid Build Coastguard Worker
182*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_SKBEDIT_PARMS] == NULL) {
183*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "[NULL skbedit parameters]");
184*de1e4e89SAndroid Build Coastguard Worker return -1;
185*de1e4e89SAndroid Build Coastguard Worker }
186*de1e4e89SAndroid Build Coastguard Worker p = RTA_DATA(tb[TCA_SKBEDIT_PARMS]);
187*de1e4e89SAndroid Build Coastguard Worker
188*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " skbedit");
189*de1e4e89SAndroid Build Coastguard Worker
190*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
191*de1e4e89SAndroid Build Coastguard Worker queue_mapping = RTA_DATA(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
192*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " queue_mapping %u", *queue_mapping);
193*de1e4e89SAndroid Build Coastguard Worker }
194*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
195*de1e4e89SAndroid Build Coastguard Worker priority = RTA_DATA(tb[TCA_SKBEDIT_PRIORITY]);
196*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " priority %s", sprint_tc_classid(*priority, b1));
197*de1e4e89SAndroid Build Coastguard Worker }
198*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_SKBEDIT_MARK] != NULL) {
199*de1e4e89SAndroid Build Coastguard Worker mark = RTA_DATA(tb[TCA_SKBEDIT_MARK]);
200*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " mark %d", *mark);
201*de1e4e89SAndroid Build Coastguard Worker }
202*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_SKBEDIT_PTYPE] != NULL) {
203*de1e4e89SAndroid Build Coastguard Worker ptype = RTA_DATA(tb[TCA_SKBEDIT_PTYPE]);
204*de1e4e89SAndroid Build Coastguard Worker if (*ptype == PACKET_HOST)
205*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " ptype host");
206*de1e4e89SAndroid Build Coastguard Worker else if (*ptype == PACKET_BROADCAST)
207*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " ptype broadcast");
208*de1e4e89SAndroid Build Coastguard Worker else if (*ptype == PACKET_MULTICAST)
209*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " ptype multicast");
210*de1e4e89SAndroid Build Coastguard Worker else if (*ptype == PACKET_OTHERHOST)
211*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " ptype otherhost");
212*de1e4e89SAndroid Build Coastguard Worker else
213*de1e4e89SAndroid Build Coastguard Worker fprintf(f, " ptype %d", *ptype);
214*de1e4e89SAndroid Build Coastguard Worker }
215*de1e4e89SAndroid Build Coastguard Worker
216*de1e4e89SAndroid Build Coastguard Worker print_action_control(f, " ", p->action, "");
217*de1e4e89SAndroid Build Coastguard Worker
218*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n\t index %u ref %d bind %d",
219*de1e4e89SAndroid Build Coastguard Worker p->index, p->refcnt, p->bindcnt);
220*de1e4e89SAndroid Build Coastguard Worker
221*de1e4e89SAndroid Build Coastguard Worker if (show_stats) {
222*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_SKBEDIT_TM]) {
223*de1e4e89SAndroid Build Coastguard Worker struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]);
224*de1e4e89SAndroid Build Coastguard Worker
225*de1e4e89SAndroid Build Coastguard Worker print_tm(f, tm);
226*de1e4e89SAndroid Build Coastguard Worker }
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker
229*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n ");
230*de1e4e89SAndroid Build Coastguard Worker
231*de1e4e89SAndroid Build Coastguard Worker return 0;
232*de1e4e89SAndroid Build Coastguard Worker }
233*de1e4e89SAndroid Build Coastguard Worker
234*de1e4e89SAndroid Build Coastguard Worker struct action_util skbedit_action_util = {
235*de1e4e89SAndroid Build Coastguard Worker .id = "skbedit",
236*de1e4e89SAndroid Build Coastguard Worker .parse_aopt = parse_skbedit,
237*de1e4e89SAndroid Build Coastguard Worker .print_aopt = print_skbedit,
238*de1e4e89SAndroid Build Coastguard Worker };
239