1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * m_csum.c checksum updating action
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can distribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Authors: Gregoire Baron <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker */
11*de1e4e89SAndroid Build Coastguard Worker
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
16*de1e4e89SAndroid Build Coastguard Worker
17*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_csum.h>
18*de1e4e89SAndroid Build Coastguard Worker
19*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
20*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
21*de1e4e89SAndroid Build Coastguard Worker
22*de1e4e89SAndroid Build Coastguard Worker static void
explain(void)23*de1e4e89SAndroid Build Coastguard Worker explain(void)
24*de1e4e89SAndroid Build Coastguard Worker {
25*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Usage: ... csum <UPDATE>\n"
26*de1e4e89SAndroid Build Coastguard Worker "Where: UPDATE := <TARGET> [<UPDATE>]\n"
27*de1e4e89SAndroid Build Coastguard Worker " TARGET := { ip4h | icmp | igmp | tcp | udp | udplite | sctp | <SWEETS> }\n"
28*de1e4e89SAndroid Build Coastguard Worker " SWEETS := { and | or | \'+\' }\n");
29*de1e4e89SAndroid Build Coastguard Worker }
30*de1e4e89SAndroid Build Coastguard Worker
31*de1e4e89SAndroid Build Coastguard Worker static void
usage(void)32*de1e4e89SAndroid Build Coastguard Worker usage(void)
33*de1e4e89SAndroid Build Coastguard Worker {
34*de1e4e89SAndroid Build Coastguard Worker explain();
35*de1e4e89SAndroid Build Coastguard Worker exit(-1);
36*de1e4e89SAndroid Build Coastguard Worker }
37*de1e4e89SAndroid Build Coastguard Worker
38*de1e4e89SAndroid Build Coastguard Worker static int
parse_csum_args(int * argc_p,char *** argv_p,struct tc_csum * sel)39*de1e4e89SAndroid Build Coastguard Worker parse_csum_args(int *argc_p, char ***argv_p, struct tc_csum *sel)
40*de1e4e89SAndroid Build Coastguard Worker {
41*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
42*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
43*de1e4e89SAndroid Build Coastguard Worker
44*de1e4e89SAndroid Build Coastguard Worker if (argc <= 0)
45*de1e4e89SAndroid Build Coastguard Worker return -1;
46*de1e4e89SAndroid Build Coastguard Worker
47*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
48*de1e4e89SAndroid Build Coastguard Worker if ((matches(*argv, "iph") == 0) ||
49*de1e4e89SAndroid Build Coastguard Worker (matches(*argv, "ip4h") == 0) ||
50*de1e4e89SAndroid Build Coastguard Worker (matches(*argv, "ipv4h") == 0))
51*de1e4e89SAndroid Build Coastguard Worker sel->update_flags |= TCA_CSUM_UPDATE_FLAG_IPV4HDR;
52*de1e4e89SAndroid Build Coastguard Worker
53*de1e4e89SAndroid Build Coastguard Worker else if (matches(*argv, "icmp") == 0)
54*de1e4e89SAndroid Build Coastguard Worker sel->update_flags |= TCA_CSUM_UPDATE_FLAG_ICMP;
55*de1e4e89SAndroid Build Coastguard Worker
56*de1e4e89SAndroid Build Coastguard Worker else if (matches(*argv, "igmp") == 0)
57*de1e4e89SAndroid Build Coastguard Worker sel->update_flags |= TCA_CSUM_UPDATE_FLAG_IGMP;
58*de1e4e89SAndroid Build Coastguard Worker
59*de1e4e89SAndroid Build Coastguard Worker else if (matches(*argv, "tcp") == 0)
60*de1e4e89SAndroid Build Coastguard Worker sel->update_flags |= TCA_CSUM_UPDATE_FLAG_TCP;
61*de1e4e89SAndroid Build Coastguard Worker
62*de1e4e89SAndroid Build Coastguard Worker else if (matches(*argv, "udp") == 0)
63*de1e4e89SAndroid Build Coastguard Worker sel->update_flags |= TCA_CSUM_UPDATE_FLAG_UDP;
64*de1e4e89SAndroid Build Coastguard Worker
65*de1e4e89SAndroid Build Coastguard Worker else if (matches(*argv, "udplite") == 0)
66*de1e4e89SAndroid Build Coastguard Worker sel->update_flags |= TCA_CSUM_UPDATE_FLAG_UDPLITE;
67*de1e4e89SAndroid Build Coastguard Worker
68*de1e4e89SAndroid Build Coastguard Worker else if (matches(*argv, "sctp") == 0)
69*de1e4e89SAndroid Build Coastguard Worker sel->update_flags |= TCA_CSUM_UPDATE_FLAG_SCTP;
70*de1e4e89SAndroid Build Coastguard Worker
71*de1e4e89SAndroid Build Coastguard Worker else if ((matches(*argv, "and") == 0) ||
72*de1e4e89SAndroid Build Coastguard Worker (matches(*argv, "or") == 0) ||
73*de1e4e89SAndroid Build Coastguard Worker (matches(*argv, "+") == 0))
74*de1e4e89SAndroid Build Coastguard Worker ; /* just ignore: ... csum iph and tcp or udp */
75*de1e4e89SAndroid Build Coastguard Worker else
76*de1e4e89SAndroid Build Coastguard Worker break;
77*de1e4e89SAndroid Build Coastguard Worker argc--;
78*de1e4e89SAndroid Build Coastguard Worker argv++;
79*de1e4e89SAndroid Build Coastguard Worker }
80*de1e4e89SAndroid Build Coastguard Worker
81*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
82*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
83*de1e4e89SAndroid Build Coastguard Worker
84*de1e4e89SAndroid Build Coastguard Worker return 0;
85*de1e4e89SAndroid Build Coastguard Worker }
86*de1e4e89SAndroid Build Coastguard Worker
87*de1e4e89SAndroid Build Coastguard Worker static int
parse_csum(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)88*de1e4e89SAndroid Build Coastguard Worker parse_csum(struct action_util *a, int *argc_p,
89*de1e4e89SAndroid Build Coastguard Worker char ***argv_p, int tca_id, struct nlmsghdr *n)
90*de1e4e89SAndroid Build Coastguard Worker {
91*de1e4e89SAndroid Build Coastguard Worker struct tc_csum sel = {};
92*de1e4e89SAndroid Build Coastguard Worker
93*de1e4e89SAndroid Build Coastguard Worker int argc = *argc_p;
94*de1e4e89SAndroid Build Coastguard Worker char **argv = *argv_p;
95*de1e4e89SAndroid Build Coastguard Worker int ok = 0;
96*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tail;
97*de1e4e89SAndroid Build Coastguard Worker
98*de1e4e89SAndroid Build Coastguard Worker while (argc > 0) {
99*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "csum") == 0) {
100*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
101*de1e4e89SAndroid Build Coastguard Worker if (parse_csum_args(&argc, &argv, &sel)) {
102*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal csum construct (%s)\n",
103*de1e4e89SAndroid Build Coastguard Worker *argv);
104*de1e4e89SAndroid Build Coastguard Worker explain();
105*de1e4e89SAndroid Build Coastguard Worker return -1;
106*de1e4e89SAndroid Build Coastguard Worker }
107*de1e4e89SAndroid Build Coastguard Worker ok++;
108*de1e4e89SAndroid Build Coastguard Worker continue;
109*de1e4e89SAndroid Build Coastguard Worker } else if (matches(*argv, "help") == 0) {
110*de1e4e89SAndroid Build Coastguard Worker usage();
111*de1e4e89SAndroid Build Coastguard Worker } else {
112*de1e4e89SAndroid Build Coastguard Worker break;
113*de1e4e89SAndroid Build Coastguard Worker }
114*de1e4e89SAndroid Build Coastguard Worker }
115*de1e4e89SAndroid Build Coastguard Worker
116*de1e4e89SAndroid Build Coastguard Worker if (!ok) {
117*de1e4e89SAndroid Build Coastguard Worker explain();
118*de1e4e89SAndroid Build Coastguard Worker return -1;
119*de1e4e89SAndroid Build Coastguard Worker }
120*de1e4e89SAndroid Build Coastguard Worker
121*de1e4e89SAndroid Build Coastguard Worker if (sel.update_flags == 0) {
122*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal csum construct, empty <UPDATE> list\n");
123*de1e4e89SAndroid Build Coastguard Worker return -1;
124*de1e4e89SAndroid Build Coastguard Worker }
125*de1e4e89SAndroid Build Coastguard Worker
126*de1e4e89SAndroid Build Coastguard Worker parse_action_control_dflt(&argc, &argv, &sel.action, false, TC_ACT_OK);
127*de1e4e89SAndroid Build Coastguard Worker
128*de1e4e89SAndroid Build Coastguard Worker if (argc) {
129*de1e4e89SAndroid Build Coastguard Worker if (matches(*argv, "index") == 0) {
130*de1e4e89SAndroid Build Coastguard Worker NEXT_ARG();
131*de1e4e89SAndroid Build Coastguard Worker if (get_u32(&sel.index, *argv, 10)) {
132*de1e4e89SAndroid Build Coastguard Worker fprintf(stderr, "Illegal \"index\" (%s) <csum>\n",
133*de1e4e89SAndroid Build Coastguard Worker *argv);
134*de1e4e89SAndroid Build Coastguard Worker return -1;
135*de1e4e89SAndroid Build Coastguard Worker }
136*de1e4e89SAndroid Build Coastguard Worker argc--;
137*de1e4e89SAndroid Build Coastguard Worker argv++;
138*de1e4e89SAndroid Build Coastguard Worker }
139*de1e4e89SAndroid Build Coastguard Worker }
140*de1e4e89SAndroid Build Coastguard Worker
141*de1e4e89SAndroid Build Coastguard Worker tail = NLMSG_TAIL(n);
142*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, tca_id, NULL, 0);
143*de1e4e89SAndroid Build Coastguard Worker addattr_l(n, MAX_MSG, TCA_CSUM_PARMS, &sel, sizeof(sel));
144*de1e4e89SAndroid Build Coastguard Worker tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
145*de1e4e89SAndroid Build Coastguard Worker
146*de1e4e89SAndroid Build Coastguard Worker *argc_p = argc;
147*de1e4e89SAndroid Build Coastguard Worker *argv_p = argv;
148*de1e4e89SAndroid Build Coastguard Worker
149*de1e4e89SAndroid Build Coastguard Worker return 0;
150*de1e4e89SAndroid Build Coastguard Worker }
151*de1e4e89SAndroid Build Coastguard Worker
152*de1e4e89SAndroid Build Coastguard Worker static int
print_csum(struct action_util * au,FILE * f,struct rtattr * arg)153*de1e4e89SAndroid Build Coastguard Worker print_csum(struct action_util *au, FILE *f, struct rtattr *arg)
154*de1e4e89SAndroid Build Coastguard Worker {
155*de1e4e89SAndroid Build Coastguard Worker struct tc_csum *sel;
156*de1e4e89SAndroid Build Coastguard Worker
157*de1e4e89SAndroid Build Coastguard Worker struct rtattr *tb[TCA_CSUM_MAX + 1];
158*de1e4e89SAndroid Build Coastguard Worker
159*de1e4e89SAndroid Build Coastguard Worker char *uflag_1 = "";
160*de1e4e89SAndroid Build Coastguard Worker char *uflag_2 = "";
161*de1e4e89SAndroid Build Coastguard Worker char *uflag_3 = "";
162*de1e4e89SAndroid Build Coastguard Worker char *uflag_4 = "";
163*de1e4e89SAndroid Build Coastguard Worker char *uflag_5 = "";
164*de1e4e89SAndroid Build Coastguard Worker char *uflag_6 = "";
165*de1e4e89SAndroid Build Coastguard Worker char *uflag_7 = "";
166*de1e4e89SAndroid Build Coastguard Worker
167*de1e4e89SAndroid Build Coastguard Worker int uflag_count = 0;
168*de1e4e89SAndroid Build Coastguard Worker
169*de1e4e89SAndroid Build Coastguard Worker if (arg == NULL)
170*de1e4e89SAndroid Build Coastguard Worker return -1;
171*de1e4e89SAndroid Build Coastguard Worker
172*de1e4e89SAndroid Build Coastguard Worker parse_rtattr_nested(tb, TCA_CSUM_MAX, arg);
173*de1e4e89SAndroid Build Coastguard Worker
174*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_CSUM_PARMS] == NULL) {
175*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "[NULL csum parameters]");
176*de1e4e89SAndroid Build Coastguard Worker return -1;
177*de1e4e89SAndroid Build Coastguard Worker }
178*de1e4e89SAndroid Build Coastguard Worker sel = RTA_DATA(tb[TCA_CSUM_PARMS]);
179*de1e4e89SAndroid Build Coastguard Worker
180*de1e4e89SAndroid Build Coastguard Worker if (sel->update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) {
181*de1e4e89SAndroid Build Coastguard Worker uflag_1 = "iph";
182*de1e4e89SAndroid Build Coastguard Worker uflag_count++;
183*de1e4e89SAndroid Build Coastguard Worker }
184*de1e4e89SAndroid Build Coastguard Worker #define CSUM_UFLAG_BUFFER(flag_buffer, flag_value, flag_string) \
185*de1e4e89SAndroid Build Coastguard Worker do { \
186*de1e4e89SAndroid Build Coastguard Worker if (sel->update_flags & flag_value) { \
187*de1e4e89SAndroid Build Coastguard Worker flag_buffer = uflag_count > 0 ? \
188*de1e4e89SAndroid Build Coastguard Worker ", " flag_string : flag_string; \
189*de1e4e89SAndroid Build Coastguard Worker uflag_count++; \
190*de1e4e89SAndroid Build Coastguard Worker } \
191*de1e4e89SAndroid Build Coastguard Worker } while (0)
192*de1e4e89SAndroid Build Coastguard Worker CSUM_UFLAG_BUFFER(uflag_2, TCA_CSUM_UPDATE_FLAG_ICMP, "icmp");
193*de1e4e89SAndroid Build Coastguard Worker CSUM_UFLAG_BUFFER(uflag_3, TCA_CSUM_UPDATE_FLAG_IGMP, "igmp");
194*de1e4e89SAndroid Build Coastguard Worker CSUM_UFLAG_BUFFER(uflag_4, TCA_CSUM_UPDATE_FLAG_TCP, "tcp");
195*de1e4e89SAndroid Build Coastguard Worker CSUM_UFLAG_BUFFER(uflag_5, TCA_CSUM_UPDATE_FLAG_UDP, "udp");
196*de1e4e89SAndroid Build Coastguard Worker CSUM_UFLAG_BUFFER(uflag_6, TCA_CSUM_UPDATE_FLAG_UDPLITE, "udplite");
197*de1e4e89SAndroid Build Coastguard Worker CSUM_UFLAG_BUFFER(uflag_7, TCA_CSUM_UPDATE_FLAG_SCTP, "sctp");
198*de1e4e89SAndroid Build Coastguard Worker if (!uflag_count) {
199*de1e4e89SAndroid Build Coastguard Worker uflag_1 = "?empty";
200*de1e4e89SAndroid Build Coastguard Worker }
201*de1e4e89SAndroid Build Coastguard Worker
202*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "csum (%s%s%s%s%s%s%s) ",
203*de1e4e89SAndroid Build Coastguard Worker uflag_1, uflag_2, uflag_3,
204*de1e4e89SAndroid Build Coastguard Worker uflag_4, uflag_5, uflag_6, uflag_7);
205*de1e4e89SAndroid Build Coastguard Worker print_action_control(f, "action ", sel->action, "\n");
206*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\tindex %u ref %d bind %d", sel->index, sel->refcnt,
207*de1e4e89SAndroid Build Coastguard Worker sel->bindcnt);
208*de1e4e89SAndroid Build Coastguard Worker
209*de1e4e89SAndroid Build Coastguard Worker if (show_stats) {
210*de1e4e89SAndroid Build Coastguard Worker if (tb[TCA_CSUM_TM]) {
211*de1e4e89SAndroid Build Coastguard Worker struct tcf_t *tm = RTA_DATA(tb[TCA_CSUM_TM]);
212*de1e4e89SAndroid Build Coastguard Worker
213*de1e4e89SAndroid Build Coastguard Worker print_tm(f, tm);
214*de1e4e89SAndroid Build Coastguard Worker }
215*de1e4e89SAndroid Build Coastguard Worker }
216*de1e4e89SAndroid Build Coastguard Worker fprintf(f, "\n");
217*de1e4e89SAndroid Build Coastguard Worker
218*de1e4e89SAndroid Build Coastguard Worker return 0;
219*de1e4e89SAndroid Build Coastguard Worker }
220*de1e4e89SAndroid Build Coastguard Worker
221*de1e4e89SAndroid Build Coastguard Worker struct action_util csum_action_util = {
222*de1e4e89SAndroid Build Coastguard Worker .id = "csum",
223*de1e4e89SAndroid Build Coastguard Worker .parse_aopt = parse_csum,
224*de1e4e89SAndroid Build Coastguard Worker .print_aopt = print_csum,
225*de1e4e89SAndroid Build Coastguard Worker };
226