uint32_t match_pid_lookup(void) { FILE *fd = fopen(MATCHLIB_PID_FILE, "r"); uint32_t pid; int err; if (!fd) { MAT_LOG(ERR, "no hardware support, daemon is not listening\n"); return 0; } err = fscanf(fd, "%" SCNu32 "", &pid); if (err < 0) { MAT_LOG(ERR, "Error: pid not found\n"); return 0; } fclose(fd); return pid; }
struct net_mat_hdr_node *match_nl_get_hdr_graph(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family) { uint8_t cmd = NET_MAT_TABLE_CMD_GET_HDR_GRAPH; struct net_mat_hdr_node *hdr_nodes = NULL; struct match_msg *msg; msg = match_nl_get_msg(nsd, cmd, pid, ifindex, family); if (msg) { struct nlmsghdr *nlh = msg->msg; struct nlattr *tb[NET_MAT_MAX+1]; int err; err = genlmsg_parse(nlh, 0, tb, NET_MAT_MAX, match_get_tables_policy); if (err < 0) { MAT_LOG(ERR, "Warning: unable to parse get header graph msg\n"); goto out; } if (match_nl_table_cmd_to_type(stdout, true, NET_MAT_HEADER_GRAPH, tb)) goto out; if (tb[NET_MAT_HEADER_GRAPH]) match_get_hdrs_graph(stdout, verbose, tb[NET_MAT_HEADER_GRAPH], &hdr_nodes); } match_nl_free_msg(msg); return hdr_nodes; out: match_nl_free_msg(msg); return NULL; }
static int matchd_create_pid(void) { pid_t pid = getpid(); char buf[1024]; int err, fd; ssize_t ret; char pidfile[1024] = MATCHLIB_PID_FILE; struct flock fl = { .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = 0}; errno = 0; fd = open(pidfile, O_CLOEXEC | O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { perror("Cannot create pidfile\n"); return errno; } errno = 0; err = fcntl(fd, F_SETLKW, &fl); if (err) { perror("Error setting F_SETLKW\n"); close(fd); return errno; } errno = 0; err = ftruncate(fd, 0); if (err) { perror("ftruncate pidfile error\n"); close(fd); return errno; } snprintf(buf, sizeof(buf), "%ld\n", (long) pid); errno = 0; ret = write(fd, buf, strlen(buf)); if (ret < 0) { perror("Write pidfile error\n"); close(fd); return errno; } close(fd); return 0; } static void matchd_int_handler(int sig __unused) { MAT_LOG(DEBUG, "\nmatchd exiting...\n"); matchd_uninit(); if (remove(MATCHLIB_PID_FILE)) { MAT_LOG(ERR, "Cannot remove %s, exiting anyway\n", MATCHLIB_PID_FILE); } exit(0); }
static void matchd_usage(void) { MAT_LOG(ERR, "matchd [-b backend] [-f family_id] [-h] [-l] [-s] [-v[v]]\n"); MAT_LOG(ERR, "Options:\n"); MAT_LOG(ERR, " -b backend name of backend to load (default: %s)\n", DEFAULT_BACKEND_NAME); MAT_LOG(ERR, " -d run as a daemon\n"); MAT_LOG(ERR, " -f family_id netlink family id\n"); MAT_LOG(ERR, " -h display this help and exit\n"); MAT_LOG(ERR, " -l list available backends and exit\n"); MAT_LOG(ERR, " -s add all ports to default vlan (ies_pipeline only)\n"); MAT_LOG(ERR, " -v be verbose (enable info messages)\n"); MAT_LOG(ERR, " -vv be very verbose (enable info+debug messages)\n"); MAT_LOG(ERR, " --version display Match interface version and exit\n"); }
int main(int argc, char **argv) { struct nl_sock *nsd; int family = NET_MAT_DFLT_FAMILY; struct sockaddr_nl dest_addr; unsigned char *buf; int rc = EXIT_SUCCESS; int err, opt; const char *backend = NULL; struct switch_args sw_args; struct sigaction sig_act; int verbose = 0; int opt_index = 0; static struct option long_options[] = { { "version", no_argument, NULL, 0 }, { 0, 0, 0, 0} }; memset(&sw_args, 0, sizeof(sw_args)); while ((opt = getopt_long(argc, argv, "b:f:vhls", long_options, &opt_index)) != -1) { switch (opt) { case 0: if (!strcmp(long_options[opt_index].name, "version")) { printf("Match Version: %s\n", match_version()); exit(0); } break; case 'b': backend = optarg; break; case 'f': family = atoi(optarg); break; case 'h': matchd_usage(); exit(-1); case 'l': match_backend_list_all(); exit(0); case 's': sw_args.single_vlan = true; break; case 'v': ++verbose; break; default: matchd_usage(); exit(-1); } } if (verbose > 1) mat_setlogmask(MAT_LOG_UPTO(MAT_LOG_DEBUG)); else if (verbose > 0) mat_setlogmask(MAT_LOG_UPTO(MAT_LOG_INFO)); else mat_setlogmask(MAT_LOG_UPTO(MAT_LOG_ERR)); nsd = nl_socket_alloc(); nl_socket_set_local_port(nsd, (uint32_t)getpid()); nl_connect(nsd, NETLINK_GENERIC); if (backend == NULL) backend = DEFAULT_BACKEND_NAME; rc = matchd_init(nsd, family, backend, &sw_args); if (rc) { MAT_LOG(ERR, "Error: cannot init matchd\n"); exit(-1); } err = matchd_create_pid(); if (err) { MAT_LOG(ERR, "matchd create pid failed\n"); exit(-1); } sig_act.sa_handler = matchd_int_handler; sigaction(SIGINT, &sig_act, NULL); sigaction(SIGTERM, &sig_act, NULL); while (1) { MAT_LOG(DEBUG, "Waiting for message\n"); rc = nl_recv(nsd, &dest_addr, &buf, NULL); if(rc <= 0) { printf("%s:receive error on netlink socket:%d\n", __func__, errno); rc = EXIT_FAILURE; break; } /*printf("%s:recvfrom received %d bytes from pid %d\n", __func__, rc, dest_addr.nl_pid); */ err = matchd_rx_process((struct nlmsghdr *)buf); if (err < 0) MAT_LOG(ERR, "%s: Warning: parsing error\n", __func__); free(buf); } matchd_uninit(); nl_close(nsd); nl_socket_free(nsd); return rc; }
struct match_msg *match_nl_alloc_msg(uint8_t type, uint32_t pid, int flags, int size, int family) { struct match_msg *msg; static uint32_t seq = 0; msg = (struct match_msg *) malloc(sizeof(struct match_msg)); if (!msg) return NULL; msg->nlbuf = nlmsg_alloc(); msg->msg = genlmsg_put(msg->nlbuf, 0, seq, family, (int)size, flags, type, NET_MAT_GENL_VERSION); msg->seq = seq++; if (pid) { struct nl_msg *nl_msg = msg->nlbuf; struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK, .nl_pid = pid, .nl_groups = 0, }; nlmsg_set_dst(nl_msg, &nladdr); } return msg; } struct match_msg *match_nl_get_msg(struct nl_sock *nsd, uint8_t cmd, uint32_t pid, unsigned int ifindex, int family) { struct match_msg *msg; sigset_t bs; int err; msg = match_nl_alloc_msg(cmd, pid, NLM_F_REQUEST|NLM_F_ACK, 0, family); if (!msg) { MAT_LOG(ERR, "Error: Allocation failure\n"); return NULL; } nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER_TYPE, NET_MAT_IDENTIFIER_IFINDEX); nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER, ifindex); nl_send_auto(nsd, msg->nlbuf); match_nl_free_msg(msg); sigemptyset(&bs); sigaddset(&bs, SIGINT); sigprocmask(SIG_UNBLOCK, &bs, NULL); msg = match_nl_recv_msg(nsd, &err); sigprocmask(SIG_BLOCK, &bs, NULL); return msg; } static int match_nl_get_port(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family, uint8_t cmd, struct net_mat_port *ports, uint32_t *port_id, uint32_t *glort) { struct net_mat_port *port_query = NULL; struct match_msg *msg; sigset_t bs; int err; msg = match_nl_alloc_msg(cmd, pid, NLM_F_REQUEST|NLM_F_ACK, 0, family); if (!msg) { MAT_LOG(ERR, "Error: Allocation failure\n"); return -ENOMEM; } if (nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER_TYPE, NET_MAT_IDENTIFIER_IFINDEX) || nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER, ifindex)) { match_nl_free_msg(msg); return -EMSGSIZE; } err = match_put_ports(msg->nlbuf, ports); if (err) { match_nl_free_msg(msg); return -EMSGSIZE; } nl_send_auto(nsd, msg->nlbuf); match_nl_free_msg(msg); sigemptyset(&bs); sigaddset(&bs, SIGINT); sigprocmask(SIG_UNBLOCK, &bs, NULL); msg = match_nl_recv_msg(nsd, &err); if (msg) { struct nlmsghdr *nlh = msg->msg; struct nlattr *tb[NET_MAT_MAX+1]; int err; err = genlmsg_parse(nlh, 0, tb, NET_MAT_MAX, match_get_tables_policy); if (err < 0) { MAT_LOG(ERR, "Warning: unable to parse pci to lport msg\n"); match_nl_free_msg(msg); return -EINVAL; } if (match_nl_table_cmd_to_type(stdout, true, NET_MAT_PORTS, tb)) { match_nl_free_msg(msg); return -EINVAL; } if (tb[NET_MAT_PORTS]) { err = match_get_ports(stdout, verbose, tb[NET_MAT_PORTS], &port_query); if (err) { match_nl_free_msg(msg); return -EINVAL; } } if (!port_query) { match_nl_free_msg(msg); return -EINVAL; } if (cmd == NET_MAT_PORT_CMD_GET_LPORT) *port_id = port_query[0].port_id; else if (cmd == NET_MAT_PORT_CMD_GET_PHYS_PORT) *port_id = port_query[0].port_phys_id; if (glort) *glort = port_query[0].glort; } match_nl_free_msg(msg); free(port_query); return 0; } int match_nl_pci_lport(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family, uint8_t bus, uint8_t device, uint8_t function, uint32_t *lport, uint32_t *glort) { struct net_mat_port port = {.pci = {0}, .port_id = NET_MAT_PORT_ID_UNSPEC, .mac_addr = 0, .port_phys_id = 0}; struct net_mat_port ports[2] = {{0}, {0}}; int err; ports[0] = ports[1] = port; ports[0].pci.bus = bus; ports[0].pci.device = device; ports[0].pci.function = function; err = match_nl_get_port(nsd, pid, ifindex, family, NET_MAT_PORT_CMD_GET_LPORT, ports, lport, glort); return err; } int match_nl_mac_lport(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family, uint64_t mac, uint32_t *lport, uint32_t *glort) { struct net_mat_port port = {.pci = {0}, .port_id = NET_MAT_PORT_ID_UNSPEC, .mac_addr = 0, .port_phys_id = 0}; struct net_mat_port ports[2] = {{0}, {0}}; int err; ports[0] = ports[1] = port; ports[0].mac_addr = mac; err = match_nl_get_port(nsd, pid, ifindex, family, NET_MAT_PORT_CMD_GET_LPORT, ports, lport, glort); return err; } int match_nl_lport_to_phys_port(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family, uint32_t lport, uint32_t *phys_port, uint32_t *glort) { struct net_mat_port port = {.pci = {0}, .port_id = NET_MAT_PORT_ID_UNSPEC, .mac_addr = 0, .port_phys_id = 0}; struct net_mat_port ports[2] = {{0}, {0}}; int err; ports[0] = ports[1] = port; ports[0].port_id = lport; err = match_nl_get_port(nsd, pid, ifindex, family, NET_MAT_PORT_CMD_GET_PHYS_PORT, ports, phys_port, glort); return err; }
static void match_nl_handle_error(struct nlmsgerr *errmsg) { MAT_LOG(ERR, "Error processing request: %s\n", strerror(errmsg->error)); }
struct net_mat_port *match_nl_get_ports(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family, uint32_t min, uint32_t max) { uint8_t cmd = NET_MAT_PORT_CMD_GET_PORTS; struct nlattr *tb[NET_MAT_MAX+1]; struct net_mat_port *port = NULL; struct match_msg *msg; struct nlmsghdr *nlh; struct nlattr *ports; sigset_t bs; int err = 0; msg = match_nl_alloc_msg(cmd, pid, NLM_F_REQUEST|NLM_F_ACK, 0, family); if (!msg) { MAT_LOG(ERR, "Error: Allocation failure\n"); return NULL; } if (nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER_TYPE, NET_MAT_IDENTIFIER_IFINDEX) || nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER, ifindex)) { MAT_LOG(ERR, "Error: Identifier put failed\n"); goto out; } err = match_put_rule_error(msg->nlbuf, NET_MAT_RULES_ERROR_CONT_LOG); if (err) goto out; ports = nla_nest_start(msg->nlbuf, NET_MAT_PORTS); if (!ports) { MAT_LOG(ERR, "Error: get_port attributes failed\n"); goto out; } if (min) { err = nla_put_u32(msg->nlbuf, NET_MAT_PORT_MIN_INDEX, min); if (err) goto out; } if (max) { err = nla_put_u32(msg->nlbuf, NET_MAT_PORT_MAX_INDEX, max); if (err) goto out; } nla_nest_end(msg->nlbuf, ports); nl_send_auto(nsd, msg->nlbuf); match_nl_free_msg(msg); /* message sent handle recv */ sigemptyset(&bs); sigaddset(&bs, SIGINT); sigprocmask(SIG_UNBLOCK, &bs, NULL); msg = match_nl_recv_msg(nsd, &err); sigprocmask(SIG_BLOCK, &bs, NULL); if (msg) { nlh = msg->msg; err = genlmsg_parse(nlh, 0, tb, NET_MAT_MAX, match_get_tables_policy); if (err < 0) { MAT_LOG(ERR, "Warning: unable to parse get rules msg\n"); goto out; } if (match_nl_table_cmd_to_type(stdout, true, NET_MAT_PORTS, tb)) goto out; if (tb[NET_MAT_PORTS]) { err = match_get_ports(stdout, verbose, tb[NET_MAT_PORTS], &port); if (err) goto out; } } match_nl_free_msg(msg); return port; out: match_nl_free_msg(msg); return NULL; }
int match_nl_set_port(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family, struct net_mat_port *port) { uint8_t cmd = NET_MAT_PORT_CMD_SET_PORTS; struct nlattr *tb[NET_MAT_MAX+1]; struct nlattr *nest, *nest1; struct nlmsghdr *nlh; struct match_msg *msg; sigset_t bs; int err = 0; msg = match_nl_alloc_msg(cmd, pid, NLM_F_REQUEST|NLM_F_ACK, 0, family); if (!msg) { MAT_LOG(ERR, "Error: Allocation failure\n"); return -ENOMSG; } if (nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER_TYPE, NET_MAT_IDENTIFIER_IFINDEX) || nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER, ifindex)) { MAT_LOG(ERR, "Error: Identifier put failed\n"); match_nl_free_msg(msg); return -EMSGSIZE; } nest = nla_nest_start(msg->nlbuf, NET_MAT_PORTS); if (!nest) { match_nl_free_msg(msg); return -EMSGSIZE; } nest1 = nla_nest_start(msg->nlbuf, NET_MAT_PORTS); match_put_port(msg->nlbuf, port); nla_nest_end(msg->nlbuf, nest1); nla_nest_end(msg->nlbuf, nest); nl_send_auto(nsd, msg->nlbuf); match_nl_free_msg(msg); sigemptyset(&bs); sigaddset(&bs, SIGINT); sigprocmask(SIG_UNBLOCK, &bs, NULL); msg = match_nl_recv_msg(nsd, &err); sigprocmask(SIG_BLOCK, &bs, NULL); if (!msg) return -EINVAL; nlh = msg->msg; err = genlmsg_parse(nlh, 0, tb, NET_MAT_MAX, match_get_tables_policy); if (err < 0) { MAT_LOG(ERR, "Warning: unable to parse set port msg\n"); match_nl_free_msg(msg); return err; } err = match_nl_table_cmd_to_type(stdout, true, 0, tb); if (err) { match_nl_free_msg(msg); return err; } if (tb[NET_MAT_PORTS]) { MAT_LOG(ERR, "Failed to set:\n"); match_get_ports(stdout, verbose, tb[NET_MAT_PORTS], NULL); match_nl_free_msg(msg); return -EINVAL; } match_nl_free_msg(msg); return 0; }
int match_nl_set_del_rules(struct nl_sock *nsd, uint32_t pid, unsigned int ifindex, int family, struct net_mat_rule *rule, uint8_t cmd) { struct nlattr *tb[NET_MAT_MAX+1]; struct match_msg *msg; struct nlmsghdr *nlh; struct nlattr *rules; sigset_t bs; int err = 0; pp_rule(stdout, true, rule); msg = match_nl_alloc_msg(cmd, pid, NLM_F_REQUEST|NLM_F_ACK, 0, family); if (!msg) { MAT_LOG(ERR, "Error: Allocation failure\n"); return -ENOMSG; } if (nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER_TYPE, NET_MAT_IDENTIFIER_IFINDEX) || nla_put_u32(msg->nlbuf, NET_MAT_IDENTIFIER, ifindex)) { MAT_LOG(ERR, "Error: Identifier put failed\n"); match_nl_free_msg(msg); return -EMSGSIZE; } err = match_put_rule_error(msg->nlbuf, NET_MAT_RULES_ERROR_CONT_LOG); if (err) { match_nl_free_msg(msg); return err; } rules = nla_nest_start(msg->nlbuf, NET_MAT_RULES); if (!rules) { match_nl_free_msg(msg); return -EMSGSIZE; } match_put_rule(msg->nlbuf, rule); nla_nest_end(msg->nlbuf, rules); nl_send_auto(nsd, msg->nlbuf); match_nl_free_msg(msg); /* message sent handle recv */ sigemptyset(&bs); sigaddset(&bs, SIGINT); sigprocmask(SIG_UNBLOCK, &bs, NULL); msg = match_nl_recv_msg(nsd, &err); sigprocmask(SIG_BLOCK, &bs, NULL); if (!msg) return -EINVAL; nlh = msg->msg; err = genlmsg_parse(nlh, 0, tb, NET_MAT_MAX, match_get_tables_policy); if (err < 0) { MAT_LOG(ERR, "Warning: unable to parse set rules msg\n"); match_nl_free_msg(msg); return err; } err = match_nl_table_cmd_to_type(stdout, true, 0, tb); if (err) { match_nl_free_msg(msg); return err; } if (tb[NET_MAT_RULES]) { MAT_LOG(ERR, "Failed to set:\n"); match_get_rules(stdout, verbose, tb[NET_MAT_RULES], NULL); match_nl_free_msg(msg); return -EINVAL; } match_nl_free_msg(msg); return 0; }
static inline int bpf_map_update_elem(__u32 fd, void *key, void *value) { union bpf_attr attr = {.map_type = 0}; /* initialize to zero */ attr.map_fd = fd; attr.key = bpf_ptr_to_u64(key); attr.value = bpf_ptr_to_u64(value); return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)); } static inline int bpf_map_delete_elem(__u32 fd, void *key) { union bpf_attr attr = {.map_type = 0}; /* initialize to zero */ attr.map_fd = fd; attr.key = bpf_ptr_to_u64(key); return syscall(__NR_bpf, BPF_MAP_DELETE_ELEM, &attr, sizeof(attr)); } #else static inline int bpf_map_update_elem(__u32 fd __unused, void *key __unused, void *value __unused) { return 0; } static inline int bpf_map_delete_elem(__u32 fd __unused, void *key __unused) { return 0; } #endif /* table cache is used to have a software representation of the maps * data structure. This allows reads to avoid going to kernel via * syscalls to rebuild the rules. Trading memory for ease of use here. */ __u8 *table_cache[BPF_MATCH_MAX_TABLES]; struct bpf_elf_map table_aux[BPF_MATCH_MAX_TABLES]; int table_fds[BPF_MATCH_MAX_TABLES]; static int bpf_pipeline_open(void *arg __unused) { struct sockaddr_un bpf_addr; int err, fd; long unsigned int i, num_fds; struct bpf_map_aux aux = {0}; struct bpf_map_set_msg bpf_msg; ssize_t ret; char filename[1024]; memset(&bpf_msg, 0, sizeof (struct bpf_map_set_msg)); fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (fd < 0) { MAT_LOG(ERR, "bpf af_unix socket failed: abort!\n"); exit(-1); } memset(&bpf_addr, 0, sizeof(bpf_addr)); bpf_addr.sun_family = AF_UNIX; for (i = 100; i < 200; i++) { sprintf(filename, "%s%lu", bpf_filename, i); strncpy(bpf_addr.sun_path, filename, sizeof bpf_addr.sun_path); err = bind(fd, (struct sockaddr *)&bpf_addr, sizeof bpf_addr); if (err < 0) { MAT_LOG(ERR, "bpf bind socket %s failed(%i): continue!\n", filename, err); continue; } printf("%s: using filename: %s\n", __func__, filename); break; } if (err) { MAT_LOG(ERR, "last bpf bind socket %s failed(%i): abort!\n", filename, err); exit(-1); } for (i = 0; i < BPF_MATCH_MAX_TABLES; i += num_fds) { struct cmsghdr *cmsg; bpf_msg.iov.iov_base = &bpf_msg.aux; bpf_msg.iov.iov_len = sizeof bpf_msg.aux; bpf_msg.hdr.msg_iov = &bpf_msg.iov; bpf_msg.hdr.msg_iovlen = 1; bpf_msg.hdr.msg_control = &bpf_msg.msg_buf; bpf_msg.hdr.msg_controllen = (10 * sizeof(int)); //(sizeof (int)); cmsg = CMSG_FIRSTHDR(&bpf_msg.hdr); cmsg->cmsg_len = bpf_msg.hdr.msg_controllen; cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; printf("%s: waiting for filter (tbd replace with fuse)\n", __func__); ret = recvmsg(fd, &bpf_msg.hdr, 0); if (ret <= 0) break; printf("%s: received maps (%lu)\n", __func__, ret); cmsg = CMSG_FIRSTHDR(&bpf_msg.hdr); num_fds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(int); assert(num_fds < BPF_MATCH_MAX_TABLES); memcpy(&fds[i], CMSG_DATA(cmsg), sizeof(int) * num_fds); memcpy(&aux.ent[i], &bpf_msg.aux.ent[i], sizeof(bpf_msg.aux.ent[0]) * num_fds); memcpy(&aux, &bpf_msg.aux, offsetof(struct bpf_map_aux, ent)); printf("%s: i %lu num_fds %lu num_ent %i\n", __func__, i, num_fds, aux.num_ent); if ((i + num_fds) == (long unsigned) (aux.num_ent <= 0 ? 0 : aux.num_ent)) break; } for (i = 0; i < BPF_MATCH_MAX_TABLES; i++) { const char *unknown = "Unknown-Table"; const char *str_label = unknown; int j; for (j = 0; j < BPF_MAX_TABLES; j++) { if (bpf_table_list[j]->uid == aux.ent[i].id) { int index = bpf_table_list[j]->uid; str_label = bpf_table_list[j]->name; /* If the table_id is larger then the max table this is a code * generator bug most likely in bpf_match.h or the actual bpf * program being loaded. In this case do a hard abort and let * the user sort the mess out. */ assert(aux.ent[i].id < BPF_MATCH_MAX_TABLES); table_cache[index] = calloc(aux.ent[i].max_elem, aux.ent[i].size_key); table_aux[index] = aux.ent[i]; table_fds[index] = fds[i]; break; } } printf("%s: @ %lu:fd(%i)\n", __func__, i, fds[i]); printf("\t label: %u -> %s\n", aux.ent[i].id, str_label); printf("\t type: %u\n", aux.ent[i].type); printf("\t max_elem: %u\n", aux.ent[i].max_elem); printf("\t key_size: %u\n", aux.ent[i].size_key); printf("\t size val: %u\n", aux.ent[i].size_value); } return 0; } static void bpf_pipeline_close(void) { int i; for (i = 0; i < BPF_MATCH_MAX_TABLES; i++) free(table_cache[i]); return; } static void bpf_pipeline_get_rule_counters(struct net_mat_rule *rule __unused) { MAT_LOG(ERR, "bpf get_counters unsupported\n"); return; } static struct net_mat_tbl *bpf_get_table(__u32 table) { int i; for (i = 0; bpf_table_list[i]; i++) { if (bpf_table_list[i]->uid == table) return bpf_table_list[i]; } return NULL; }