13822cc986cc33751b82a22b91289ef088d94440cGregoire Baron/*
23822cc986cc33751b82a22b91289ef088d94440cGregoire Baron * m_csum.c	checksum updating action
33822cc986cc33751b82a22b91289ef088d94440cGregoire Baron *
43822cc986cc33751b82a22b91289ef088d94440cGregoire Baron *		This program is free software; you can distribute it and/or
53822cc986cc33751b82a22b91289ef088d94440cGregoire Baron *		modify it under the terms of the GNU General Public License
63822cc986cc33751b82a22b91289ef088d94440cGregoire Baron *		as published by the Free Software Foundation; either version
73822cc986cc33751b82a22b91289ef088d94440cGregoire Baron *		2 of the License, or (at your option) any later version.
83822cc986cc33751b82a22b91289ef088d94440cGregoire Baron *
93822cc986cc33751b82a22b91289ef088d94440cGregoire Baron * Authors: Gregoire Baron <baronchon@n7mm.org>
103822cc986cc33751b82a22b91289ef088d94440cGregoire Baron */
113822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
123822cc986cc33751b82a22b91289ef088d94440cGregoire Baron#include <stdio.h>
133822cc986cc33751b82a22b91289ef088d94440cGregoire Baron#include <stdlib.h>
143822cc986cc33751b82a22b91289ef088d94440cGregoire Baron#include <string.h>
153822cc986cc33751b82a22b91289ef088d94440cGregoire Baron#include <unistd.h>
163822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
173822cc986cc33751b82a22b91289ef088d94440cGregoire Baron#include <linux/tc_act/tc_csum.h>
183822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
193822cc986cc33751b82a22b91289ef088d94440cGregoire Baron#include "utils.h"
203822cc986cc33751b82a22b91289ef088d94440cGregoire Baron#include "tc_util.h"
213822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
223822cc986cc33751b82a22b91289ef088d94440cGregoire Baronstatic void
233822cc986cc33751b82a22b91289ef088d94440cGregoire Baronexplain(void)
243822cc986cc33751b82a22b91289ef088d94440cGregoire Baron{
253822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	fprintf(stderr, "Usage: ... csum <UPDATE>\n"
263822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			"Where: UPDATE := <TARGET> [<UPDATE>]\n"
273822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			"       TARGET := { ip4h | icmp | igmp |"
283822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				" tcp | udp | udplite | <SWEETS> }\n"
293822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			"       SWEETS := { and | or | \'+\' }\n");
303822cc986cc33751b82a22b91289ef088d94440cGregoire Baron}
313822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
323822cc986cc33751b82a22b91289ef088d94440cGregoire Baronstatic void
333822cc986cc33751b82a22b91289ef088d94440cGregoire Baronusage(void)
343822cc986cc33751b82a22b91289ef088d94440cGregoire Baron{
353822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	explain();
363822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	exit(-1);
373822cc986cc33751b82a22b91289ef088d94440cGregoire Baron}
383822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
393822cc986cc33751b82a22b91289ef088d94440cGregoire Baronstatic int
403822cc986cc33751b82a22b91289ef088d94440cGregoire Baronparse_csum_args(int *argc_p, char ***argv_p, struct tc_csum *sel)
413822cc986cc33751b82a22b91289ef088d94440cGregoire Baron{
423822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	int argc = *argc_p;
433822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char **argv = *argv_p;
443822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
453822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (argc <= 0)
463822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		return -1;
473822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
483822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	while(argc > 0) {
493822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		if ((matches(*argv, "iph") == 0) ||
503822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		    (matches(*argv, "ip4h") == 0) ||
513822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		    (matches(*argv, "ipv4h") == 0))
523822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel->update_flags |= TCA_CSUM_UPDATE_FLAG_IPV4HDR;
533822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
543822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else if (matches(*argv, "icmp") == 0)
553822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel->update_flags |= TCA_CSUM_UPDATE_FLAG_ICMP;
563822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
573822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else if (matches(*argv, "igmp") == 0)
583822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel->update_flags |= TCA_CSUM_UPDATE_FLAG_IGMP;
593822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
603822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else if (matches(*argv, "tcp") == 0)
613822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel->update_flags |= TCA_CSUM_UPDATE_FLAG_TCP;
623822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
633822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else if (matches(*argv, "udp") == 0)
643822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel->update_flags |= TCA_CSUM_UPDATE_FLAG_UDP;
653822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
663822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else if (matches(*argv, "udplite") == 0)
673822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel->update_flags |= TCA_CSUM_UPDATE_FLAG_UDPLITE;
683822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
693822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else if ((matches(*argv, "and") == 0) ||
703822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			 (matches(*argv, "or") == 0) ||
713822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			 (matches(*argv, "+") == 0))
723822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			; /* just ignore: ... csum iph and tcp or udp */
733822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else
743822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			break;
753822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		argc--;
763822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		argv++;
773822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
783822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
793822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	*argc_p = argc;
803822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	*argv_p = argv;
813822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
823822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	return 0;
833822cc986cc33751b82a22b91289ef088d94440cGregoire Baron}
843822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
853822cc986cc33751b82a22b91289ef088d94440cGregoire Baronstatic int
863822cc986cc33751b82a22b91289ef088d94440cGregoire Baronparse_csum(struct action_util *a, int *argc_p,
873822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	   char ***argv_p, int tca_id, struct nlmsghdr *n)
883822cc986cc33751b82a22b91289ef088d94440cGregoire Baron{
893822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	struct tc_csum sel;
903822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
913822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	int argc = *argc_p;
923822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char **argv = *argv_p;
933822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	int ok = 0;
943822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	struct rtattr *tail;
953822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
963822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	memset(&sel, 0, sizeof(sel));
973822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
983822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	while (argc > 0) {
993822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		if (matches(*argv, "csum") == 0) {
1003822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			NEXT_ARG();
1013822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			if (parse_csum_args(&argc, &argv, &sel)) {
1023822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				fprintf(stderr, "Illegal csum construct (%s)\n",
1033822cc986cc33751b82a22b91289ef088d94440cGregoire Baron					*argv);
1043822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				explain();
1053822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				return -1;
1063822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			}
1073822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			ok++;
1083822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			continue;
1093822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		} else if (matches(*argv, "help") == 0) {
1103822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			usage();
1113822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		}
1123822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		else {
1133822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			break;
1143822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		}
1153822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
1163822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1173822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (!ok) {
1183822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		explain();
1193822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		return -1;
1203822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
1213822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1223822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (sel.update_flags == 0) {
1233822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		fprintf(stderr, "Illegal csum construct, empty <UPDATE> list\n");
1243822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		return -1;
1253822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
1263822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1273822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (argc) {
1283822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		if (matches(*argv, "reclassify") == 0) {
1293822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel.action = TC_ACT_RECLASSIFY;
1303822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argc--;
1313822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argv++;
1323822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		} else if (matches(*argv, "pipe") == 0) {
1333822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel.action = TC_ACT_PIPE;
1343822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argc--;
1353822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argv++;
1363822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		} else if (matches(*argv, "drop") == 0 ||
1373822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			matches(*argv, "shot") == 0) {
1383822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel.action = TC_ACT_SHOT;
1393822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argc--;
1403822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argv++;
1413822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		} else if (matches(*argv, "continue") == 0) {
1423822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel.action = TC_ACT_UNSPEC;
1433822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argc--;
1443822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argv++;
1453822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		} else if (matches(*argv, "pass") == 0) {
1463822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			sel.action = TC_ACT_OK;
1473822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argc--;
1483822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argv++;
1493822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		}
1503822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
1513822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1523822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (argc) {
1533822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		if (matches(*argv, "index") == 0) {
1543822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			NEXT_ARG();
1553822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			if (get_u32(&sel.index, *argv, 10)) {
1563822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				fprintf(stderr, "Illegal \"index\" (%s) <csum>\n",
1573822cc986cc33751b82a22b91289ef088d94440cGregoire Baron					*argv);
1583822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				return -1;
1593822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			}
1603822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argc--;
1613822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			argv++;
1623822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		}
1633822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
1643822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1653822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	tail = NLMSG_TAIL(n);
1663822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
1673822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	addattr_l(n, MAX_MSG, TCA_CSUM_PARMS, &sel, sizeof(sel));
1683822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
1693822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1703822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	*argc_p = argc;
1713822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	*argv_p = argv;
1723822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1733822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	return 0;
1743822cc986cc33751b82a22b91289ef088d94440cGregoire Baron}
1753822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1763822cc986cc33751b82a22b91289ef088d94440cGregoire Baronstatic int
1773822cc986cc33751b82a22b91289ef088d94440cGregoire Baronprint_csum(struct action_util *au, FILE * f, struct rtattr *arg)
1783822cc986cc33751b82a22b91289ef088d94440cGregoire Baron{
1793822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	struct tc_csum *sel;
1803822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1813822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	struct rtattr *tb[TCA_CSUM_MAX + 1];
1823822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1833822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char *uflag_1 = "";
1843822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char *uflag_2 = "";
1853822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char *uflag_3 = "";
1863822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char *uflag_4 = "";
1873822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char *uflag_5 = "";
1883822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	char *uflag_6 = "";
1893822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	SPRINT_BUF(action_buf);
1903822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1913822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	int uflag_count = 0;
1923822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1933822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (arg == NULL)
1943822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		return -1;
1953822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1963822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	parse_rtattr_nested(tb, TCA_CSUM_MAX, arg);
1973822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
1983822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (tb[TCA_CSUM_PARMS] == NULL) {
1993822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		fprintf(f, "[NULL csum parameters]");
2003822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		return -1;
2013822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
2023822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	sel = RTA_DATA(tb[TCA_CSUM_PARMS]);
2033822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
2043822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (sel->update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) {
2053822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		uflag_1 = "iph";
2063822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		uflag_count++;
2073822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
2083822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	#define CSUM_UFLAG_BUFFER(flag_buffer, flag_value, flag_string)	\
2093822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		do {							\
2103822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			if (sel->update_flags & flag_value) {		\
2113822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				flag_buffer = uflag_count > 0 ?		\
2123822cc986cc33751b82a22b91289ef088d94440cGregoire Baron					", " flag_string : flag_string; \
2133822cc986cc33751b82a22b91289ef088d94440cGregoire Baron				uflag_count++;				\
2143822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			}						\
2153822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		} while(0)
2163822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	CSUM_UFLAG_BUFFER(uflag_2, TCA_CSUM_UPDATE_FLAG_ICMP, "icmp");
2173822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	CSUM_UFLAG_BUFFER(uflag_3, TCA_CSUM_UPDATE_FLAG_IGMP, "igmp");
21890d98edf39dc7da64fdf79408d5378e8d88acbe3Anton Danilov	CSUM_UFLAG_BUFFER(uflag_4, TCA_CSUM_UPDATE_FLAG_TCP, "tcp");
2193822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	CSUM_UFLAG_BUFFER(uflag_5, TCA_CSUM_UPDATE_FLAG_UDP, "udp");
2203822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	CSUM_UFLAG_BUFFER(uflag_6, TCA_CSUM_UPDATE_FLAG_UDPLITE, "udplite");
2213822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (!uflag_count) {
2223822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		uflag_1 = "?empty";
2233822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
2243822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
2253822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	fprintf(f, "csum (%s%s%s%s%s%s) action %s\n",
2263822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		uflag_1, uflag_2, uflag_3,
2273822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		uflag_4, uflag_5, uflag_6,
2283822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		action_n2a(sel->action, action_buf, sizeof(action_buf)));
2293822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	fprintf(f, "\tindex %d ref %d bind %d", sel->index, sel->refcnt, sel->bindcnt);
2303822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
2313822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	if (show_stats) {
2323822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		if (tb[TCA_CSUM_TM]) {
2333822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			struct tcf_t *tm = RTA_DATA(tb[TCA_CSUM_TM]);
2343822cc986cc33751b82a22b91289ef088d94440cGregoire Baron			print_tm(f,tm);
2353822cc986cc33751b82a22b91289ef088d94440cGregoire Baron		}
2363822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	}
2373822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	fprintf(f, "\n");
2383822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
2393822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	return 0;
2403822cc986cc33751b82a22b91289ef088d94440cGregoire Baron}
2413822cc986cc33751b82a22b91289ef088d94440cGregoire Baron
2423822cc986cc33751b82a22b91289ef088d94440cGregoire Baronstruct action_util csum_action_util = {
2433822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	.id = "csum",
2443822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	.parse_aopt = parse_csum,
2453822cc986cc33751b82a22b91289ef088d94440cGregoire Baron	.print_aopt = print_csum,
2463822cc986cc33751b82a22b91289ef088d94440cGregoire Baron};
247