/* * parse filter handle */ void parse_u32_handle(char *p, int len, unsigned handle) { if(TC_U32_HTID(handle)) APPEND_SNPRINTF(rc, p, len, "%x", TC_U32_HTID(handle)>>20); APPEND_SNPRINTF(rc, p, len, ":"); if(TC_U32_HASH(handle)) APPEND_SNPRINTF(rc, p, len, "%x", TC_U32_HASH(handle)); APPEND_SNPRINTF(rc, p, len, ":"); if(TC_U32_NODE(handle)) APPEND_SNPRINTF(rc, p, len, "%x", TC_U32_NODE(handle)); }
/* * parse filter handle */ void parse_u32_handle(char *p, int len, unsigned handle) { if(TC_U32_HTID(handle)) p += snprintf(p, len, "%x", TC_U32_HTID(handle)>>20); p += snprintf(p, len, ":"); if(TC_U32_HASH(handle)) p += snprintf(p, len, "%x", TC_U32_HASH(handle)); p += snprintf(p, len, ":"); if(TC_U32_NODE(handle)) p += snprintf(p, len, "%x", TC_U32_NODE(handle)); }
static char * sprint_u32_handle(__u32 handle, char *buf) { int bsize = SPRINT_BSIZE-1; __u32 htid = TC_U32_HTID(handle); __u32 hash = TC_U32_HASH(handle); __u32 nodeid = TC_U32_NODE(handle); char *b = buf; if (handle == 0) { snprintf(b, bsize, "none"); return b; } if (htid) { int l = snprintf(b, bsize, "%x:", htid>>20); bsize -= l; b += l; } if (nodeid|hash) { if (hash) { int l = snprintf(b, bsize, "%x", hash); bsize -= l; b += l; } if (nodeid) { int l = snprintf(b, bsize, ":%x", nodeid); bsize -= l; b += l; } } if (show_raw) snprintf(b, bsize, "[%08x] ", handle); return buf; }
static uint32_t get_u32_parse_handle(const char *cHandle) { uint32_t handle=0; if(get_u32_handle(&handle, cHandle)) { printf ("Illegal \"ht\"\n"); return -1; } if (handle && TC_U32_NODE(handle)) { printf("\"link\" must be a hash table.\n"); return -1; } return handle; }
int main(void) { struct nl_sock *sock; struct rtnl_link *link; uint32_t ht, htlink, htid, direction; char chashlink[16]=""; int err; struct nl_cache *link_cache; struct rtnl_act *act, *act2; uint32_t i; if (!(sock = nl_socket_alloc())) { printf("Unable to allocate netlink socket\n"); exit(1); } if ((err = nl_connect(sock, NETLINK_ROUTE)) < 0 ) { printf("Nu s-a putut conecta la NETLINK!\n"); nl_socket_free(sock); exit(1); } if ((err = rtnl_link_alloc_cache(sock, AF_UNSPEC, &link_cache)) < 0) { printf("Unable to allocate link cache: %s\n", nl_geterror(err)); nl_socket_free(sock); exit(1); } /* lookup interface index of eth0 */ if (!(link = rtnl_link_get_by_name(link_cache, "eth0"))) { /* error */ printf("Interface not found\n"); nl_socket_free(sock); exit(1); } err=qdisc_add_ingress(sock, link); //printf("Add main hash table\n"); /* create u32 first hash filter table * */ /* formula calcul handle: * uint32_t handle = (htid << 20) | (hash << 12) | nodeid; */ /* * Upper limit of number of hash tables: 4096 (0xFFF) * Number of hashes in a table: 256 values (0xFF) * */ /* using 256 values for hash table * each entry in hash table match a byte from IP address specified later by a hash key */ for (i = 1; i <= 0xf; i++) u32_add_ht(sock, link, 1, i, 256); /* * attach a u32 filter to the first hash * that redirects all traffic and make a hash key * from the fist byte of the IP address * */ //divisor=0x0; // unused here //handle = 0x0; // unused here //hash = 0x0; // unused here //htid = 0x0; // unused here //nodeid = 0x0; // unused here // direction = 12 -> source IP // direction = 16 -> destination IP direction = 16; /* * which hash table will use * in our case is hash table no 1 defined previous * * There are 2 posibilities to set the the hash table: * 1. Using function get_u32_handle and sent a string in * format 10: where 10 is number of the hash table * 2. Create your own value in format: 0xa00000 * */ strcpy(chashlink, "1:"); //printf("Hash Link: %s\n", chashlink); //chashlink=malloc(sizeof(char) * htlink = 0x0; // is used by get_u32_handle to return the correct value of hash table (link) if(get_u32_handle(&htlink, chashlink)) { printf ("Illegal \"link\""); nl_socket_free(sock); exit(1); } //printf ("hash link : 0x%X\n", htlink); //printf ("hash link test : %u\n", (htlink && TC_U32_NODE(htlink))); if (htlink && TC_U32_NODE(htlink)) { printf("\"link\" must be a hash table.\n"); nl_socket_free(sock); exit(1); } /* the hash mask will hit the hash table (link) no 1: in our case */ /* set the hash key mask */ //hashmask = 0xFF000000UL; // the mask that is used to match the hash in specific table, in our case for example 1:a with mean the first byte which is 10 in hash table 1 /* Here we add a hash filter which match the first byte (see the hashmask value) * of the source IP (offset 12 in the packet header) * You can use also offset 16 to match the destination IP */ /* * Also we need a filter to match our rule * This mean that we will put a 0.0.0.0/0 filter in our first rule * that match the offset 12 (source IP) * Also you can put offset 16 to match the destination IP */ u32_add_filter_on_ht_with_hashmask(sock, link, 1, 0x0, 0x0, direction, 0, 0, htlink, 0xff000000, direction, NULL, NULL); /* * For each first byte that we need to match we will create a new hash table * For example: you have those clases: 10.0.0.0/24 and 172.16.0.0/23 * For byte 10 and byte 172 will create a separate hash table that will match the second * byte from each class. * */ /* * Now we will create other filter under (ATENTION) our first hash table (link) 1: * Previous rule redirects the trafic according the hash mask to hash table (link) no 1: * Here we will match the hash tables from 1:0 to 1:ff. Under each hash table we will attach * other rules that matches next byte from IP source/destination IP and we will repeat the * previous steps. * */ act = rtnl_act_alloc(); if (!act) { printf("rtnl_act_alloc() returns %p\n", act); return -1; } rtnl_tc_set_kind(TC_CAST(act), "skbedit"); rtnl_skbedit_set_queue_mapping(act, 4); rtnl_skbedit_set_action(act, TC_ACT_PIPE); act2 = rtnl_act_alloc(); if (!act2) { printf("rtnl_act_alloc() returns %p\n", act2); return -1; } rtnl_tc_set_kind(TC_CAST(act2), "mirred"); rtnl_mirred_set_action(act2, TCA_EGRESS_REDIR); rtnl_mirred_set_policy(act2, TC_ACT_STOLEN); rtnl_mirred_set_ifindex(act2, rtnl_link_name2i(link_cache, "eth1")); // /8 check // 10.0.0.0/8 ht=get_u32_parse_handle("1:a:"); htid = (ht&0xFFFFF000); htlink=get_u32_parse_handle("2:"); u32_add_filter_on_ht_with_hashmask(sock, link, 1, 0x0a000000, 0xff000000, direction, 0, htid, htlink, 0x00ff0000, direction, act, act2); rtnl_act_put(act); nl_socket_free(sock); return 0; }
static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct { struct tc_u32_sel sel; struct tc_u32_key keys[128]; } sel; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; int sel_ok = 0; int sample_ok = 0; __u32 htid = 0; __u32 order = 0; memset(&sel, 0, sizeof(sel)); if (handle && get_u32_handle(&t->tcm_handle, handle)) { fprintf(stderr, "Illegal filter ID\n"); return -1; } if (argc == 0) return 0; tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len)); addattr_l(n, 4096, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "match") == 0) { NEXT_ARG(); if (parse_selector(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"match\"\n"); return -1; } sel_ok++; continue; } else if (matches(*argv, "offset") == 0) { NEXT_ARG(); if (parse_offset(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"offset\"\n"); return -1; } continue; } else if (matches(*argv, "hashkey") == 0) { NEXT_ARG(); if (parse_hashkey(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"hashkey\"\n"); return -1; } continue; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, 4096, TCA_U32_CLASSID, &handle, 4); sel.sel.flags |= TC_U32_TERMINAL; } else if (matches(*argv, "divisor") == 0) { unsigned divisor; NEXT_ARG(); if (get_unsigned(&divisor, *argv, 0) || divisor == 0 || divisor > 0x100) { fprintf(stderr, "Illegal \"divisor\"\n"); return -1; } addattr_l(n, 4096, TCA_U32_DIVISOR, &divisor, 4); } else if (matches(*argv, "order") == 0) { NEXT_ARG(); if (get_u32(&order, *argv, 0)) { fprintf(stderr, "Illegal \"order\"\n"); return -1; } } else if (strcmp(*argv, "link") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"link\"\n"); return -1; } if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"link\" must be a hash table.\n"); return -1; } addattr_l(n, 4096, TCA_U32_LINK, &handle, 4); } else if (strcmp(*argv, "ht") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"ht\"\n"); return -1; } if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"ht\" must be a hash table.\n"); return -1; } if (sample_ok) htid = (htid&0xFF000)|(handle&0xFFF00000); else htid = (handle&0xFFFFF000); } else if (strcmp(*argv, "sample") == 0) { __u32 hash; struct { struct tc_u32_sel sel; struct tc_u32_key keys[4]; } sel2; NEXT_ARG(); if (parse_selector(&argc, &argv, &sel2.sel)) { fprintf(stderr, "Illegal \"sample\"\n"); return -1; } if (sel2.sel.nkeys != 1) { fprintf(stderr, "\"sample\" must contain exactly ONE key.\n"); return -1; } hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask; hash ^= hash>>16; hash ^= hash>>8; htid = ((hash<<12)&0xFF000)|(htid&0xFFF00000); sample_ok = 1; continue; #ifdef TC_CONFIG_ALL } else if (matches(*argv, "police") == 0) {
static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { struct { struct tc_u32_sel sel; struct tc_u32_key keys[128]; } sel; struct tcmsg *t = NLMSG_DATA(n); struct rtattr *tail; int sel_ok = 0; int sample_ok = 0; __u32 htid = 0; __u32 order = 0; memset(&sel, 0, sizeof(sel)); //fprintf(stderr, "handle[%s]\n", handle); if (handle && get_u32_handle(&t->tcm_handle, handle)) { fprintf(stderr, "Illegal filter ID\n"); return -1; } if (argc == 0) return 0; tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (matches(*argv, "match") == 0) { NEXT_ARG(); if (parse_selector(&argc, &argv, &sel.sel, n)) { fprintf(stderr, "Illegal \"match\"\n"); return -1; } sel_ok++; continue; } else if (matches(*argv, "offset") == 0) { NEXT_ARG(); if (parse_offset(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"offset\"\n"); return -1; } continue; } else if (matches(*argv, "hashkey") == 0) { NEXT_ARG(); if (parse_hashkey(&argc, &argv, &sel.sel)) { fprintf(stderr, "Illegal \"hashkey\"\n"); return -1; } continue; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; NEXT_ARG(); if (get_tc_classid(&handle, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &handle, 4); sel.sel.flags |= TC_U32_TERMINAL; } else if (matches(*argv, "divisor") == 0) { unsigned int divisor; fprintf(stderr, "parse divisor\n"); NEXT_ARG(); if (get_unsigned(&divisor, *argv, 0) || divisor == 0 || //divisor > 0x100 || ((divisor - 1) & divisor)) {//richie1124 divisor > 0x1000 || ((divisor - 1) & divisor)) { fprintf(stderr, "Illegal \"divisor\"\n"); return -1; } addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4); } else if (matches(*argv, "order") == 0) { NEXT_ARG(); if (get_u32(&order, *argv, 0)) { fprintf(stderr, "Illegal \"order\"\n"); return -1; } } else if (strcmp(*argv, "link") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"link\"\n"); return -1; } if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"link\" must be a hash table.\n"); return -1; } addattr_l(n, MAX_MSG, TCA_U32_LINK, &handle, 4); } else if (strcmp(*argv, "ht") == 0) { unsigned handle; NEXT_ARG(); if (get_u32_handle(&handle, *argv)) { fprintf(stderr, "Illegal \"ht\"\n"); return -1; } //fprintf(stderr, "f_u32, handle[%x]\n", handle); if (handle && TC_U32_NODE(handle)) { fprintf(stderr, "\"ht\" must be a hash table.\n"); return -1; } if (sample_ok) { //htid = (htid&0xFF000)|(handle&0xFFF00000); //htid = (htid&0xFFF00)|(handle&0xFFF00000); htid = (htid&0xFFF00)|(handle&0xFFF00000);//richie1124 } else { //htid = (handle&0xFFFFF000); htid = (handle&0xFFFFFF00); //htid = (handle&0xFFFFFF00);//richie1124 } } else if (strcmp(*argv, "sample") == 0) { __u32 hash; unsigned divisor = 0x100; struct { struct tc_u32_sel sel; struct tc_u32_key keys[4]; } sel2; memset(&sel2, 0, sizeof(sel2)); NEXT_ARG(); if (parse_selector(&argc, &argv, &sel2.sel, n)) { fprintf(stderr, "Illegal \"sample\"\n"); return -1; } if (sel2.sel.nkeys != 1) { fprintf(stderr, "\"sample\" must contain exactly ONE key.\n"); return -1; } if (*argv != 0 && strcmp(*argv, "divisor") == 0) { NEXT_ARG(); if (get_unsigned(&divisor, *argv, 0) || divisor == 0 || divisor > 0x100 || ((divisor - 1) & divisor)) { fprintf(stderr, "Illegal sample \"divisor\"\n"); return -1; } NEXT_ARG(); } hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask; hash ^= hash>>16; hash ^= hash>>8; htid = ((hash%divisor)<<12)|(htid&0xFFF00000); sample_ok = 1; continue; } else if (strcmp(*argv, "indev") == 0) {