iproute2/tc/f_fw.c
<<
>>
Prefs
   1/*
   2 * f_fw.c               FW filter.
   3 *
   4 *              This program is free software; you can redistribute 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.
   8 *
   9 * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  10 *
  11 */
  12
  13#include <stdio.h>
  14#include <stdlib.h>
  15#include <unistd.h>
  16#include <fcntl.h>
  17#include <sys/socket.h>
  18#include <netinet/in.h>
  19#include <arpa/inet.h>
  20#include <string.h>
  21#include <linux/if.h> /* IFNAMSIZ */
  22#include "utils.h"
  23#include "tc_util.h"
  24
  25static void explain(void)
  26{
  27        fprintf(stderr,
  28                "Usage: ... fw [ classid CLASSID ] [ indev DEV ] [ action ACTION_SPEC ]\n"
  29                "       CLASSID := Push matching packets to the class identified by CLASSID with format X:Y\n"
  30                "               CLASSID is parsed as hexadecimal input.\n"
  31                "       DEV := specify device for incoming device classification.\n"
  32                "       ACTION_SPEC := Apply an action on matching packets.\n"
  33                "       NOTE: handle is represented as HANDLE[/FWMASK].\n"
  34                "               FWMASK is 0xffffffff by default.\n");
  35}
  36
  37static int fw_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
  38{
  39        struct tcmsg *t = NLMSG_DATA(n);
  40        struct rtattr *tail;
  41        __u32 mask = 0;
  42        int mask_set = 0;
  43
  44        if (handle) {
  45                char *slash;
  46
  47                if ((slash = strchr(handle, '/')) != NULL)
  48                        *slash = '\0';
  49                if (get_u32(&t->tcm_handle, handle, 0)) {
  50                        fprintf(stderr, "Illegal \"handle\"\n");
  51                        return -1;
  52                }
  53                if (slash) {
  54                        if (get_u32(&mask, slash+1, 0)) {
  55                                fprintf(stderr, "Illegal \"handle\" mask\n");
  56                                return -1;
  57                        }
  58                        mask_set = 1;
  59                }
  60        }
  61
  62        if (argc == 0)
  63                return 0;
  64
  65        tail = addattr_nest(n, 4096, TCA_OPTIONS);
  66
  67        if (mask_set)
  68                addattr32(n, MAX_MSG, TCA_FW_MASK, mask);
  69
  70        while (argc > 0) {
  71                if (matches(*argv, "classid") == 0 ||
  72                    matches(*argv, "flowid") == 0) {
  73                        unsigned int handle;
  74
  75                        NEXT_ARG();
  76                        if (get_tc_classid(&handle, *argv)) {
  77                                fprintf(stderr, "Illegal \"classid\"\n");
  78                                return -1;
  79                        }
  80                        addattr_l(n, 4096, TCA_FW_CLASSID, &handle, 4);
  81                } else if (matches(*argv, "police") == 0) {
  82                        NEXT_ARG();
  83                        if (parse_police(&argc, &argv, TCA_FW_POLICE, n)) {
  84                                fprintf(stderr, "Illegal \"police\"\n");
  85                                return -1;
  86                        }
  87                        continue;
  88                } else if (matches(*argv, "action") == 0) {
  89                        NEXT_ARG();
  90                        if (parse_action(&argc, &argv, TCA_FW_ACT, n)) {
  91                                fprintf(stderr, "Illegal fw \"action\"\n");
  92                                return -1;
  93                        }
  94                        continue;
  95                } else if (strcmp(*argv, "indev") == 0) {
  96                        char d[IFNAMSIZ+1] = {};
  97
  98                        argc--;
  99                        argv++;
 100                        if (argc < 1) {
 101                                fprintf(stderr, "Illegal indev\n");
 102                                return -1;
 103                        }
 104                        strncpy(d, *argv, sizeof(d) - 1);
 105                        addattr_l(n, MAX_MSG, TCA_FW_INDEV, d, strlen(d) + 1);
 106                } else if (strcmp(*argv, "help") == 0) {
 107                        explain();
 108                        return -1;
 109                } else {
 110                        fprintf(stderr, "What is \"%s\"?\n", *argv);
 111                        explain();
 112                        return -1;
 113                }
 114                argc--; argv++;
 115        }
 116        addattr_nest_end(n, tail);
 117        return 0;
 118}
 119
 120static int fw_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
 121{
 122        struct rtattr *tb[TCA_FW_MAX+1];
 123
 124        if (opt == NULL)
 125                return 0;
 126
 127        parse_rtattr_nested(tb, TCA_FW_MAX, opt);
 128
 129        if (handle || tb[TCA_FW_MASK]) {
 130                __u32 mark = 0, mask = 0;
 131
 132                if (handle)
 133                        mark = handle;
 134                if (tb[TCA_FW_MASK] &&
 135                    (mask = rta_getattr_u32(tb[TCA_FW_MASK])) != 0xFFFFFFFF)
 136                        fprintf(f, "handle 0x%x/0x%x ", mark, mask);
 137                else
 138                        fprintf(f, "handle 0x%x ", handle);
 139        }
 140
 141        if (tb[TCA_FW_CLASSID]) {
 142                SPRINT_BUF(b1);
 143                fprintf(f, "classid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_FW_CLASSID]), b1));
 144        }
 145
 146        if (tb[TCA_FW_POLICE])
 147                tc_print_police(f, tb[TCA_FW_POLICE]);
 148        if (tb[TCA_FW_INDEV]) {
 149                struct rtattr *idev = tb[TCA_FW_INDEV];
 150
 151                fprintf(f, "input dev %s ", rta_getattr_str(idev));
 152        }
 153
 154        if (tb[TCA_FW_ACT]) {
 155                fprintf(f, "\n");
 156                tc_print_action(f, tb[TCA_FW_ACT], 0);
 157        }
 158        return 0;
 159}
 160
 161struct filter_util fw_filter_util = {
 162        .id = "fw",
 163        .parse_fopt = fw_parse_opt,
 164        .print_fopt = fw_print_opt,
 165};
 166