2 * f_canprio.c Filter for CAN packets
4 * This program is free software; you can distribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Copyright: (c) 2011 Czech Technical University in Prague
10 * Authors: Michal Sojka <sojkam1@fel.cvut.cz>
11 * Pavel Pisa <pisa@cmp.felk.cvut.cz>
12 * Rostislav Lisovy <lisovy@kormus.cz>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
30 #ifdef CONFIG_HAVE_LINUX_CAN_H
31 #include "linux/can.h"
33 #elif !defined(CAN_EFF_FLAG)
34 /* special address description flags for the CAN_ID */
35 #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
36 #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
37 #define CAN_ERR_FLAG 0x20000000U /* error frame */
39 /* valid bits in CAN ID for frame formats */
40 #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
41 #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
42 #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
51 static void explain(void)
53 fprintf(stderr, "Usage: ... canprio [ MATCHSPEC ] [ flowid FLOWID ]\n"
55 "Where: MATCHSPEC := { matchid FILTERID | matcheid FILTERID | \n"
57 " FILTERID := CANID:MASK \n"
59 "NOTE: CLASSID, CANID, MASK is parsed as hexadecimal input.\n");
62 static int canprio_parse_opt(struct filter_util *qu, char *handle,
63 int argc, char **argv, struct nlmsghdr *n)
65 struct tcmsg *t = NLMSG_DATA(n); // Why?
67 struct canprio_rule canprio_rules[32];
77 h = strtol(handle, NULL, 0);
78 if (h == LONG_MIN || h == LONG_MAX) {
79 fprintf(stderr, "Illegal handle \"%s\", must be numeric.\n",
85 t->tcm_handle = h; // Why?
87 tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
88 addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
91 if (matches(*argv, "match") == 0) {
92 //printf(" [parsing match ...");
95 if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
96 fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
100 //printf("... 0x%x:0x%x]\n", canid, canid_mask);
101 if (canid >= 0) {// FIXME boundary check
102 canprio_rules[rules_count].canid = canid;
103 canprio_rules[rules_count].canid_mask = canid_mask;
107 } else if (matches(*argv, "matchid") == 0) {
110 if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
111 fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
115 if (canid & ~CAN_SFF_MASK) {
116 fprintf(stderr, "Id 0x%lx exceeded standard CAN ID range.",
117 (unsigned long)canid);
121 canprio_rules[rules_count].canid = canid;
122 canprio_rules[rules_count].canid_mask = (canid_mask & CAN_SFF_MASK);
125 } else if (matches(*argv, "matcheid") == 0) {
128 if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
129 fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
133 if (canid & ~CAN_EFF_MASK) {
134 fprintf(stderr, "Id 0x%lx exceeded extended CAN ID range.",
135 (unsigned long)canid);
139 canprio_rules[rules_count].canid = canid | CAN_EFF_FLAG;
140 canprio_rules[rules_count].canid_mask = (canid_mask & CAN_EFF_MASK);
143 } else if (matches(*argv, "classid") == 0 ||
144 strcmp(*argv, "flowid") == 0) {
145 //printf(" [parsing flowid]\n");
148 if (get_tc_classid(&handle, *argv)) {
149 fprintf(stderr, "Illegal \"classid\"\n");
152 addattr_l(n, MAX_MSG, TCA_CANPRIO_CLASSID, &handle, 4);
154 } else if (strcmp(*argv, "help") == 0) {
159 fprintf(stderr, "What is \"%s\"?\n", *argv);
166 addattr_l(n, MAX_MSG, TCA_CANPRIO_RULES, &canprio_rules,
167 sizeof(struct canprio_rule) * rules_count);
169 tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail;
173 /* FIXME I don't know how to test if function is correct.
174 I was not able to figure out how to call this function */
175 static int canprio_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
178 struct rtattr *tb[TCA_CANPRIO_MAX+1];
179 struct canprio_rule *canprio_rules = NULL;
183 printf("canprio_print_opt() invoked \n");
188 parse_rtattr_nested(tb, TCA_CANPRIO_MAX, opt);
191 fprintf(f, "handle 0x%x ", handle);
193 if (tb[TCA_BASIC_CLASSID]) {
194 SPRINT_BUF(b1); //allocate buffer b1
195 fprintf(f, "flowid %s ",
196 sprint_tc_classid(*(__u32*)RTA_DATA(tb[TCA_BASIC_CLASSID]), b1));
199 if (tb[TCA_CANPRIO_RULES]) {
200 if (RTA_PAYLOAD(tb[TCA_CANPRIO_RULES]) < sizeof(struct canprio_rule))
203 canprio_rules = RTA_DATA(tb[TCA_CANPRIO_RULES]);
204 rules_count = RTA_LENGTH(canprio_rules);
206 for(i = 0; i < rules_count; i++) {
207 fprintf(f, "CAN ID 0x%lx ",
208 (unsigned long)(canprio_rules[i].canid));
209 fprintf(f, "CAN ID mask 0x%lx ",
210 (unsigned long)(canprio_rules[i].canid_mask));
218 struct filter_util canprio_filter_util = {
220 .parse_fopt = canprio_parse_opt,
221 .print_fopt = canprio_print_opt,