1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * q_dsmark.c		Differentiated Services field marking.
3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Hacked 1998,1999 by Werner Almesberger, EPFL ICA
5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */
7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h>
9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h>
10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h>
11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h>
12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h>
13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h>
14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h>
15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h>
16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h>
17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h"
19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_util.h"
20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void explain(void)
23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr,"Usage: dsmark indices INDICES [ default_index "
25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	    "DEFAULT_INDEX ] [ set_tc_index ]\n");
26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int dsmark_parse_opt(struct qdisc_util *qu, int argc, char **argv,
30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat    struct nlmsghdr *n)
31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tail;
33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	__u16 ind;
34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *end;
35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int dflt,set_tc_index;
36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	ind = set_tc_index = 0;
38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	dflt = -1;
39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (argc > 0) {
40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!strcmp(*argv,"indices")) {
41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			NEXT_ARG();
42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			ind = strtoul(*argv,&end,0);
43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (*end) {
44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				explain();
45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (!strcmp(*argv,"default_index") || !strcmp(*argv,
49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		    "default")) {
50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			NEXT_ARG();
51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			dflt = strtoul(*argv,&end,0);
52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (*end) {
53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				explain();
54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (!strcmp(*argv,"set_tc_index")) {
58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			set_tc_index = 1;
59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else {
61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			explain();
62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		argc--;
65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		argv++;
66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!ind) {
68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		explain();
69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail = NLMSG_TAIL(n);
72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n,1024,TCA_OPTIONS,NULL,0);
73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n,1024,TCA_DSMARK_INDICES,&ind,sizeof(ind));
74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (dflt != -1) {
75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	    __u16 tmp = dflt;
76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	    addattr_l(n,1024,TCA_DSMARK_DEFAULT_INDEX,&tmp,sizeof(tmp));
78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (set_tc_index) addattr_l(n,1024,TCA_DSMARK_SET_TC_INDEX,NULL,0);
80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic void explain_class(void)
86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	fprintf(stderr, "Usage: ... dsmark [ mask MASK ] [ value VALUE ]\n");
88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int dsmark_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat   struct nlmsghdr *n)
93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tail;
95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	__u8 tmp;
96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *end;
97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail = NLMSG_TAIL(n);
99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	addattr_l(n,1024,TCA_OPTIONS,NULL,0);
100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	while (argc > 0) {
101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!strcmp(*argv,"mask")) {
102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			NEXT_ARG();
103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			tmp = strtoul(*argv,&end,0);
104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (*end) {
105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				explain_class();
106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			addattr_l(n,1024,TCA_DSMARK_MASK,&tmp,1);
109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (!strcmp(*argv,"value")) {
111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			NEXT_ARG();
112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			tmp = strtoul(*argv,&end,0);
113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (*end) {
114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				explain_class();
115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return -1;
116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			addattr_l(n,1024,TCA_DSMARK_VALUE,&tmp,1);
118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else {
120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			explain_class();
121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		argc--;
124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		argv++;
125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int dsmark_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tb[TCA_DSMARK_MAX+1];
135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!opt) return 0;
137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	memset(tb, 0, sizeof(tb));
138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	parse_rtattr(tb, TCA_DSMARK_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt));
139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_DSMARK_MASK]) {
140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK]))
141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr,"dsmark: empty mask\n");
142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else fprintf(f,"mask 0x%02x ",
143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			    *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK]));
144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_DSMARK_VALUE]) {
146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE]))
147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr,"dsmark: empty value\n");
148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else fprintf(f,"value 0x%02x ",
149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			    *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE]));
150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_DSMARK_INDICES]) {
152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (RTA_PAYLOAD(tb[TCA_DSMARK_INDICES]) < sizeof(__u16))
153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr,"dsmark: indices too short\n");
154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else fprintf(f,"indices 0x%04x ",
155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			    *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES]));
156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_DSMARK_DEFAULT_INDEX]) {
158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX]) < sizeof(__u16))
159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(stderr,"dsmark: default_index too short\n");
160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else fprintf(f,"default_index 0x%04x ",
161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			    *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX]));
162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_DSMARK_SET_TC_INDEX]) fprintf(f,"set_tc_index ");
164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct qdisc_util dsmark_qdisc_util = {
169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.id		= "dsmark",
170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.parse_qopt	= dsmark_parse_opt,
171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.print_qopt	= dsmark_print_opt,
172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.parse_copt	= dsmark_parse_class_opt,
173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	.print_copt	= dsmark_print_opt,
174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
175