iproute2/tc/f_tcindex.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 * f_tcindex.c          Traffic control index filter
   4 *
   5 * Written 1998,1999 by Werner Almesberger
   6 */
   7
   8#include <stdio.h>
   9#include <stdlib.h>
  10#include <unistd.h>
  11#include <fcntl.h>
  12#include <string.h>
  13#include <netinet/in.h>
  14
  15#include "utils.h"
  16#include "tc_util.h"
  17
  18static void explain(void)
  19{
  20        fprintf(stderr,
  21                " Usage: ... tcindex    [ hash SIZE ] [ mask MASK ] [ shift SHIFT ]\n"
  22                "                       [ pass_on | fall_through ]\n"
  23                "                       [ classid CLASSID ] [ action ACTION_SPEC ]\n");
  24}
  25
  26static int tcindex_parse_opt(struct filter_util *qu, char *handle, int argc,
  27                             char **argv, struct nlmsghdr *n)
  28{
  29        struct tcmsg *t = NLMSG_DATA(n);
  30        struct rtattr *tail;
  31        char *end;
  32
  33        if (handle) {
  34                t->tcm_handle = strtoul(handle, &end, 0);
  35                if (*end) {
  36                        fprintf(stderr, "Illegal filter ID\n");
  37                        return -1;
  38                }
  39        }
  40        if (!argc) return 0;
  41        tail = addattr_nest(n, 4096, TCA_OPTIONS);
  42        while (argc) {
  43                if (!strcmp(*argv, "hash")) {
  44                        int hash;
  45
  46                        NEXT_ARG();
  47                        hash = strtoul(*argv, &end, 0);
  48                        if (*end || !hash || hash > 0x10000) {
  49                                explain();
  50                                return -1;
  51                        }
  52                        addattr_l(n, 4096, TCA_TCINDEX_HASH, &hash,
  53                                  sizeof(hash));
  54                } else if (!strcmp(*argv,"mask")) {
  55                        __u16 mask;
  56
  57                        NEXT_ARG();
  58                        mask = strtoul(*argv, &end, 0);
  59                        if (*end) {
  60                                explain();
  61                                return -1;
  62                        }
  63                        addattr_l(n, 4096, TCA_TCINDEX_MASK, &mask,
  64                                  sizeof(mask));
  65                } else if (!strcmp(*argv,"shift")) {
  66                        int shift;
  67
  68                        NEXT_ARG();
  69                        shift = strtoul(*argv, &end, 0);
  70                        if (*end) {
  71                                explain();
  72                                return -1;
  73                        }
  74                        addattr_l(n, 4096, TCA_TCINDEX_SHIFT, &shift,
  75                            sizeof(shift));
  76                } else if (!strcmp(*argv,"fall_through")) {
  77                        int value = 1;
  78
  79                        addattr_l(n, 4096, TCA_TCINDEX_FALL_THROUGH, &value,
  80                            sizeof(value));
  81                } else if (!strcmp(*argv,"pass_on")) {
  82                        int value = 0;
  83
  84                        addattr_l(n, 4096, TCA_TCINDEX_FALL_THROUGH, &value,
  85                            sizeof(value));
  86                } else if (!strcmp(*argv,"classid")) {
  87                        __u32 handle;
  88
  89                        NEXT_ARG();
  90                        if (get_tc_classid(&handle, *argv)) {
  91                                fprintf(stderr, "Illegal \"classid\"\n");
  92                                return -1;
  93                        }
  94                        addattr_l(n, 4096, TCA_TCINDEX_CLASSID, &handle, 4);
  95                } else if (!strcmp(*argv,"police")) {
  96                        NEXT_ARG();
  97                        if (parse_police(&argc, &argv, TCA_TCINDEX_POLICE, n)) {
  98                                fprintf(stderr, "Illegal \"police\"\n");
  99                                return -1;
 100                        }
 101                        continue;
 102                } else if (!strcmp(*argv,"action")) {
 103                        NEXT_ARG();
 104                        if (parse_action(&argc, &argv, TCA_TCINDEX_ACT, n)) {
 105                                fprintf(stderr, "Illegal \"action\"\n");
 106                                return -1;
 107                        }
 108                        continue;
 109                } else {
 110                        explain();
 111                        return -1;
 112                }
 113                argc--;
 114                argv++;
 115        }
 116        addattr_nest_end(n, tail);
 117        return 0;
 118}
 119
 120
 121static int tcindex_print_opt(struct filter_util *qu, FILE *f,
 122                             struct rtattr *opt, __u32 handle)
 123{
 124        struct rtattr *tb[TCA_TCINDEX_MAX+1];
 125
 126        if (opt == NULL)
 127                return 0;
 128
 129        parse_rtattr_nested(tb, TCA_TCINDEX_MAX, opt);
 130
 131        if (handle != ~0) fprintf(f, "handle 0x%04x ", handle);
 132        if (tb[TCA_TCINDEX_HASH]) {
 133                __u16 hash;
 134
 135                if (RTA_PAYLOAD(tb[TCA_TCINDEX_HASH]) < sizeof(hash))
 136                        return -1;
 137                hash = rta_getattr_u16(tb[TCA_TCINDEX_HASH]);
 138                fprintf(f, "hash %d ", hash);
 139        }
 140        if (tb[TCA_TCINDEX_MASK]) {
 141                __u16 mask;
 142
 143                if (RTA_PAYLOAD(tb[TCA_TCINDEX_MASK]) < sizeof(mask))
 144                        return -1;
 145                mask = rta_getattr_u16(tb[TCA_TCINDEX_MASK]);
 146                fprintf(f, "mask 0x%04x ", mask);
 147        }
 148        if (tb[TCA_TCINDEX_SHIFT]) {
 149                int shift;
 150
 151                if (RTA_PAYLOAD(tb[TCA_TCINDEX_SHIFT]) < sizeof(shift))
 152                        return -1;
 153                shift = rta_getattr_u32(tb[TCA_TCINDEX_SHIFT]);
 154                fprintf(f, "shift %d ", shift);
 155        }
 156        if (tb[TCA_TCINDEX_FALL_THROUGH]) {
 157                int fall_through;
 158
 159                if (RTA_PAYLOAD(tb[TCA_TCINDEX_FALL_THROUGH]) <
 160                    sizeof(fall_through))
 161                        return -1;
 162                fall_through = rta_getattr_u32(tb[TCA_TCINDEX_FALL_THROUGH]);
 163                fprintf(f, fall_through ? "fall_through " : "pass_on ");
 164        }
 165        if (tb[TCA_TCINDEX_CLASSID]) {
 166                SPRINT_BUF(b1);
 167                fprintf(f, "classid %s ", sprint_tc_classid(*(__u32 *)
 168                    RTA_DATA(tb[TCA_TCINDEX_CLASSID]), b1));
 169        }
 170        if (tb[TCA_TCINDEX_POLICE]) {
 171                fprintf(f, "\n");
 172                tc_print_police(f, tb[TCA_TCINDEX_POLICE]);
 173        }
 174        if (tb[TCA_TCINDEX_ACT]) {
 175                fprintf(f, "\n");
 176                tc_print_action(f, tb[TCA_TCINDEX_ACT], 0);
 177        }
 178        return 0;
 179}
 180
 181struct filter_util tcindex_filter_util = {
 182        .id = "tcindex",
 183        .parse_fopt = tcindex_parse_opt,
 184        .print_fopt = tcindex_print_opt,
 185};
 186