iproute2/tc/f_route.c
<<
>>
Prefs
   1/*
   2 * f_route.c            ROUTE 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
  22#include "utils.h"
  23#include "rt_names.h"
  24#include "tc_common.h"
  25#include "tc_util.h"
  26
  27static void explain(void)
  28{
  29        fprintf(stderr,
  30                "Usage: ... route [ from REALM | fromif TAG ] [ to REALM ]\n"
  31                "                [ classid CLASSID ] [ action ACTION_SPEC ]\n"
  32                "       ACTION_SPEC := ... look at individual actions\n"
  33                "       CLASSID := X:Y\n"
  34                "\n"
  35                "NOTE: CLASSID is parsed as hexadecimal input.\n");
  36}
  37
  38static int route_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
  39{
  40        struct tcmsg *t = NLMSG_DATA(n);
  41        struct rtattr *tail;
  42        __u32 fh = 0xFFFF8000;
  43        __u32 order = 0;
  44
  45        if (handle) {
  46                if (get_u32(&t->tcm_handle, handle, 0)) {
  47                        fprintf(stderr, "Illegal \"handle\"\n");
  48                        return -1;
  49                }
  50        }
  51
  52        if (argc == 0)
  53                return 0;
  54
  55        tail = addattr_nest(n, 4096, TCA_OPTIONS);
  56
  57        while (argc > 0) {
  58                if (matches(*argv, "to") == 0) {
  59                        __u32 id;
  60
  61                        NEXT_ARG();
  62                        if (rtnl_rtrealm_a2n(&id, *argv)) {
  63                                fprintf(stderr, "Illegal \"to\"\n");
  64                                return -1;
  65                        }
  66                        addattr_l(n, 4096, TCA_ROUTE4_TO, &id, 4);
  67                        fh &= ~0x80FF;
  68                        fh |= id&0xFF;
  69                } else if (matches(*argv, "from") == 0) {
  70                        __u32 id;
  71
  72                        NEXT_ARG();
  73                        if (rtnl_rtrealm_a2n(&id, *argv)) {
  74                                fprintf(stderr, "Illegal \"from\"\n");
  75                                return -1;
  76                        }
  77                        addattr_l(n, 4096, TCA_ROUTE4_FROM, &id, 4);
  78                        fh &= 0xFFFF;
  79                        fh |= id<<16;
  80                } else if (matches(*argv, "fromif") == 0) {
  81                        __u32 id;
  82
  83                        NEXT_ARG();
  84                        ll_init_map(&rth);
  85                        if ((id = ll_name_to_index(*argv)) <= 0) {
  86                                fprintf(stderr, "Illegal \"fromif\"\n");
  87                                return -1;
  88                        }
  89                        addattr_l(n, 4096, TCA_ROUTE4_IIF, &id, 4);
  90                        fh &= 0xFFFF;
  91                        fh |= (0x8000|id)<<16;
  92                } else if (matches(*argv, "classid") == 0 ||
  93                           strcmp(*argv, "flowid") == 0) {
  94                        unsigned int handle;
  95
  96                        NEXT_ARG();
  97                        if (get_tc_classid(&handle, *argv)) {
  98                                fprintf(stderr, "Illegal \"classid\"\n");
  99                                return -1;
 100                        }
 101                        addattr_l(n, 4096, TCA_ROUTE4_CLASSID, &handle, 4);
 102                } else if (matches(*argv, "police") == 0) {
 103                        NEXT_ARG();
 104                        if (parse_police(&argc, &argv, TCA_ROUTE4_POLICE, n)) {
 105                                fprintf(stderr, "Illegal \"police\"\n");
 106                                return -1;
 107                        }
 108                        continue;
 109                } else if (matches(*argv, "action") == 0) {
 110                        NEXT_ARG();
 111                        if (parse_action(&argc, &argv, TCA_ROUTE4_ACT, n)) {
 112                                fprintf(stderr, "Illegal \"action\"\n");
 113                                return -1;
 114                        }
 115                        continue;
 116                } else if (matches(*argv, "order") == 0) {
 117                        NEXT_ARG();
 118                        if (get_u32(&order, *argv, 0)) {
 119                                fprintf(stderr, "Illegal \"order\"\n");
 120                                return -1;
 121                        }
 122                } else if (strcmp(*argv, "help") == 0) {
 123                        explain();
 124                        return -1;
 125                } else {
 126                        fprintf(stderr, "What is \"%s\"?\n", *argv);
 127                        explain();
 128                        return -1;
 129                }
 130                argc--; argv++;
 131        }
 132        addattr_nest_end(n, tail);
 133        if (order) {
 134                fh &= ~0x7F00;
 135                fh |= (order<<8)&0x7F00;
 136        }
 137        if (!t->tcm_handle)
 138                t->tcm_handle = fh;
 139        return 0;
 140}
 141
 142static int route_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
 143{
 144        struct rtattr *tb[TCA_ROUTE4_MAX+1];
 145
 146        SPRINT_BUF(b1);
 147
 148        if (opt == NULL)
 149                return 0;
 150
 151        parse_rtattr_nested(tb, TCA_ROUTE4_MAX, opt);
 152
 153        if (handle)
 154                fprintf(f, "fh 0x%08x ", handle);
 155        if (handle&0x7F00)
 156                fprintf(f, "order %d ", (handle>>8)&0x7F);
 157
 158        if (tb[TCA_ROUTE4_CLASSID]) {
 159                SPRINT_BUF(b1);
 160                fprintf(f, "flowid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_ROUTE4_CLASSID]), b1));
 161        }
 162        if (tb[TCA_ROUTE4_TO])
 163                fprintf(f, "to %s ", rtnl_rtrealm_n2a(rta_getattr_u32(tb[TCA_ROUTE4_TO]), b1, sizeof(b1)));
 164        if (tb[TCA_ROUTE4_FROM])
 165                fprintf(f, "from %s ", rtnl_rtrealm_n2a(rta_getattr_u32(tb[TCA_ROUTE4_FROM]), b1, sizeof(b1)));
 166        if (tb[TCA_ROUTE4_IIF])
 167                fprintf(f, "fromif %s", ll_index_to_name(rta_getattr_u32(tb[TCA_ROUTE4_IIF])));
 168        if (tb[TCA_ROUTE4_POLICE])
 169                tc_print_police(f, tb[TCA_ROUTE4_POLICE]);
 170        if (tb[TCA_ROUTE4_ACT])
 171                tc_print_action(f, tb[TCA_ROUTE4_ACT], 0);
 172        return 0;
 173}
 174
 175struct filter_util route_filter_util = {
 176        .id = "route",
 177        .parse_fopt = route_parse_opt,
 178        .print_fopt = route_print_opt,
 179};
 180