1 /* f_canprio.c Filter for CAN packets */
8 #include <sys/socket.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
18 #ifdef CONFIG_HAVE_LINUX_CAN_H
19 #include "linux/can.h"
21 #elif !defined(CAN_EFF_FLAG)
22 /* special address description flags for the CAN_ID */
23 #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
24 #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
25 #define CAN_ERR_FLAG 0x20000000U /* error frame */
27 /* valid bits in CAN ID for frame formats */
28 #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
29 #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
30 #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
38 struct canprio_rule canprio_rules[32];
40 static void explain(void)
42 fprintf(stderr, "Usage: ... canprio [ MATCHSPEC ] [ flowid FLOWID ]\n"
44 "Where: MATCHSPEC := { matchid FILTERID | matcheid FILTERID | \n"
46 " FILTERID := CANID:MASK \n"
48 "NOTE: CLASSID, CANID, MASK is parsed as hexadecimal input.\n");
52 static int canprio_parse_opt(struct filter_util *qu, char *handle,
53 int argc, char **argv, struct nlmsghdr *n)
55 struct tcmsg *t = NLMSG_DATA(n); // Why?
66 h = strtol(handle, NULL, 0);
67 if (h == LONG_MIN || h == LONG_MAX) {
68 fprintf(stderr, "Illegal handle \"%s\", must be numeric.\n",
74 t->tcm_handle = h; // Why?
76 tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
77 addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
80 if (matches(*argv, "match") == 0) {
81 //printf(" [parsing match ...");
84 if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
85 fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
89 //printf("... 0x%x:0x%x]\n", canid, canid_mask);
90 if (canid >= 0) {// FIXME boundary check
91 canprio_rules[rules_count].canid = canid;
92 canprio_rules[rules_count].canid_mask = canid_mask;
97 } else if (matches(*argv, "matchid") == 0) {
100 if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
101 fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
105 if (canid & ~CAN_SFF_MASK) {
106 fprintf(stderr, "Id 0x%lx exceeded standard CAN ID range.",
107 (unsigned long)canid);
111 canprio_rules[rules_count].canid = canid;
112 canprio_rules[rules_count].canid_mask = (canid_mask & CAN_SFF_MASK);
115 } else if (matches(*argv, "matcheid") == 0) {
118 if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &canid, &canid_mask) != 2) {
119 fprintf(stderr, "improperly formed Can ID & mask '%s'\n", *argv);
123 if (canid & ~CAN_EFF_MASK) {
124 fprintf(stderr, "Id 0x%lx exceeded extended CAN ID range.",
125 (unsigned long)canid);
129 canprio_rules[rules_count].canid = canid | CAN_EFF_FLAG;
130 canprio_rules[rules_count].canid_mask = (canid_mask & CAN_EFF_MASK);
133 } else if (matches(*argv, "classid") == 0 ||
134 strcmp(*argv, "flowid") == 0) {
135 //printf(" [parsing flowid]\n");
138 if (get_tc_classid(&handle, *argv)) {
139 fprintf(stderr, "Illegal \"classid\"\n");
142 addattr_l(n, MAX_MSG, TCA_CANPRIO_CLASSID, &handle, 4);
144 } else if (strcmp(*argv, "help") == 0) {
149 fprintf(stderr, "What is \"%s\"?\n", *argv);
157 addattr_l(n, MAX_MSG, TCA_CANPRIO_RULES, &canprio_rules,
158 sizeof(struct canprio_rule) * rules_count);
160 tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail;
164 static int canprio_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
167 struct rtattr *tb[TCA_CANPRIO_MAX+1];
173 parse_rtattr_nested(tb, TCA_CANPRIO_MAX, opt);
176 fprintf(f, "handle 0x%x ", handle);
178 if (tb[TCA_BASIC_CLASSID]) {
179 SPRINT_BUF(b1); //FIXME wat?
180 fprintf(f, "flowid %s ",
181 sprint_tc_classid(*(__u32*)RTA_DATA(tb[TCA_BASIC_CLASSID]), b1));
185 //if (tb[TCA_CANPRIO_RULES])
186 // fprintf(f, "Canid 0x%x ",
187 // *(__u32 *)RTA_DATA(tb[TCA_CANPRIO_MATCH]));
194 struct filter_util canprio_filter_util = {
196 .parse_fopt = canprio_parse_opt,
197 .print_fopt = canprio_print_opt,