1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* 2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * m_action.c Action Management 3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This program is free software; you can distribute it and/or 5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * modify it under the terms of the GNU General Public License 6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * as published by the Free Software Foundation; either version 7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 2 of the License, or (at your option) any later version. 8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors: J Hadi Salim (hadi@cyberus.ca) 10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * TODO: 12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * - parse to be passed a filedescriptor for logging purposes 13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat*/ 15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h> 17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h> 18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h> 19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h> 20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h> 21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h> 22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h> 23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h> 24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h> 25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <dlfcn.h> 26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h" 28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_common.h" 29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_util.h" 30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic struct action_util * action_list; 32c5b66ed439aab1843d40a629347852359ba2ae70San Mehat 33c5b66ed439aab1843d40a629347852359ba2ae70San Mehat#ifdef ANDROID 34c5b66ed439aab1843d40a629347852359ba2ae70San Mehatextern struct action_util mirred_action_util; 35c5b66ed439aab1843d40a629347852359ba2ae70San Mehat#endif 36c5b66ed439aab1843d40a629347852359ba2ae70San Mehat 37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifdef CONFIG_GACT 38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint gact_ld = 0 ; //fuckin backward compatibility 39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif 40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint batch_c = 0; 41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint tab_flush = 0; 42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid act_usage(void) 44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /*XXX: In the near future add a action->print_help to improve 46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * usability 47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * This would mean new tc will not be backward compatible 48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * with any action .so from the old days. But if someone really 49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * does that, they would know how to fix this .. 50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * 51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */ 52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf (stderr, "usage: tc actions <ACTSPECOP>*\n"); 53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, 54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "Where: \tACTSPECOP := ACR | GD | FL\n" 55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tACR := add | change | replace <ACTSPEC>* \n" 56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tGD := get | delete | <ACTISPEC>*\n" 57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tFL := ls | list | flush | <ACTNAMESPEC>\n" 58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tACTNAMESPEC := action <ACTNAME>\n" 59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tACTISPEC := <ACTNAMESPEC> <INDEXSPEC>\n" 60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tACTSPEC := action <ACTDETAIL> [INDEXSPEC]\n" 61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tINDEXSPEC := index <32 bit indexvalue>\n" 62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\tACTDETAIL := <ACTNAME> <ACTPARAMS>\n" 63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\t\tExample ACTNAME is gact, mirred etc\n" 64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\t\tEach action has its own parameters (ACTPARAMS)\n" 65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat "\n"); 66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat exit(-1); 68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int print_noaopt(struct action_util *au, FILE *f, struct rtattr *opt) 71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (opt && RTA_PAYLOAD(opt)) 73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "[Unknown action, optlen=%u] ", 74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (unsigned) RTA_PAYLOAD(opt)); 75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic int parse_noaopt(struct action_util *au, int *argc_p, char ***argv_p, int code, struct nlmsghdr *n) 79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int argc = *argc_p; 81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char **argv = *argv_p; 82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc) { 84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Unknown action \"%s\", hence option \"%s\" is unparsable\n", au->id, *argv); 85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Unknown action \"%s\"\n", au->id); 87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstruct action_util *get_action_kind(char *str) 92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 93c5b66ed439aab1843d40a629347852359ba2ae70San Mehat#ifdef ANDROID 94c5b66ed439aab1843d40a629347852359ba2ae70San Mehat if (!strcmp(str, "mirred")) { 95c5b66ed439aab1843d40a629347852359ba2ae70San Mehat return &mirred_action_util; 96c5b66ed439aab1843d40a629347852359ba2ae70San Mehat } else { 97c5b66ed439aab1843d40a629347852359ba2ae70San Mehat fprintf(stderr, "Android does not support action '%s'", str); 98c5b66ed439aab1843d40a629347852359ba2ae70San Mehat return NULL; 99c5b66ed439aab1843d40a629347852359ba2ae70San Mehat } 100c5b66ed439aab1843d40a629347852359ba2ae70San Mehat#endif 101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat static void *aBODY; 102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *dlh; 103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[256]; 104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct action_util *a; 105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifdef CONFIG_GACT 106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int looked4gact = 0; 107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatrestart_s: 108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif 109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (a = action_list; a; a = a->next) { 110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(a->id, str) == 0) 111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return a; 112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 1141a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt snprintf(buf, sizeof(buf), "%s/m_%s.so", get_tc_lib(), str); 1151a441f49ec87ef74b978d7ae17da2a9b2ca6e811Dmitry Shmidt dlh = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL); 116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (dlh == NULL) { 117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat dlh = aBODY; 118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (dlh == NULL) { 119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat dlh = aBODY = dlopen(NULL, RTLD_LAZY); 120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (dlh == NULL) 121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto noexist; 122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat snprintf(buf, sizeof(buf), "%s_action_util", str); 126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = dlsym(dlh, buf); 127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a == NULL) 128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto noexist; 129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatreg: 131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a->next = action_list; 132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat action_list = a; 133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return a; 134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatnoexist: 136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifdef CONFIG_GACT 137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!looked4gact) { 138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat looked4gact = 1; 139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strcpy(str,"gact"); 140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto restart_s; 141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif 143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = malloc(sizeof(*a)); 144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (a) { 145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(a, 0, sizeof(*a)); 146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strncpy(a->id, "noact", 15); 147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a->parse_aopt = parse_noaopt; 148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a->print_aopt = print_noaopt; 149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto reg; 150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return a; 152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint 155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatnew_cmd(char **argv) 156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if ((matches(*argv, "change") == 0) || 158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (matches(*argv, "replace") == 0)|| 159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (matches(*argv, "delete") == 0)|| 160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat (matches(*argv, "add") == 0)) 161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 1; 162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint 168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatparse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) 169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int argc = *argc_p; 171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char **argv = *argv_p; 172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tail, *tail2; 173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char k[16]; 174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ok = 0; 175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int eap = 0; /* expect action parameters */ 176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ret = 0; 178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int prio = 0; 179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc <= 0) 181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail = tail2 = NLMSG_TAIL(n); 184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, MAX_MSG, tca_id, NULL, 0); 186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (argc > 0) { 188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(k, 0, sizeof (k)); 190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "action") == 0 ) { 192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc--; 193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv++; 194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat eap = 1; 195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifdef CONFIG_GACT 196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!gact_ld) { 197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat get_action_kind("gact"); 198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif 200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "help") == 0) { 202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (new_cmd(argv)) { 204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto done0; 205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct action_util *a = NULL; 207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strncpy(k, *argv, sizeof (k) - 1); 208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat eap = 0; 209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc > 0 ) { 210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = get_action_kind(k); 211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatdone0: 213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (ok) 214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat break; 215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat else 216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto done; 217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NULL == a) { 220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail = NLMSG_TAIL(n); 224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, MAX_MSG, ++prio, NULL, 0); 225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1); 226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = a->parse_aopt(a,&argc, &argv, TCA_ACT_OPTIONS, n); 228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (ret < 0) { 230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"bad action parsing\n"); 231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; 234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ok++; 235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (eap > 0) { 240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"bad action empty %d\n",eap); 241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail2->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail2; 245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatdone: 247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *argc_p = argc; 248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *argv_p = argv; 249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatbad_val: 251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat /* no need to undo things, returning from here should 252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * cause enough pain */ 253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "parse_action: bad value (%d:%s)!\n",argc,*argv); 254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint 258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehattc_print_one_action(FILE * f, struct rtattr *arg) 259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tb[TCA_ACT_MAX + 1]; 262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int err = 0; 263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct action_util *a = NULL; 264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (arg == NULL) 266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat parse_rtattr_nested(tb, TCA_ACT_MAX, arg); 269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[TCA_ACT_KIND] == NULL) { 270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "NULL Action!\n"); 271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = get_action_kind(RTA_DATA(tb[TCA_ACT_KIND])); 276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NULL == a) 277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tab_flush) { 280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f," %s \n", a->id); 281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tab_flush = 0; 282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat err = a->print_aopt(a,f,tb[TCA_ACT_OPTIONS]); 286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (0 > err) 289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return err; 290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (show_stats && tb[TCA_ACT_STATS]) { 292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "\tAction statistics:\n"); 293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL); 294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "\n"); 295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint 301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehattc_print_action(FILE * f, const struct rtattr *arg) 302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int i; 305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tb[TCA_ACT_MAX_PRIO + 1]; 306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (arg == NULL) 308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat parse_rtattr_nested(tb, TCA_ACT_MAX_PRIO, arg); 311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tab_flush && NULL != tb[0] && NULL == tb[1]) { 313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ret = tc_print_one_action(f, tb[0]); 314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return ret; 315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat for (i = 0; i < TCA_ACT_MAX_PRIO; i++) { 318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (tb[i]) { 319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "\n\taction order %d: ", i + batch_c); 320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (0 > tc_print_one_action(f, tb[i])) { 321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(f, "Error printing action\n"); 322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat batch_c+=TCA_ACT_MAX_PRIO ; 328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint print_action(const struct sockaddr_nl *who, 332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *n, 333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat void *arg) 334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat FILE *fp = (FILE*)arg; 336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcamsg *t = NLMSG_DATA(n); 337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int len = n->nlmsg_len; 338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr * tb[TCAA_MAX+1]; 339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat len -= NLMSG_LENGTH(sizeof(*t)); 341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (len < 0) { 343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Wrong len %d\n", len); 344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat parse_rtattr(tb, TCAA_MAX, TA_RTA(t), len); 348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NULL == tb[TCA_ACT_TAB]) { 350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (n->nlmsg_type != RTM_GETACTION) 351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "print_action: NULL kind\n"); 352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (n->nlmsg_type == RTM_DELACTION) { 356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (n->nlmsg_flags & NLM_F_ROOT) { 357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fp, "Flushed table "); 358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tab_flush = 1; 359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fp, "deleted action "); 361dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 362dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 363dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 364dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (n->nlmsg_type == RTM_NEWACTION) 365dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(fp, "Added action "); 366dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tc_print_action(fp, tb[TCA_ACT_TAB]); 367dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 368dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 369dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 370dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 371dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint tc_action_gd(int cmd, unsigned flags, int *argc_p, char ***argv_p) 372dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 373dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char k[16]; 374dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct action_util *a = NULL; 375dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int argc = *argc_p; 376dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char **argv = *argv_p; 377dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int prio = 0; 378dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ret = 0; 379dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat __u32 i; 380dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct sockaddr_nl nladdr; 381dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tail; 382dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tail2; 383dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr *ans = NULL; 384dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 385dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct { 386dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr n; 387dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcamsg t; 388dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[MAX_MSG]; 389dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } req; 390dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 391dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.t.tca_family = AF_UNSPEC; 392dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 393dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&req, 0, sizeof(req)); 394dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 395dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&nladdr, 0, sizeof(nladdr)); 396dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat nladdr.nl_family = AF_NETLINK; 397dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 398dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)); 399dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_flags = NLM_F_REQUEST|flags; 400dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_type = cmd; 401dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc -=1; 402dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv +=1; 403dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 404dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 405dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail = NLMSG_TAIL(&req.n); 406dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(&req.n, MAX_MSG, TCA_ACT_TAB, NULL, 0); 407dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 408dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (argc > 0) { 409dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(*argv, "action") == 0 ) { 410dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc--; 411dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv++; 412dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat continue; 413dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (strcmp(*argv, "help") == 0) { 414dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 415dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 416dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 417dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strncpy(k, *argv, sizeof (k) - 1); 418dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = get_action_kind(k); 419dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NULL == a) { 420dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Error: non existent action: %s\n",k); 421dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = -1; 422dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 423dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 424dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(a->id, k) != 0) { 425dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Error: non existent action: %s\n",k); 426dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = -1; 427dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 428dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 429dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 430dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc -=1; 431dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv +=1; 432dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc <= 0) { 433dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Error: no index specified action: %s\n",k); 434dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = -1; 435dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 436dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 437dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 438dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "index") == 0) { 439dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat NEXT_ARG(); 440dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (get_u32(&i, *argv, 10)) { 441dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"index\"\n"); 442dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = -1; 443dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 444dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 445dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc -=1; 446dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv +=1; 447dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 448dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Error: no index specified action: %s\n",k); 449dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = -1; 450dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 451dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 452dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 453dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail2 = NLMSG_TAIL(&req.n); 454dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(&req.n, MAX_MSG, ++prio, NULL, 0); 455dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1); 456dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr32(&req.n, MAX_MSG, TCA_ACT_INDEX, i); 457dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail2->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail2; 458dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 459dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 460dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 461dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; 462dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 463dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_seq = rth.dump = ++rth.seq; 464dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (cmd == RTM_GETACTION) 465dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ans = &req.n; 466dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 467dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_talk(&rth, &req.n, 0, 0, ans, NULL, NULL) < 0) { 468dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "We have an error talking to the kernel\n"); 469dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 1; 470dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 471dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 472dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (ans && print_action(NULL, &req.n, (void*)stdout) < 0) { 473dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Dump terminated\n"); 474dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 1; 475dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 476dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 477dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *argc_p = argc; 478dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *argv_p = argv; 479dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatbad_val: 480dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return ret; 481dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 482dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 483dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint tc_action_modify(int cmd, unsigned flags, int *argc_p, char ***argv_p) 484dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 485dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int argc = *argc_p; 486dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char **argv = *argv_p; 487dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ret = 0; 488dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 489dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tail; 490dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct { 491dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr n; 492dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcamsg t; 493dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[MAX_MSG]; 494dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } req; 495dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 496dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.t.tca_family = AF_UNSPEC; 497dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 498dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&req, 0, sizeof(req)); 499dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 500dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)); 501dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_flags = NLM_F_REQUEST|flags; 502dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_type = cmd; 503dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail = NLMSG_TAIL(&req.n); 504dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc -=1; 505dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv +=1; 506dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (parse_action(&argc, &argv, TCA_ACT_TAB, &req.n)) { 507dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Illegal \"action\"\n"); 508dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 509dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 510dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; 511dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 512dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { 513dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "We have an error talking to the kernel\n"); 514dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = -1; 515dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 516dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 517dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *argc_p = argc; 518dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *argv_p = argv; 519dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 520dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return ret; 521dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 522dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 523dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint tc_act_list_or_flush(int argc, char **argv, int event) 524dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 525dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ret = 0, prio = 0, msg_size = 0; 526dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char k[16]; 527dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct rtattr *tail,*tail2; 528dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct action_util *a = NULL; 529dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct { 530dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct nlmsghdr n; 531dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat struct tcamsg t; 532dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat char buf[MAX_MSG]; 533dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } req; 534dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 535dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.t.tca_family = AF_UNSPEC; 536dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 537dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat memset(&req, 0, sizeof(req)); 538dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 539dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)); 540dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 541dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail = NLMSG_TAIL(&req.n); 542dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(&req.n, MAX_MSG, TCA_ACT_TAB, NULL, 0); 543dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail2 = NLMSG_TAIL(&req.n); 544dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 545dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strncpy(k, *argv, sizeof (k) - 1); 546dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifdef CONFIG_GACT 547dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (!gact_ld) { 548dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat get_action_kind("gact"); 549dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 550dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif 551dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat a = get_action_kind(k); 552dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (NULL == a) { 553dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"bad action %s\n",k); 554dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 555dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 556dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (strcmp(a->id, k) != 0) { 557dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr,"bad action %s\n",k); 558dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat goto bad_val; 559dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 560dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat strncpy(k, *argv, sizeof (k) - 1); 561dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 562dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(&req.n, MAX_MSG, ++prio, NULL, 0); 563dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat addattr_l(&req.n, MAX_MSG, TCA_ACT_KIND, k, strlen(k) + 1); 564dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail2->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail2; 565dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; 566dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 567dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat msg_size = NLMSG_ALIGN(req.n.nlmsg_len) - NLMSG_ALIGN(sizeof(struct nlmsghdr)); 568dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 569dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (event == RTM_GETACTION) { 570dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_dump_request(&rth, event, (void *)&req.t, msg_size) < 0) { 571dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat perror("Cannot send dump request"); 572dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 1; 573dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 574dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = rtnl_dump_filter(&rth, print_action, stdout, NULL, NULL); 575dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 576dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 577dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (event == RTM_DELACTION) { 578dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len); 579dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_type = RTM_DELACTION; 580dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_flags |= NLM_F_ROOT; 581dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat req.n.nlmsg_flags |= NLM_F_REQUEST; 582dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { 583dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "We have an error flushing\n"); 584dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 1; 585dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 586dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 587dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 588dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 589dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatbad_val: 590dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 591dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return ret; 592dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 593dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 594dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint do_action(int argc, char **argv) 595dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{ 596dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 597dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat int ret = 0; 598dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 599dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat while (argc > 0) { 600dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 601dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (matches(*argv, "add") == 0) { 602dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = tc_action_modify(RTM_NEWACTION, NLM_F_EXCL|NLM_F_CREATE, &argc, &argv); 603dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "change") == 0 || 604dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat matches(*argv, "replace") == 0) { 605dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = tc_action_modify(RTM_NEWACTION, NLM_F_CREATE|NLM_F_REPLACE, &argc, &argv); 606dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "delete") == 0) { 607dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc -=1; 608dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv +=1; 609dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = tc_action_gd(RTM_DELACTION, 0, &argc, &argv); 610dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "get") == 0) { 611dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argc -=1; 612dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat argv +=1; 613dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = tc_action_gd(RTM_GETACTION, 0, &argc, &argv); 614dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 615dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat || matches(*argv, "lst") == 0) { 616dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc <= 2) { 617dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat act_usage(); 618dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 619dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 620dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return tc_act_list_or_flush(argc-2, argv+2, RTM_GETACTION); 621dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "flush") == 0) { 622dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (argc <= 2) { 623dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat act_usage(); 624dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 625dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 626dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return tc_act_list_or_flush(argc-2, argv+2, RTM_DELACTION); 627dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else if (matches(*argv, "help") == 0) { 628dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat act_usage(); 629dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 630dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } else { 631dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 632dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat ret = -1; 633dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 634dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 635dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat if (ret < 0) { 636dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat fprintf(stderr, "Command \"%s\" is unknown, try \"tc actions help\".\n", *argv); 637dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return -1; 638dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 639dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat } 640dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 641dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat return 0; 642dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} 643dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat 644