+++ /dev/null
-/*
- * f_canprio.c Filter for CAN packets
- *
- * This program is free software; you can distribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * Idea: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
- * Copyright: (c) 2011 Czech Technical University in Prague
- * (c) 2011 Volkswagen Group Research
- * Authors: Michal Sojka <sojkam1@fel.cvut.cz>
- * Pavel Pisa <pisa@cmp.felk.cvut.cz>
- * Rostislav Lisovy <lisovy@kormus.cz>
- * Founded by: Volkswagen Group Research
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <linux/if.h>
-#include <limits.h>
-#include <inttypes.h>
-#include "utils.h"
-#include "tc_util.h"
-
-#ifdef CONFIG_HAVE_LINUX_CAN_H
- #include "linux/can.h"
-
-#elif !defined(CAN_EFF_FLAG)
- /* special address description flags for the CAN_ID */
- #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
- #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */
- #define CAN_ERR_FLAG 0x20000000U /* error frame */
-
- /* valid bits in CAN ID for frame formats */
- #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
- #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */
- #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */
-
- typedef __u32 canid_t;
- struct can_filter {
- canid_t can_id;
- canid_t can_mask;
- };
-#endif
-
-#define RULES_SIZE 128
-
-
-static void explain(void)
-{
- fprintf(stderr, "Usage: ... canprio [ MATCHSPEC ] [ flowid FLOWID ]\n"
- "\n"
- "Where: MATCHSPEC := { sffid FILTERID | effid FILTERID | \n"
- " MATCHSPEC ... }\n"
- " FILTERID := CANID[:MASK] \n"
- "\n"
- "NOTE: CLASSID, CANID, MASK is parsed as hexadecimal input.\n");
-}
-
-static int canprio_parse_opt(struct filter_util *qu, char *handle,
- int argc, char **argv, struct nlmsghdr *n)
-{
- struct tcmsg *t = NLMSG_DATA(n);
- struct rtattr *tail;
- struct can_filter canprio_rules[RULES_SIZE];
- int rules_count = 0;
- long h = 0;
- __u32 can_id;
- __u32 can_mask;
-
- if (argc == 0)
- return 0;
-
- if (handle) {
- h = strtol(handle, NULL, 0);
- if (h == LONG_MIN || h == LONG_MAX) {
- fprintf(stderr, "Illegal handle \"%s\", must be numeric.\n",
- handle);
- return -1;
- }
- }
-
- t->tcm_handle = h;
-
- tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
- addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
-
- while (argc > 0) {
- if (matches(*argv, "sffid") == 0) {
- /* parse SFF CAN ID optionally with mask */
- if (rules_count >= RULES_SIZE) {
- fprintf(stderr, "Too much rules on input. "
- "Maximum number of rules is: %d\n", RULES_SIZE);
- return -1;
- }
-
- NEXT_ARG();
-
- if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &can_id, &can_mask) != 2) {
- if (sscanf(*argv, "%"SCNx32, &can_id) != 1) {
- fprintf(stderr, "Improperly formed CAN ID & mask '%s'\n", *argv);
- return -1;
- } else
- can_mask = CAN_SFF_MASK;
- }
-
- /* we do not support extra handling for RTR frames due to the bitmap approach */
- if (can_id & ~CAN_SFF_MASK) {
- fprintf(stderr, "ID 0x%lx exceeded standard CAN ID range.\n",
- (unsigned long)can_id);
- return -1;
- }
-
- canprio_rules[rules_count].can_id = can_id;
- canprio_rules[rules_count].can_mask = (can_mask & CAN_SFF_MASK);
- rules_count++;
-
- } else if (matches(*argv, "effid") == 0) {
- /* parse EFF CAN ID optionally with mask */
- if (rules_count >= RULES_SIZE) {
- fprintf(stderr, "Too much rules on input. "
- "Maximum number of rules is: %d\n", RULES_SIZE);
- return -1;
- }
-
- NEXT_ARG();
-
- if (sscanf(*argv, "%"SCNx32 ":" "%"SCNx32, &can_id, &can_mask) != 2) {
- if (sscanf(*argv, "%"SCNx32, &can_id) != 1) {
- fprintf(stderr, "Improperly formed CAN ID & mask '%s'\n", *argv);
- return -1;
- } else
- can_mask = CAN_EFF_MASK;
- }
-
- if (can_id & ~CAN_EFF_MASK) {
- fprintf(stderr, "ID 0x%lx exceeded extended CAN ID range.",
- (unsigned long)can_id);
- return -1;
- }
-
- canprio_rules[rules_count].can_id = can_id | CAN_EFF_FLAG;
- canprio_rules[rules_count].can_mask = (can_mask & CAN_EFF_MASK) | CAN_EFF_FLAG;
- rules_count++;
-
- } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) {
- unsigned handle;
- NEXT_ARG();
- if (get_tc_classid(&handle, *argv)) {
- fprintf(stderr, "Illegal \"classid\"\n");
- return -1;
- }
- addattr_l(n, MAX_MSG, TCA_CANPRIO_CLASSID, &handle, 4);
-
- } else if (strcmp(*argv, "help") == 0) {
- explain();
- return -1;
-
- } else {
- fprintf(stderr, "What is \"%s\"?\n", *argv);
- explain();
- return -1;
- }
- argc--; argv++;
- }
-
- addattr_l(n, MAX_MSG, TCA_CANPRIO_RULES, &canprio_rules,
- sizeof(struct can_filter) * rules_count);
-
- tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail;
- return 0;
-}
-
-/* When "tc filter show dev XY" is executed, function canprio_walk() (in kernel)
- * is called (which calls canprio_dump() for each instance of a filter) which sends
- * information about each instance of a filters to userspace -- to this function
- * (which parses the message and prints it).
- */
-static int canprio_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
- __u32 handle)
-{
- struct rtattr *tb[TCA_CANPRIO_MAX+1];
- struct can_filter *canprio_rules = NULL;
- int rules_count = 0;
- int i;
-
- if (opt == NULL)
- return 0;
-
- parse_rtattr_nested(tb, TCA_CANPRIO_MAX, opt);
-
- if (handle)
- fprintf(f, "handle 0x%x ", handle);
-
-
- if (tb[TCA_BASIC_CLASSID]) {
- SPRINT_BUF(b1); /* allocates buffer b1 */
- fprintf(f, "flowid %s ",
- sprint_tc_classid(*(__u32*)RTA_DATA(tb[TCA_BASIC_CLASSID]), b1));
- }
-
- if (tb[TCA_CANPRIO_RULES]) {
- if (RTA_PAYLOAD(tb[TCA_CANPRIO_RULES]) < sizeof(struct can_filter))
- return -1;
-
- canprio_rules = RTA_DATA(tb[TCA_CANPRIO_RULES]);
- rules_count = (RTA_PAYLOAD(tb[TCA_CANPRIO_RULES]) / sizeof(struct can_filter));
-
- for(i = 0; i < rules_count; i++) {
- if (canprio_rules[i].can_id & CAN_EFF_FLAG) {
- if (canprio_rules[i].can_mask == (CAN_EFF_FLAG|CAN_EFF_MASK))
- fprintf(f, "effid 0x%lx ",
- (unsigned long)(canprio_rules[i].can_id & CAN_EFF_MASK));
- else
- fprintf(f, "effid 0x%lx:0x%lx ",
- (unsigned long)(canprio_rules[i].can_id & CAN_EFF_MASK),
- (unsigned long)(canprio_rules[i].can_mask & CAN_EFF_MASK));
- }
- else {
- if (canprio_rules[i].can_mask == CAN_SFF_MASK)
- fprintf(f, "sffid 0x%lx ",
- (unsigned long)(canprio_rules[i].can_id));
- else
- fprintf(f, "sffid 0x%lx:0x%lx ",
- (unsigned long)(canprio_rules[i].can_id),
- (unsigned long)(canprio_rules[i].can_mask));
- }
- }
- }
-
- return 0;
-}
-
-
-struct filter_util canprio_filter_util = {
- .id = "canprio",
- .parse_fopt = canprio_parse_opt,
- .print_fopt = canprio_print_opt,
-};
-