static int get_targets_handler(struct nl_msg *n, void *arg) { struct nlmsghdr *nlh = nlmsg_hdr(n); struct nlattr *attrs[NFC_ATTR_MAX + 1]; uint32_t adapter_idx, target_idx, protocols; uint16_t sens_res = 0; uint8_t sel_res = 0; uint8_t nfcid[NFC_MAX_NFCID1_LEN], nfcid_len; uint8_t iso15693_dsfid = 0; uint8_t iso15693_uid_len, iso15693_uid[NFC_MAX_ISO15693_UID_LEN]; DBG(""); genlmsg_parse(nlh, 0, attrs, NFC_ATTR_MAX, NULL); adapter_idx = *((uint32_t *)arg); target_idx = nla_get_u32(attrs[NFC_ATTR_TARGET_INDEX]); protocols = nla_get_u32(attrs[NFC_ATTR_PROTOCOLS]); if (attrs[NFC_ATTR_TARGET_SENS_RES]) sens_res = nla_get_u16(attrs[NFC_ATTR_TARGET_SENS_RES]); if (attrs[NFC_ATTR_TARGET_SEL_RES]) sel_res = nla_get_u16(attrs[NFC_ATTR_TARGET_SEL_RES]); if (attrs[NFC_ATTR_TARGET_NFCID1]) { nfcid_len = nla_len(attrs[NFC_ATTR_TARGET_NFCID1]); if (nfcid_len <= NFC_MAX_NFCID1_LEN) memcpy(nfcid, nla_data(attrs[NFC_ATTR_TARGET_NFCID1]), nfcid_len); } else { nfcid_len = 0; } if (attrs[NFC_ATTR_TARGET_ISO15693_DSFID]) iso15693_dsfid = nla_get_u8(attrs[NFC_ATTR_TARGET_ISO15693_DSFID]); if (attrs[NFC_ATTR_TARGET_ISO15693_UID]) { iso15693_uid_len = nla_len(attrs[NFC_ATTR_TARGET_ISO15693_UID]); if (iso15693_uid_len == NFC_MAX_ISO15693_UID_LEN) memcpy(iso15693_uid, nla_data(attrs[NFC_ATTR_TARGET_ISO15693_UID]), NFC_MAX_ISO15693_UID_LEN); } else { iso15693_uid_len = 0; } DBG("target idx %d proto 0x%x sens_res 0x%x sel_res 0x%x NFCID len %d", target_idx, protocols, sens_res, sel_res, nfcid_len); DBG("\tiso15693_uid_len %d", iso15693_uid_len); __near_adapter_add_target(adapter_idx, target_idx, protocols, sens_res, sel_res, nfcid, nfcid_len, iso15693_dsfid, iso15693_uid_len, iso15693_uid); return 0; }
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; } 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) { struct net_mat_port port = {.pci = {0}, .port_id = 0}; struct net_mat_port ports[2] = {{0}, {0}}; uint8_t cmd = NET_MAT_PORT_CMD_GET_LPORT; 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; } port.pci.bus = bus; port.pci.device = device; port.pci.function = function; ports[0] = port; 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; } *lport = port_query[0].port_id; } match_nl_free_msg(msg); free(port_query); return 0; }
static int ipvs_services_parse_cb(struct nl_msg *msg, void *arg) { struct nlmsghdr *nlh = nlmsg_hdr(msg); struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1]; struct nlattr *svc_attrs[IPVS_SVC_ATTR_MAX + 1]; struct ip_vs_get_services **getp = (struct ip_vs_get_services **)arg; struct ip_vs_get_services *get = (struct ip_vs_get_services *)*getp; struct ip_vs_flags flags; int i = get->num_services; if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0) return -1; if (!attrs[IPVS_CMD_ATTR_SERVICE]) return -1; if (nla_parse_nested(svc_attrs, IPVS_SVC_ATTR_MAX, attrs[IPVS_CMD_ATTR_SERVICE], ipvs_service_policy)) return -1; memset(&(get->entrytable[i]), 0, sizeof(get->entrytable[i])); if (!(svc_attrs[IPVS_SVC_ATTR_AF] && (svc_attrs[IPVS_SVC_ATTR_FWMARK] || (svc_attrs[IPVS_SVC_ATTR_PROTOCOL] && svc_attrs[IPVS_SVC_ATTR_ADDR] && svc_attrs[IPVS_SVC_ATTR_PORT])) && svc_attrs[IPVS_SVC_ATTR_SCHED_NAME] && svc_attrs[IPVS_SVC_ATTR_NETMASK] && svc_attrs[IPVS_SVC_ATTR_TIMEOUT] && svc_attrs[IPVS_SVC_ATTR_FLAGS])) return -1; get->entrytable[i].af = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_AF]); if (svc_attrs[IPVS_SVC_ATTR_FWMARK]) get->entrytable[i].fwmark = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_FWMARK]); else { get->entrytable[i].protocol = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_PROTOCOL]); memcpy(&(get->entrytable[i].addr), nla_data(svc_attrs[IPVS_SVC_ATTR_ADDR]), sizeof(get->entrytable[i].addr)); get->entrytable[i].port = nla_get_u16(svc_attrs[IPVS_SVC_ATTR_PORT]); } strncpy(get->entrytable[i].sched_name, nla_get_string(svc_attrs[IPVS_SVC_ATTR_SCHED_NAME]), IP_VS_SCHEDNAME_MAXLEN); get->entrytable[i].netmask = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_NETMASK]); get->entrytable[i].timeout = nla_get_u32(svc_attrs[IPVS_SVC_ATTR_TIMEOUT]); nla_memcpy(&flags, svc_attrs[IPVS_SVC_ATTR_FLAGS], sizeof(flags)); get->entrytable[i].flags = flags.flags & flags.mask; if (ipvs_parse_stats(&(get->entrytable[i].stats), svc_attrs[IPVS_SVC_ATTR_STATS]) != 0) return -1; get->entrytable[i].num_dests = 0; i++; get->num_services = i; get = realloc(get, sizeof(*get) + sizeof(ipvs_service_entry_t) * (get->num_services + 1)); *getp = get; return 0; }
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 int ipvs_dests_parse_cb(struct nl_msg *msg, void *arg) { struct nlmsghdr *nlh = nlmsg_hdr(msg); struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1]; struct nlattr *dest_attrs[IPVS_DEST_ATTR_MAX + 1]; struct nlattr *attr_addr_family = NULL; struct ip_vs_get_dests **dp = (struct ip_vs_get_dests **)arg; struct ip_vs_get_dests *d = (struct ip_vs_get_dests *)*dp; int i = d->num_dests; if (genlmsg_parse(nlh, 0, attrs, IPVS_CMD_ATTR_MAX, ipvs_cmd_policy) != 0) return -1; if (!attrs[IPVS_CMD_ATTR_DEST]) return -1; if (nla_parse_nested(dest_attrs, IPVS_DEST_ATTR_MAX, attrs[IPVS_CMD_ATTR_DEST], ipvs_dest_policy)) return -1; memset(&(d->entrytable[i]), 0, sizeof(d->entrytable[i])); if (!(dest_attrs[IPVS_DEST_ATTR_ADDR] && dest_attrs[IPVS_DEST_ATTR_PORT] && dest_attrs[IPVS_DEST_ATTR_FWD_METHOD] && dest_attrs[IPVS_DEST_ATTR_WEIGHT] && dest_attrs[IPVS_DEST_ATTR_U_THRESH] && dest_attrs[IPVS_DEST_ATTR_L_THRESH] && dest_attrs[IPVS_DEST_ATTR_ACTIVE_CONNS] && dest_attrs[IPVS_DEST_ATTR_INACT_CONNS] && dest_attrs[IPVS_DEST_ATTR_PERSIST_CONNS])) return -1; memcpy(&(d->entrytable[i].addr), nla_data(dest_attrs[IPVS_DEST_ATTR_ADDR]), sizeof(d->entrytable[i].addr)); d->entrytable[i].port = nla_get_u16(dest_attrs[IPVS_DEST_ATTR_PORT]); d->entrytable[i].conn_flags = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_FWD_METHOD]); d->entrytable[i].weight = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_WEIGHT]); d->entrytable[i].u_threshold = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_U_THRESH]); d->entrytable[i].l_threshold = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_L_THRESH]); d->entrytable[i].activeconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_ACTIVE_CONNS]); d->entrytable[i].inactconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_INACT_CONNS]); d->entrytable[i].persistconns = nla_get_u32(dest_attrs[IPVS_DEST_ATTR_PERSIST_CONNS]); attr_addr_family = dest_attrs[IPVS_DEST_ATTR_ADDR_FAMILY]; if (attr_addr_family) d->entrytable[i].af = nla_get_u16(attr_addr_family); else d->entrytable[i].af = d->af; if (dest_attrs[IPVS_DEST_ATTR_STATS64]) { if (ipvs_parse_stats(&d->entrytable[i].stats64, dest_attrs[IPVS_DEST_ATTR_STATS64]) != 0) return -1; } else if (dest_attrs[IPVS_DEST_ATTR_STATS]) { if (ipvs_parse_stats(&d->entrytable[i].stats64, dest_attrs[IPVS_DEST_ATTR_STATS]) != 0) return -1; } i++; d->num_dests = i; d = realloc(d, sizeof(*d) + sizeof(ipvs_dest_entry_t) * (d->num_dests + 1)); *dp = d; return 0; }
/** * Callback to process an WIMAX_GNL_RE_STATE_CHANGE from the kernel * * \internal * * \param wmx WiMAX device handle * \param mch WiMAX multicast group handle * \param msg Pointer to netlink message * \return \c enum nl_cb_action * * wimaxll_mc_rx_read() calls libnl's nl_recvmsgs() to receive messages; * when a valid message is received, it goes into a loop that selects * a callback to run for each type of message and it will call this * function. * * This just expects a _RE_STATE_CHANGE message, whose payload is what * has to be passed to the caller. We just extract the data and call * the callback defined in the handle. */ int wimaxll_gnl_handle_state_change(struct wimaxll_handle *wmx, struct nl_msg *msg) { ssize_t result; struct nlmsghdr *nl_hdr; struct genlmsghdr *gnl_hdr; struct nlattr *tb[WIMAX_GNL_ATTR_MAX+1]; enum wimax_st old_state, new_state; unsigned dest_ifidx; d_fnstart(7, wmx, "(wmx %p msg %p)\n", wmx, msg); nl_hdr = nlmsg_hdr(msg); gnl_hdr = nlmsg_data(nl_hdr); assert(gnl_hdr->cmd == WIMAX_GNL_RE_STATE_CHANGE); /* Parse the attributes */ result = genlmsg_parse(nl_hdr, 0, tb, WIMAX_GNL_ATTR_MAX, wimaxll_gnl_re_state_change_policy); if (result < 0) { wimaxll_msg(wmx, "E: %s: genlmsg_parse() failed: %zd\n", __func__, result); goto error_parse; } /* Find if the message is for the interface wmx represents */ dest_ifidx = nla_get_u32(tb[WIMAX_GNL_STCH_IFIDX]); if (wmx->ifidx > 0 && wmx->ifidx != dest_ifidx) { wimaxll_msg(wmx, "E: %s: cannot find IFIDX attribute\n", __func__); result = -ENODEV; goto error_no_attrs; } if (tb[WIMAX_GNL_STCH_STATE_OLD] == NULL) { wimaxll_msg(wmx, "E: %s: cannot find STCH_STATE_OLD " "attribute\n", __func__); result = -ENXIO; goto error_no_attrs; } old_state = nla_get_u8(tb[WIMAX_GNL_STCH_STATE_OLD]); if (tb[WIMAX_GNL_STCH_STATE_NEW] == NULL) { wimaxll_msg(wmx, "E: %s: cannot find STCH_STATE_NEW " "attribute\n", __func__); result = -EINVAL; goto error_no_attrs; } new_state = nla_get_u8(tb[WIMAX_GNL_STCH_STATE_NEW]); d_printf(1, wmx, "D: CRX re_state_change old %u new %u\n", old_state, new_state); /* If this is an "any" handle, set the wmx->ifidx to the * received one so the callback can now where did the thing * come from. Will be restored. */ if (wmx->ifidx == 0) { wmx->ifidx = dest_ifidx; dest_ifidx = 0; } /* Now execute the callback for handling re-state-change; if * it doesn't update the context's result code, we'll do. */ result = wmx->state_change_cb(wmx, wmx->state_change_priv, old_state, new_state); wmx->ifidx = dest_ifidx; error_no_attrs: error_parse: d_fnend(7, wmx, "(wmx %p msg %p) = %zd\n", wmx, msg, result); return result; }