]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - tc/f_canprio.c
It is possible to pass multiple rules for one instance of a filter.
[lisovros/iproute2_canprio.git] / tc / f_canprio.c
1 /* f_canprio.c          Filter for CAN packets */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <syslog.h>
7 #include <fcntl.h>
8 #include <sys/socket.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
11 #include <string.h>
12 #include <linux/if.h>
13 #include <limits.h>
14
15 #include "utils.h"
16 #include "tc_util.h"
17
18 struct canprio_rule {
19         __u32 canid;
20         __u32 canid_mask;
21 };
22
23 struct canprio_rule canprio_rules[32];
24
25 static void explain(void)
26 {
27         fprintf(stderr, "Usage: ... canprio match CANID:MASK flowid FLOWID\n");
28 }
29
30
31 static int canprio_parse_opt(struct filter_util *qu, char *handle,
32                          int argc, char **argv, struct nlmsghdr *n)
33 {
34         struct tcmsg *t = NLMSG_DATA(n);  // Why?
35         struct rtattr *tail;
36         long h = 0;
37         __u32 canid, canid_mask;
38         int rules_count = 0;
39
40         if (argc == 0)
41                 return 0;
42
43         if (handle) {
44                 h = strtol(handle, NULL, 0);
45                 if (h == LONG_MIN || h == LONG_MAX) {
46                         fprintf(stderr, "Illegal handle \"%s\", must be numeric.\n",
47                                 handle);
48                         return -1;
49                 }
50         }
51
52         t->tcm_handle = h;  // Why?
53
54         tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
55         addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
56
57         while (argc > 0) {
58                 if (matches(*argv, "match") == 0) {
59                         //printf("  [parsing match ...");
60                         NEXT_ARG();
61
62                         //FIXME why it does not work with "%jx"?
63                         if (sscanf(*argv, "%lx:%lx", &canid, &canid_mask) != 2) { 
64                                 fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
65                                 return -1;
66                         }
67
68                         //printf("... 0x%x:0x%x]\n", canid, canid_mask);
69                         if (canid > 0) {// FIXME boundary check
70                                 canprio_rules[rules_count].canid = canid;
71                                 canprio_rules[rules_count].canid_mask = canid_mask;
72                                 rules_count++;
73                         }
74
75                 } else if (matches(*argv, "classid") == 0 ||
76                                 strcmp(*argv, "flowid") == 0) {
77                         //printf("  [parsing flowid]\n");
78                         unsigned handle;
79                         NEXT_ARG();
80                         if (get_tc_classid(&handle, *argv)) {
81                                 fprintf(stderr, "Illegal \"classid\"\n");
82                                 return -1;
83                         }
84                         addattr_l(n, MAX_MSG, TCA_CANPRIO_CLASSID, &handle, 4);
85
86                 } else if (strcmp(*argv, "help") == 0) {
87                         explain();
88                         return -1;
89
90                 } else {
91                         fprintf(stderr, "What is \"%s\"?\n", *argv);
92                         explain();
93                         return -1;
94                 }
95                 argc--; argv++;
96         }
97
98         
99         addattr_l(n, MAX_MSG, TCA_CANPRIO_RULES, &canprio_rules, 
100                 sizeof(struct canprio_rule) * rules_count);
101
102         tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail;
103         return 0;
104 }
105
106 static int canprio_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
107                          __u32 handle)
108 {
109         struct rtattr *tb[TCA_CANPRIO_MAX+1];
110
111
112         if (opt == NULL)
113                 return 0;
114
115         parse_rtattr_nested(tb, TCA_CANPRIO_MAX, opt);
116
117         if (handle)
118                 fprintf(f, "handle 0x%x ", handle);
119
120         if (tb[TCA_BASIC_CLASSID]) {
121                 SPRINT_BUF(b1); //FIXME wat?
122                 fprintf(f, "flowid %s ",
123                         sprint_tc_classid(*(__u32*)RTA_DATA(tb[TCA_BASIC_CLASSID]), b1));
124         }
125
126         //FIXME
127         //if (tb[TCA_CANPRIO_RULES])
128         //      fprintf(f, "Canid 0x%x ",
129         //                      *(__u32 *)RTA_DATA(tb[TCA_CANPRIO_MATCH]));
130
131
132         return 0;
133 }
134
135
136 struct filter_util canprio_filter_util = {
137         .id = "canprio",
138         .parse_fopt = canprio_parse_opt,
139         .print_fopt = canprio_print_opt,
140 };
141