void show_tree_range(struct btree *btree, tuxkey_t start, unsigned count) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } __tux3_dbg("%i level btree at %Li:\n", btree->root.depth, btree->root.block); if (!has_root(btree)) return; struct cursor *cursor = alloc_cursor(btree, 0); if (!cursor) { tux3_err(btree->sb, "out of memory"); return; } if (btree_probe(cursor, start)) { tux3_fs_error(btree->sb, "tell me why!!!"); goto out; } struct buffer_head *buffer; do { buffer = cursor_leafbuf(cursor); assert((btree->ops->leaf_sniff)(btree, bufdata(buffer))); (btree->ops->leaf_dump)(btree, bufdata(buffer)); } while (--count && cursor_advance(cursor)); out: free_cursor(cursor); }
/* * Traverse btree for specified range * key: start to traverse (cursor should point leaf is including key) * len: length to traverse * * return value: * < 0 - error * 0 - traversed all range * 0 < - traverse was stopped by func, and return value of func */ int btree_traverse(struct cursor *cursor, tuxkey_t key, u64 len, btree_traverse_func_t func, void *data) { if(DEBUG_MODE_K==1) { printf("\t\t\t\t%25s[K] %25s %4d #in\n",__FILE__,__func__,__LINE__); } struct btree *btree = cursor->btree; int ret; do { tuxkey_t bottom = cursor_this_key(cursor); tuxkey_t limit = cursor_next_key(cursor); void *leaf = bufdata(cursor_leafbuf(cursor)); assert(btree->ops->leaf_sniff(btree, leaf)); if (key < bottom) { len -= min_t(u64, len, bottom - key); if (len == 0) break; key = bottom; } ret = func(btree, bottom, limit, leaf, key, len, data); /* Stop traverse if ret >= 1, or error */ if (ret) goto out; /* If next key is out of range, done */ if (key + len <= limit) break; ret = cursor_advance(cursor); if (ret < 0) goto out; } while (ret); ret = 0; out: return ret; }
int pem(struct __sk_buff *skb) { u32 ifindex_in, *ifindex_p; u8 *cursor = 0; struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); ifindex_in = skb->ingress_ifindex; ifindex_p = pem_dest.lookup(&ifindex_in); if (ifindex_p) { #if 1 if (ethernet->type == 0x0800 || ethernet->type == 0x0806) { /* accumulate stats */ u32 index = 0; u32 *value = pem_stats.lookup(&index); if (value) lock_xadd(value, 1); } #endif bpf_clone_redirect(skb, *ifindex_p, 0); } return 1; }
/*eBPF program. Filter IP and TCP packets, having payload not empty and containing "HTTP", "GET", "POST" ... as first bytes of payload if the program is loaded as PROG_TYPE_SOCKET_FILTER and attached to a socket return 0 -> DROP the packet return -1 -> KEEP the packet and return it to user space (userspace can read it from the socket_fd ) */ int http_filter(struct __sk_buff *skb) { u8 *cursor = 0; struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); //filter IP packets (ethernet type = 0x0800) if (!(ethernet->type == 0x0800)) { goto DROP; } struct ip_t *ip = cursor_advance(cursor, sizeof(*ip)); //filter TCP packets (ip next protocol = 0x06) if (ip->nextp != IP_TCP) { goto DROP; } u32 tcp_header_length = 0; u32 ip_header_length = 0; u32 payload_offset = 0; u32 payload_length = 0; struct tcp_t *tcp = cursor_advance(cursor, sizeof(*tcp)); //calculate ip header length //value to multiply * 4 //e.g. ip->hlen = 5 ; IP Header Length = 5 x 4 byte = 20 byte ip_header_length = ip->hlen << 2; //SHL 2 -> *4 multiply //calculate tcp header length //value to multiply *4 //e.g. tcp->offset = 5 ; TCP Header Length = 5 x 4 byte = 20 byte tcp_header_length = tcp->offset << 2; //SHL 2 -> *4 multiply //calculate patload offset and length payload_offset = ETH_HLEN + ip_header_length + tcp_header_length; payload_length = ip->tlen - ip_header_length - tcp_header_length; //http://stackoverflow.com/questions/25047905/http-request-minimum-size-in-bytes //minimum length of http request is always geater than 7 bytes //avoid invalid access memory //include empty payload if(payload_length < 7) { goto DROP; } //load first 7 byte of payload into p (payload_array) //direct access to skb not allowed unsigned long p[7]; int i = 0; int j = 0; const int last_index = payload_offset + 7; for (i = payload_offset ; i < last_index ; i++) { p[j] = load_byte(skb , i); j++; } //find a match with an HTTP message //HTTP if ((p[0] == 'H') && (p[1] == 'T') && (p[2] == 'T') && (p[3] == 'P')) { goto KEEP; } //GET if ((p[0] == 'G') && (p[1] == 'E') && (p[2] == 'T')) { goto KEEP; } //POST if ((p[0] == 'P') && (p[1] == 'O') && (p[2] == 'S') && (p[3] == 'T')) { goto KEEP; } //PUT if ((p[0] == 'P') && (p[1] == 'U') && (p[2] == 'T')) { goto KEEP; } //DELETE if ((p[0] == 'D') && (p[1] == 'E') && (p[2] == 'L') && (p[3] == 'E') && (p[4] == 'T') && (p[5] == 'E')) { goto KEEP; } //HEAD if ((p[0] == 'H') && (p[1] == 'E') && (p[2] == 'A') && (p[3] == 'D')) { goto KEEP; } //no HTTP match goto DROP; //keep the packet and send it to userspace retruning -1 KEEP: return -1; //drop the packet returning 0 DROP: return 0; }