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.
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
22 #include <linux/can.h>
26 #define EM_CAN_RULES_SIZE 32
28 extern struct ematch_util can_ematch_util;
30 static void can_print_usage(FILE *fd)
33 "Usage: can(MATCH)\n" \
34 "where: MATCH = {sff CANID | eff CANID}\n" \
35 " CANID := ID:MASK\n" \
37 "Example: u32(sff 0x123 sff 0x124 sff 0x125:0xf)\n");
40 static int can_parse_rule(struct can_filter *rule, struct bstr *a, int iseff)
42 unsigned int can_id = 0;
43 unsigned int can_mask = 0;
45 if (sscanf(a->data, "%"SCNx32 ":" "%"SCNx32, &can_id, &can_mask) != 2) {
46 if (sscanf(a->data, "%"SCNx32, &can_id) != 1) {
49 can_mask = CAN_SFF_MASK;
51 rule->can_id = can_id | ((iseff) ? CAN_EFF_FLAG : 0) ;
52 rule->can_mask = can_mask;
57 static int can_parse_eopt(struct nlmsghdr *n, struct tcf_ematch_hdr *hdr,
61 struct can_filter rules_raw[EM_CAN_RULES_SIZE];
66 memset(&rules_raw, 0, sizeof(rules_raw));
68 #define PARSE_ERR(CARG, FMT, ARGS...) \
69 em_parse_error(EINVAL, args, CARG, &can_ematch_util, FMT ,##ARGS)
72 return PARSE_ERR(args, "can: missing arguments");
74 if (!bstrcmp(args, "sff"))
76 else if (!bstrcmp(args, "eff"))
79 return PARSE_ERR(args, "can: invalid key");
83 return PARSE_ERR(a, "can: missing key");
85 ret = can_parse_rule(&rules_raw[0], a, iseff);
87 return PARSE_ERR(a, "can: Improperly formed CAN ID & mask\n");
89 for (i = 1; i < (sizeof(rules_raw)/sizeof(struct can_filter)); i++) {
95 ret = can_parse_rule(&rules_raw[i], a, iseff);
97 return PARSE_ERR(a, "can: Improperly formed CAN ID & mask\n");
100 can_id = bstrtoul(a);
101 if (can_id == ULONG_MAX)
102 return PARSE_ERR(a, "can: invalid ID, must be numeric");
104 rules_raw[i].can_id = can_id | (iseff) ? CAN_EFF_FLAG : 0 ;
110 // return PARSE_ERR(a->next, "can: unexpected trailer");
112 addraw_l(n, MAX_MSG, hdr, sizeof(*hdr));
113 addraw_l(n, MAX_MSG, &rules_raw, sizeof(struct can_filter) * i); // FIXME is size ok
119 static int can_print_eopt(FILE *fd, struct tcf_ematch_hdr *hdr, void *data,
122 struct can_filter *conf = data; /* Array with rules, fixed size EM_CAN_RULES_SIZE */
125 if (data_len < sizeof(*conf)) {
126 fprintf(stderr, "U32 header size mismatch\n");
130 fprintf(fd, "%08x/%08x at %s%d",
131 (unsigned int) ntohl(u_key->val),
132 (unsigned int) ntohl(u_key->mask),
133 u_key->offmask ? "nexthdr+" : "",
140 struct ematch_util can_ematch_util = {
142 .kind_num = TCF_EM_CAN,
143 .parse_eopt = can_parse_eopt,
144 .print_eopt = can_print_eopt,
145 .print_usage = can_print_usage