Home | History | Annotate | Download | only in tc
      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 (at) ms2.inr.ac.ru>
     10  *
     11  */
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <unistd.h>
     16 #include <syslog.h>
     17 #include <fcntl.h>
     18 #include <sys/socket.h>
     19 #include <netinet/in.h>
     20 #include <arpa/inet.h>
     21 #include <string.h>
     22 
     23 #include "utils.h"
     24 #include "rt_names.h"
     25 #include "tc_common.h"
     26 #include "tc_util.h"
     27 
     28 static void explain(void)
     29 {
     30 	fprintf(stderr, "Usage: ... route [ from REALM | fromif TAG ] [ to REALM ]\n");
     31 	fprintf(stderr, "                [ flowid CLASSID ] [ police POLICE_SPEC ]\n");
     32 	fprintf(stderr, "       POLICE_SPEC := ... look at TBF\n");
     33 	fprintf(stderr, "       CLASSID := X:Y\n");
     34 	fprintf(stderr, "\nNOTE: CLASSID is parsed as hexadecimal input.\n");
     35 }
     36 
     37 static int route_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
     38 {
     39 	struct tc_police tp;
     40 	struct tcmsg *t = NLMSG_DATA(n);
     41 	struct rtattr *tail;
     42 	__u32 fh = 0xFFFF8000;
     43 	__u32 order = 0;
     44 
     45 	memset(&tp, 0, sizeof(tp));
     46 
     47 	if (handle) {
     48 		if (get_u32(&t->tcm_handle, handle, 0)) {
     49 			fprintf(stderr, "Illegal \"handle\"\n");
     50 			return -1;
     51 		}
     52 	}
     53 
     54 	if (argc == 0)
     55 		return 0;
     56 
     57 	tail = NLMSG_TAIL(n);
     58 	addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
     59 
     60 	while (argc > 0) {
     61 		if (matches(*argv, "to") == 0) {
     62 			__u32 id;
     63 			NEXT_ARG();
     64 			if (rtnl_rtrealm_a2n(&id, *argv)) {
     65 				fprintf(stderr, "Illegal \"to\"\n");
     66 				return -1;
     67 			}
     68 			addattr_l(n, 4096, TCA_ROUTE4_TO, &id, 4);
     69 			fh &= ~0x80FF;
     70 			fh |= id&0xFF;
     71 		} else if (matches(*argv, "from") == 0) {
     72 			__u32 id;
     73 			NEXT_ARG();
     74 			if (rtnl_rtrealm_a2n(&id, *argv)) {
     75 				fprintf(stderr, "Illegal \"from\"\n");
     76 				return -1;
     77 			}
     78 			addattr_l(n, 4096, TCA_ROUTE4_FROM, &id, 4);
     79 			fh &= 0xFFFF;
     80 			fh |= id<<16;
     81 		} else if (matches(*argv, "fromif") == 0) {
     82 			__u32 id;
     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 handle;
     95 			NEXT_ARG();
     96 			if (get_tc_classid(&handle, *argv)) {
     97 				fprintf(stderr, "Illegal \"classid\"\n");
     98 				return -1;
     99 			}
    100 			addattr_l(n, 4096, TCA_ROUTE4_CLASSID, &handle, 4);
    101 		} else if (matches(*argv, "police") == 0) {
    102 			NEXT_ARG();
    103 			if (parse_police(&argc, &argv, TCA_ROUTE4_POLICE, n)) {
    104 				fprintf(stderr, "Illegal \"police\"\n");
    105 				return -1;
    106 			}
    107 			continue;
    108 		} else if (matches(*argv, "order") == 0) {
    109 			NEXT_ARG();
    110 			if (get_u32(&order, *argv, 0)) {
    111 				fprintf(stderr, "Illegal \"order\"\n");
    112 				return -1;
    113 			}
    114 		} else if (strcmp(*argv, "help") == 0) {
    115 			explain();
    116 			return -1;
    117 		} else {
    118 			fprintf(stderr, "What is \"%s\"?\n", *argv);
    119 			explain();
    120 			return -1;
    121 		}
    122 		argc--; argv++;
    123 	}
    124 	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
    125 	if (order) {
    126 		fh &= ~0x7F00;
    127 		fh |= (order<<8)&0x7F00;
    128 	}
    129 	if (!t->tcm_handle)
    130 		t->tcm_handle = fh;
    131 	return 0;
    132 }
    133 
    134 static int route_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle)
    135 {
    136 	struct rtattr *tb[TCA_ROUTE4_MAX+1];
    137 	SPRINT_BUF(b1);
    138 
    139 	if (opt == NULL)
    140 		return 0;
    141 
    142 	parse_rtattr_nested(tb, TCA_ROUTE4_MAX, opt);
    143 
    144 	if (handle)
    145 		fprintf(f, "fh 0x%08x ", handle);
    146 	if (handle&0x7F00)
    147 		fprintf(f, "order %d ", (handle>>8)&0x7F);
    148 
    149 	if (tb[TCA_ROUTE4_CLASSID]) {
    150 		SPRINT_BUF(b1);
    151 		fprintf(f, "flowid %s ", sprint_tc_classid(*(__u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID]), b1));
    152 	}
    153 	if (tb[TCA_ROUTE4_TO])
    154 		fprintf(f, "to %s ", rtnl_rtrealm_n2a(*(__u32*)RTA_DATA(tb[TCA_ROUTE4_TO]), b1, sizeof(b1)));
    155 	if (tb[TCA_ROUTE4_FROM])
    156 		fprintf(f, "from %s ", rtnl_rtrealm_n2a(*(__u32*)RTA_DATA(tb[TCA_ROUTE4_FROM]), b1, sizeof(b1)));
    157 	if (tb[TCA_ROUTE4_IIF])
    158 		fprintf(f, "fromif %s", ll_index_to_name(*(int*)RTA_DATA(tb[TCA_ROUTE4_IIF])));
    159 	if (tb[TCA_ROUTE4_POLICE])
    160 		tc_print_police(f, tb[TCA_ROUTE4_POLICE]);
    161 	return 0;
    162 }
    163 
    164 struct filter_util route_filter_util = {
    165 	.id = "route",
    166 	.parse_fopt = route_parse_opt,
    167 	.print_fopt = route_print_opt,
    168 };
    169