1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker * em_canid.c Ematch rule to match CAN frames according to their CAN identifiers
3*de1e4e89SAndroid Build Coastguard Worker *
4*de1e4e89SAndroid Build Coastguard Worker * This program is free software; you can distribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker * as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker * 2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker *
9*de1e4e89SAndroid Build Coastguard Worker * Idea: Oliver Hartkopp <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker * Copyright: (c) 2011 Czech Technical University in Prague
11*de1e4e89SAndroid Build Coastguard Worker * (c) 2011 Volkswagen Group Research
12*de1e4e89SAndroid Build Coastguard Worker * Authors: Michal Sojka <[email protected]>
13*de1e4e89SAndroid Build Coastguard Worker * Pavel Pisa <[email protected]>
14*de1e4e89SAndroid Build Coastguard Worker * Rostislav Lisovy <[email protected]>
15*de1e4e89SAndroid Build Coastguard Worker * Funded by: Volkswagen Group Research
16*de1e4e89SAndroid Build Coastguard Worker *
17*de1e4e89SAndroid Build Coastguard Worker * Documentation: http://rtime.felk.cvut.cz/can/socketcan-qdisc-final.pdf
18*de1e4e89SAndroid Build Coastguard Worker */
19*de1e4e89SAndroid Build Coastguard Worker
20*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
25*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
26*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
27*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
28*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
30*de1e4e89SAndroid Build Coastguard Worker #include <linux/can.h>
31*de1e4e89SAndroid Build Coastguard Worker #include <inttypes.h>
32*de1e4e89SAndroid Build Coastguard Worker #include "m_ematch.h"
33*de1e4e89SAndroid Build Coastguard Worker
34*de1e4e89SAndroid Build Coastguard Worker #define EM_CANID_RULES_MAX 400 /* Main reason for this number is Nelink
35*de1e4e89SAndroid Build Coastguard Worker message size limit equal to Single memory page size. When dump()
36*de1e4e89SAndroid Build Coastguard Worker is invoked, there are even some ematch related headers sent from
37*de1e4e89SAndroid Build Coastguard Worker kernel to userspace together with em_canid configuration --
38*de1e4e89SAndroid Build Coastguard Worker 400*sizeof(struct can_filter) should fit without any problems */
39*de1e4e89SAndroid Build Coastguard Worker
40*de1e4e89SAndroid Build Coastguard Worker extern struct ematch_util canid_ematch_util;
41*de1e4e89SAndroid Build Coastguard Worker struct rules {
42*de1e4e89SAndroid Build Coastguard Worker struct can_filter *rules_raw;
43*de1e4e89SAndroid Build Coastguard Worker int rules_capacity; /* Size of array allocated for rules_raw */
44*de1e4e89SAndroid Build Coastguard Worker int rules_cnt; /* Actual number of rules stored in rules_raw */
45*de1e4e89SAndroid Build Coastguard Worker };
46*de1e4e89SAndroid Build Coastguard Worker
canid_print_usage(FILE * fd)47*de1e4e89SAndroid Build Coastguard Worker static void canid_print_usage(FILE *fd)
48*de1e4e89SAndroid Build Coastguard Worker {
49*de1e4e89SAndroid Build Coastguard Worker fprintf(fd,
50*de1e4e89SAndroid Build Coastguard Worker "Usage: canid(IDLIST)\n" \
51*de1e4e89SAndroid Build Coastguard Worker "where: IDLIST := IDSPEC [ IDLIST ]\n" \
52*de1e4e89SAndroid Build Coastguard Worker " IDSPEC := { ’sff’ CANID | ’eff’ CANID }\n" \
53*de1e4e89SAndroid Build Coastguard Worker " CANID := ID[:MASK]\n" \
54*de1e4e89SAndroid Build Coastguard Worker " ID, MASK := hexadecimal number (i.e. 0x123)\n" \
55*de1e4e89SAndroid Build Coastguard Worker "Example: canid(sff 0x123 sff 0x124 sff 0x125:0xf)\n");
56*de1e4e89SAndroid Build Coastguard Worker }
57*de1e4e89SAndroid Build Coastguard Worker
canid_parse_rule(struct rules * rules,struct bstr * a,int iseff)58*de1e4e89SAndroid Build Coastguard Worker static int canid_parse_rule(struct rules *rules, struct bstr *a, int iseff)
59*de1e4e89SAndroid Build Coastguard Worker {
60*de1e4e89SAndroid Build Coastguard Worker unsigned int can_id = 0;
61*de1e4e89SAndroid Build Coastguard Worker unsigned int can_mask = 0;
62*de1e4e89SAndroid Build Coastguard Worker
63*de1e4e89SAndroid Build Coastguard Worker if (sscanf(a->data, "%"SCNx32 ":" "%"SCNx32, &can_id, &can_mask) != 2) {
64*de1e4e89SAndroid Build Coastguard Worker if (sscanf(a->data, "%"SCNx32, &can_id) != 1) {
65*de1e4e89SAndroid Build Coastguard Worker return -1;
66*de1e4e89SAndroid Build Coastguard Worker } else {
67*de1e4e89SAndroid Build Coastguard Worker can_mask = (iseff) ? CAN_EFF_MASK : CAN_SFF_MASK;
68*de1e4e89SAndroid Build Coastguard Worker }
69*de1e4e89SAndroid Build Coastguard Worker }
70*de1e4e89SAndroid Build Coastguard Worker
71*de1e4e89SAndroid Build Coastguard Worker /* Stretch rules array up to EM_CANID_RULES_MAX if necessary */
72*de1e4e89SAndroid Build Coastguard Worker if (rules->rules_cnt == rules->rules_capacity) {
73*de1e4e89SAndroid Build Coastguard Worker if (rules->rules_capacity <= EM_CANID_RULES_MAX/2) {
74*de1e4e89SAndroid Build Coastguard Worker rules->rules_capacity *= 2;
75*de1e4e89SAndroid Build Coastguard Worker rules->rules_raw = realloc(rules->rules_raw,
76*de1e4e89SAndroid Build Coastguard Worker sizeof(struct can_filter) * rules->rules_capacity);
77*de1e4e89SAndroid Build Coastguard Worker } else {
78*de1e4e89SAndroid Build Coastguard Worker return -2;
79*de1e4e89SAndroid Build Coastguard Worker }
80*de1e4e89SAndroid Build Coastguard Worker }
81*de1e4e89SAndroid Build Coastguard Worker
82*de1e4e89SAndroid Build Coastguard Worker rules->rules_raw[rules->rules_cnt].can_id =
83*de1e4e89SAndroid Build Coastguard Worker can_id | ((iseff) ? CAN_EFF_FLAG : 0);
84*de1e4e89SAndroid Build Coastguard Worker rules->rules_raw[rules->rules_cnt].can_mask =
85*de1e4e89SAndroid Build Coastguard Worker can_mask | CAN_EFF_FLAG;
86*de1e4e89SAndroid Build Coastguard Worker
87*de1e4e89SAndroid Build Coastguard Worker rules->rules_cnt++;
88*de1e4e89SAndroid Build Coastguard Worker
89*de1e4e89SAndroid Build Coastguard Worker return 0;
90*de1e4e89SAndroid Build Coastguard Worker }
91*de1e4e89SAndroid Build Coastguard Worker
canid_parse_eopt(struct nlmsghdr * n,struct tcf_ematch_hdr * hdr,struct bstr * args)92*de1e4e89SAndroid Build Coastguard Worker static int canid_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
93*de1e4e89SAndroid Build Coastguard Worker struct bstr *args)
94*de1e4e89SAndroid Build Coastguard Worker {
95*de1e4e89SAndroid Build Coastguard Worker int iseff = 0;
96*de1e4e89SAndroid Build Coastguard Worker int ret = 0;
97*de1e4e89SAndroid Build Coastguard Worker struct rules rules = {
98*de1e4e89SAndroid Build Coastguard Worker .rules_capacity = 25, /* Denominator of EM_CANID_RULES_MAX
99*de1e4e89SAndroid Build Coastguard Worker Will be multiplied by 2 to calculate the size for realloc() */
100*de1e4e89SAndroid Build Coastguard Worker .rules_cnt = 0
101*de1e4e89SAndroid Build Coastguard Worker };
102*de1e4e89SAndroid Build Coastguard Worker
103*de1e4e89SAndroid Build Coastguard Worker #define PARSE_ERR(CARG, FMT, ARGS...) \
104*de1e4e89SAndroid Build Coastguard Worker em_parse_error(EINVAL, args, CARG, &canid_ematch_util, FMT, ##ARGS)
105*de1e4e89SAndroid Build Coastguard Worker
106*de1e4e89SAndroid Build Coastguard Worker if (args == NULL)
107*de1e4e89SAndroid Build Coastguard Worker return PARSE_ERR(args, "canid: missing arguments");
108*de1e4e89SAndroid Build Coastguard Worker
109*de1e4e89SAndroid Build Coastguard Worker rules.rules_raw = calloc(rules.rules_capacity,
110*de1e4e89SAndroid Build Coastguard Worker sizeof(struct can_filter));
111*de1e4e89SAndroid Build Coastguard Worker
112*de1e4e89SAndroid Build Coastguard Worker do {
113*de1e4e89SAndroid Build Coastguard Worker if (!bstrcmp(args, "sff")) {
114*de1e4e89SAndroid Build Coastguard Worker iseff = 0;
115*de1e4e89SAndroid Build Coastguard Worker } else if (!bstrcmp(args, "eff")) {
116*de1e4e89SAndroid Build Coastguard Worker iseff = 1;
117*de1e4e89SAndroid Build Coastguard Worker } else {
118*de1e4e89SAndroid Build Coastguard Worker ret = PARSE_ERR(args, "canid: invalid key");
119*de1e4e89SAndroid Build Coastguard Worker goto exit;
120*de1e4e89SAndroid Build Coastguard Worker }
121*de1e4e89SAndroid Build Coastguard Worker
122*de1e4e89SAndroid Build Coastguard Worker args = bstr_next(args);
123*de1e4e89SAndroid Build Coastguard Worker if (args == NULL) {
124*de1e4e89SAndroid Build Coastguard Worker ret = PARSE_ERR(args, "canid: missing argument");
125*de1e4e89SAndroid Build Coastguard Worker goto exit;
126*de1e4e89SAndroid Build Coastguard Worker }
127*de1e4e89SAndroid Build Coastguard Worker
128*de1e4e89SAndroid Build Coastguard Worker ret = canid_parse_rule(&rules, args, iseff);
129*de1e4e89SAndroid Build Coastguard Worker if (ret == -1) {
130*de1e4e89SAndroid Build Coastguard Worker ret = PARSE_ERR(args, "canid: Improperly formed CAN ID & mask\n");
131*de1e4e89SAndroid Build Coastguard Worker goto exit;
132*de1e4e89SAndroid Build Coastguard Worker } else if (ret == -2) {
133*de1e4e89SAndroid Build Coastguard Worker ret = PARSE_ERR(args, "canid: Too many arguments on input\n");
134*de1e4e89SAndroid Build Coastguard Worker goto exit;
135*de1e4e89SAndroid Build Coastguard Worker }
136*de1e4e89SAndroid Build Coastguard Worker } while ((args = bstr_next(args)) != NULL);
137*de1e4e89SAndroid Build Coastguard Worker
138*de1e4e89SAndroid Build Coastguard Worker addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
139*de1e4e89SAndroid Build Coastguard Worker addraw_l(n, MAX_MSG, rules.rules_raw,
140*de1e4e89SAndroid Build Coastguard Worker sizeof(struct can_filter) * rules.rules_cnt);
141*de1e4e89SAndroid Build Coastguard Worker
142*de1e4e89SAndroid Build Coastguard Worker #undef PARSE_ERR
143*de1e4e89SAndroid Build Coastguard Worker exit:
144*de1e4e89SAndroid Build Coastguard Worker free(rules.rules_raw);
145*de1e4e89SAndroid Build Coastguard Worker return ret;
146*de1e4e89SAndroid Build Coastguard Worker }
147*de1e4e89SAndroid Build Coastguard Worker
canid_print_eopt(FILE * fd,struct tcf_ematch_hdr * hdr,void * data,int data_len)148*de1e4e89SAndroid Build Coastguard Worker static int canid_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
149*de1e4e89SAndroid Build Coastguard Worker int data_len)
150*de1e4e89SAndroid Build Coastguard Worker {
151*de1e4e89SAndroid Build Coastguard Worker struct can_filter *conf = data; /* Array with rules */
152*de1e4e89SAndroid Build Coastguard Worker int rules_count;
153*de1e4e89SAndroid Build Coastguard Worker int i;
154*de1e4e89SAndroid Build Coastguard Worker
155*de1e4e89SAndroid Build Coastguard Worker rules_count = data_len / sizeof(struct can_filter);
156*de1e4e89SAndroid Build Coastguard Worker
157*de1e4e89SAndroid Build Coastguard Worker for (i = 0; i < rules_count; i++) {
158*de1e4e89SAndroid Build Coastguard Worker struct can_filter *pcfltr = &conf[i];
159*de1e4e89SAndroid Build Coastguard Worker
160*de1e4e89SAndroid Build Coastguard Worker if (pcfltr->can_id & CAN_EFF_FLAG) {
161*de1e4e89SAndroid Build Coastguard Worker if (pcfltr->can_mask == (CAN_EFF_FLAG | CAN_EFF_MASK))
162*de1e4e89SAndroid Build Coastguard Worker fprintf(fd, "eff 0x%"PRIX32,
163*de1e4e89SAndroid Build Coastguard Worker pcfltr->can_id & CAN_EFF_MASK);
164*de1e4e89SAndroid Build Coastguard Worker else
165*de1e4e89SAndroid Build Coastguard Worker fprintf(fd, "eff 0x%"PRIX32":0x%"PRIX32,
166*de1e4e89SAndroid Build Coastguard Worker pcfltr->can_id & CAN_EFF_MASK,
167*de1e4e89SAndroid Build Coastguard Worker pcfltr->can_mask & CAN_EFF_MASK);
168*de1e4e89SAndroid Build Coastguard Worker } else {
169*de1e4e89SAndroid Build Coastguard Worker if (pcfltr->can_mask == (CAN_EFF_FLAG | CAN_SFF_MASK))
170*de1e4e89SAndroid Build Coastguard Worker fprintf(fd, "sff 0x%"PRIX32,
171*de1e4e89SAndroid Build Coastguard Worker pcfltr->can_id & CAN_SFF_MASK);
172*de1e4e89SAndroid Build Coastguard Worker else
173*de1e4e89SAndroid Build Coastguard Worker fprintf(fd, "sff 0x%"PRIX32":0x%"PRIX32,
174*de1e4e89SAndroid Build Coastguard Worker pcfltr->can_id & CAN_SFF_MASK,
175*de1e4e89SAndroid Build Coastguard Worker pcfltr->can_mask & CAN_SFF_MASK);
176*de1e4e89SAndroid Build Coastguard Worker }
177*de1e4e89SAndroid Build Coastguard Worker
178*de1e4e89SAndroid Build Coastguard Worker if ((i + 1) < rules_count)
179*de1e4e89SAndroid Build Coastguard Worker fprintf(fd, " ");
180*de1e4e89SAndroid Build Coastguard Worker }
181*de1e4e89SAndroid Build Coastguard Worker
182*de1e4e89SAndroid Build Coastguard Worker return 0;
183*de1e4e89SAndroid Build Coastguard Worker }
184*de1e4e89SAndroid Build Coastguard Worker
185*de1e4e89SAndroid Build Coastguard Worker struct ematch_util canid_ematch_util = {
186*de1e4e89SAndroid Build Coastguard Worker .kind = "canid",
187*de1e4e89SAndroid Build Coastguard Worker .kind_num = TCF_EM_CANID,
188*de1e4e89SAndroid Build Coastguard Worker .parse_eopt = canid_parse_eopt,
189*de1e4e89SAndroid Build Coastguard Worker .print_eopt = canid_print_eopt,
190*de1e4e89SAndroid Build Coastguard Worker .print_usage = canid_print_usage
191*de1e4e89SAndroid Build Coastguard Worker };
192