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 <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 28static 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} 35 36#define usage() return(-1) 37 38static int route_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) 39{ 40 struct tc_police tp; 41 struct tcmsg *t = NLMSG_DATA(n); 42 struct rtattr *tail; 43 __u32 fh = 0xFFFF8000; 44 __u32 order = 0; 45 46 memset(&tp, 0, sizeof(tp)); 47 48 if (handle) { 49 if (get_u32(&t->tcm_handle, handle, 0)) { 50 fprintf(stderr, "Illegal \"handle\"\n"); 51 return -1; 52 } 53 } 54 55 if (argc == 0) 56 return 0; 57 58 tail = NLMSG_TAIL(n); 59 addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); 60 61 while (argc > 0) { 62 if (matches(*argv, "to") == 0) { 63 __u32 id; 64 NEXT_ARG(); 65 if (rtnl_rtrealm_a2n(&id, *argv)) { 66 fprintf(stderr, "Illegal \"to\"\n"); 67 return -1; 68 } 69 addattr_l(n, 4096, TCA_ROUTE4_TO, &id, 4); 70 fh &= ~0x80FF; 71 fh |= id&0xFF; 72 } else if (matches(*argv, "from") == 0) { 73 __u32 id; 74 NEXT_ARG(); 75 if (rtnl_rtrealm_a2n(&id, *argv)) { 76 fprintf(stderr, "Illegal \"from\"\n"); 77 return -1; 78 } 79 addattr_l(n, 4096, TCA_ROUTE4_FROM, &id, 4); 80 fh &= 0xFFFF; 81 fh |= id<<16; 82 } else if (matches(*argv, "fromif") == 0) { 83 __u32 id; 84 NEXT_ARG(); 85 ll_init_map(&rth); 86 if ((id=ll_name_to_index(*argv)) <= 0) { 87 fprintf(stderr, "Illegal \"fromif\"\n"); 88 return -1; 89 } 90 addattr_l(n, 4096, TCA_ROUTE4_IIF, &id, 4); 91 fh &= 0xFFFF; 92 fh |= (0x8000|id)<<16; 93 } else if (matches(*argv, "classid") == 0 || 94 strcmp(*argv, "flowid") == 0) { 95 unsigned handle; 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, "order") == 0) { 110 NEXT_ARG(); 111 if (get_u32(&order, *argv, 0)) { 112 fprintf(stderr, "Illegal \"order\"\n"); 113 return -1; 114 } 115 } else if (strcmp(*argv, "help") == 0) { 116 explain(); 117 return -1; 118 } else { 119 fprintf(stderr, "What is \"%s\"?\n", *argv); 120 explain(); 121 return -1; 122 } 123 argc--; argv++; 124 } 125 tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; 126 if (order) { 127 fh &= ~0x7F00; 128 fh |= (order<<8)&0x7F00; 129 } 130 if (!t->tcm_handle) 131 t->tcm_handle = fh; 132 return 0; 133} 134 135static int route_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle) 136{ 137 struct rtattr *tb[TCA_ROUTE4_MAX+1]; 138 SPRINT_BUF(b1); 139 140 if (opt == NULL) 141 return 0; 142 143 parse_rtattr_nested(tb, TCA_ROUTE4_MAX, opt); 144 145 if (handle) 146 fprintf(f, "fh 0x%08x ", handle); 147 if (handle&0x7F00) 148 fprintf(f, "order %d ", (handle>>8)&0x7F); 149 150 if (tb[TCA_ROUTE4_CLASSID]) { 151 SPRINT_BUF(b1); 152 fprintf(f, "flowid %s ", sprint_tc_classid(*(__u32*)RTA_DATA(tb[TCA_ROUTE4_CLASSID]), b1)); 153 } 154 if (tb[TCA_ROUTE4_TO]) 155 fprintf(f, "to %s ", rtnl_rtrealm_n2a(*(__u32*)RTA_DATA(tb[TCA_ROUTE4_TO]), b1, sizeof(b1))); 156 if (tb[TCA_ROUTE4_FROM]) 157 fprintf(f, "from %s ", rtnl_rtrealm_n2a(*(__u32*)RTA_DATA(tb[TCA_ROUTE4_FROM]), b1, sizeof(b1))); 158 if (tb[TCA_ROUTE4_IIF]) 159 fprintf(f, "fromif %s", ll_index_to_name(*(int*)RTA_DATA(tb[TCA_ROUTE4_IIF]))); 160 if (tb[TCA_ROUTE4_POLICE]) 161 tc_print_police(f, tb[TCA_ROUTE4_POLICE]); 162 return 0; 163} 164 165struct filter_util route_filter_util = { 166 .id = "route", 167 .parse_fopt = route_parse_opt, 168 .print_fopt = route_print_opt, 169}; 170