static int deth_netlink_do_broadcast_addresses(struct sock* nl_sk, u32 index) { struct sk_buff* skb = nlmsg_new(sizeof(u32), 0); struct nlmsghdr* nlh; if (!skb) { printk(KERN_ERR "Failed to allocate new skb\n"); return -ENOBUFS; } nlh = nlmsg_put(skb, 0, 0, MULTICAST_ADDRESS_CHANGE, sizeof(u32), 0); if (nlh == NULL) { nlmsg_free(skb); return -EMSGSIZE; } memcpy(nlmsg_data(nlh), &index, sizeof(u32)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) NETLINK_CB(skb).portid = 0; #else NETLINK_CB(skb).pid = 0; #endif NETLINK_CB(skb).dst_group = NETLINK_DETH_GROUP; return netlink_broadcast(nl_sk, skb, 0, NETLINK_DETH_GROUP, GFP_KERNEL); }
static struct nl_msg *build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags) { struct nl_msg *msg; struct rtmsg rtm = { .rtm_type = RTN_UNSPEC }; if (cmd == RTM_NEWRULE) rtm.rtm_type = RTN_UNICAST; if (tmpl->ce_mask & RULE_ATTR_FAMILY) rtm.rtm_family = tmpl->r_family; if (tmpl->ce_mask & RULE_ATTR_TABLE) rtm.rtm_table = tmpl->r_table; if (tmpl->ce_mask & RULE_ATTR_DSFIELD) rtm.rtm_tos = tmpl->r_dsfield; if (tmpl->ce_mask & RULE_ATTR_TYPE) rtm.rtm_type = tmpl->r_type; if (tmpl->ce_mask & RULE_ATTR_SRC_LEN) rtm.rtm_src_len = tmpl->r_src_len; if (tmpl->ce_mask & RULE_ATTR_DST_LEN) rtm.rtm_dst_len = tmpl->r_dst_len; msg = nlmsg_alloc_simple(cmd, flags); if (!msg) goto nla_put_failure; if (nlmsg_append(msg, &rtm, sizeof(rtm), NLMSG_ALIGNTO) < 0) goto nla_put_failure; if (tmpl->ce_mask & RULE_ATTR_SRC) NLA_PUT_ADDR(msg, RTA_SRC, tmpl->r_src); if (tmpl->ce_mask & RULE_ATTR_DST) NLA_PUT_ADDR(msg, RTA_DST, tmpl->r_dst); if (tmpl->ce_mask & RULE_ATTR_PRIO) NLA_PUT_U32(msg, RTA_PRIORITY, tmpl->r_prio); if (tmpl->ce_mask & RULE_ATTR_MARK) NLA_PUT_U32(msg, RTA_PROTOINFO, tmpl->r_mark); if (tmpl->ce_mask & RULE_ATTR_REALMS) NLA_PUT_U32(msg, RTA_FLOW, tmpl->r_realms); if (tmpl->ce_mask & RULE_ATTR_IIF) NLA_PUT_STRING(msg, RTA_IIF, tmpl->r_iif); return msg; nla_put_failure: nlmsg_free(msg); return NULL; }
static int nfnl_log_build_request(const struct nfnl_log *log, struct nl_msg **result) { struct nl_msg *msg; if (!nfnl_log_test_group(log)) return -NLE_MISSING_ATTR; msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0, 0, nfnl_log_get_group(log)); if (msg == NULL) return -NLE_NOMEM; /* This sucks. The nfnetlink_log interface always expects both * parameters to be present. Needs to be done properly. */ if (nfnl_log_test_copy_mode(log)) { struct nfulnl_msg_config_mode mode; switch (nfnl_log_get_copy_mode(log)) { case NFNL_LOG_COPY_NONE: mode.copy_mode = NFULNL_COPY_NONE; break; case NFNL_LOG_COPY_META: mode.copy_mode = NFULNL_COPY_META; break; case NFNL_LOG_COPY_PACKET: mode.copy_mode = NFULNL_COPY_PACKET; break; } mode.copy_range = htonl(nfnl_log_get_copy_range(log)); mode._pad = 0; if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0) goto nla_put_failure; } if (nfnl_log_test_flush_timeout(log) && nla_put_u32(msg, NFULA_CFG_TIMEOUT, htonl(nfnl_log_get_flush_timeout(log))) < 0) goto nla_put_failure; if (nfnl_log_test_alloc_size(log) && nla_put_u32(msg, NFULA_CFG_NLBUFSIZ, htonl(nfnl_log_get_alloc_size(log))) < 0) goto nla_put_failure; if (nfnl_log_test_queue_threshold(log) && nla_put_u32(msg, NFULA_CFG_QTHRESH, htonl(nfnl_log_get_queue_threshold(log))) < 0) goto nla_put_failure; *result = msg; return 0; nla_put_failure: nlmsg_free(msg); return -NLE_MSGSIZE; }
/* return after DAD finishes for all known IPv6 addresses or an error */ int virNetDevIPWaitDadFinish(virSocketAddrPtr *addrs, size_t count) { struct nl_msg *nlmsg = NULL; struct ifaddrmsg ifa; struct nlmsghdr *resp = NULL; unsigned int recvbuflen; int ret = -1; bool dad = true; time_t max_time = time(NULL) + VIR_DAD_WAIT_TIMEOUT; if (!(nlmsg = nlmsg_alloc_simple(RTM_GETADDR, NLM_F_REQUEST | NLM_F_DUMP))) { virReportOOMError(); return -1; } memset(&ifa, 0, sizeof(ifa)); /* DAD is for IPv6 adresses only. */ ifa.ifa_family = AF_INET6; if (nlmsg_append(nlmsg, &ifa, sizeof(ifa), NLMSG_ALIGNTO) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("allocated netlink buffer is too small")); goto cleanup; } /* Periodically query netlink until DAD finishes on all known addresses. */ while (dad && time(NULL) < max_time) { if (virNetlinkCommand(nlmsg, &resp, &recvbuflen, 0, 0, NETLINK_ROUTE, 0) < 0) goto cleanup; if (virNetlinkGetErrorCode(resp, recvbuflen) < 0) { virReportError(VIR_ERR_SYSTEM_ERROR, "%s", _("error reading DAD state information")); goto cleanup; } /* Parse response. */ dad = virNetDevIPParseDadStatus(resp, recvbuflen, addrs, count); if (dad) usleep(1000 * 10); VIR_FREE(resp); } /* Check timeout. */ if (dad) { virReportError(VIR_ERR_SYSTEM_ERROR, _("Duplicate Address Detection " "not finished in %d seconds"), VIR_DAD_WAIT_TIMEOUT); } else { ret = 0; } cleanup: VIR_FREE(resp); nlmsg_free(nlmsg); return ret; }
static int netdev_set_flag(const char *name, int flag) { struct nl_handler nlh; struct nlmsg *nlmsg = NULL, *answer = NULL; struct link_req *link_req; int index, len, err; err = netlink_open(&nlh, NETLINK_ROUTE); if (err) return err; err = -EINVAL; len = strlen(name); if (len == 1 || len >= IFNAMSIZ) goto out; err = -ENOMEM; nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!nlmsg) goto out; answer = nlmsg_alloc(NLMSG_GOOD_SIZE); if (!answer) goto out; err = -EINVAL; index = if_nametoindex(name); if (!index) goto out; link_req = (struct link_req *)nlmsg; link_req->ifinfomsg.ifi_family = AF_UNSPEC; link_req->ifinfomsg.ifi_index = index; link_req->ifinfomsg.ifi_change |= IFF_UP; link_req->ifinfomsg.ifi_flags |= flag; nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); nlmsg->nlmsghdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK; err = netlink_transaction(&nlh, nlmsg, answer); out: netlink_close(&nlh); nlmsg_free(nlmsg); nlmsg_free(answer); return err; }
int nf10_reg_wr(uint32_t addr, uint32_t val) { struct nl_msg *msg; int err; err = driver_connect(); if(err) return err; msg = nlmsg_alloc(); if(msg == NULL) { driver_disconnect(); return -NLE_NOMEM; } /* genlmsg_put will fill in the fields of the nlmsghdr and the genlmsghdr. */ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, nf10_genl_family, 0, 0, NF10_GENL_C_REG_WR, NF10_GENL_FAMILY_VERSION); nla_put_u32(msg, NF10_GENL_A_ADDR32, addr); nla_put_u32(msg, NF10_GENL_A_REGVAL32, val); /* nl_send_auto will automatically fill in the PID and the sequence number, * and also add an NLM_F_REQUEST flag. It will also add an NLM_F_ACK * flag unless the netlink socket has the NL_NO_AUTO_ACK flag set. */ err = nl_send_auto(nf10_genl_sock, msg); if(err < 0) { nlmsg_free(msg); driver_disconnect(); return err; } nlmsg_free(msg); nl_socket_modify_cb(nf10_genl_sock, NL_CB_ACK, NL_CB_CUSTOM, nf10_reg_wr_recv_ack_cb, NULL); /* FIXME: this function will return even if there's no ACK in the buffer. I.E. it doesn't * seem to wait for the ACK to be received... Ideally we'd have the behavior that getting an * ACK tells us everything is OK, otherwise we time out on waiting for an ACK and tell this * to the user. */ err = nl_recvmsgs_default(nf10_genl_sock); driver_disconnect(); return err; }
int ipvs_nl_send_message(struct nl_msg *msg, nl_recvmsg_msg_cb_t func, void *arg) { int err = EINVAL; sock = nl_socket_alloc(); if (!sock) { nlmsg_free(msg); return -1; } if (genl_connect(sock) < 0) goto fail_genl; family = genl_ctrl_resolve(sock, IPVS_GENL_NAME); if (family < 0) goto fail_genl; /* To test connections and set the family */ if (msg == NULL) { nl_socket_free(sock); sock = NULL; return 0; } if (nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, func, arg) != 0) goto fail_genl; if (nl_send_auto_complete(sock, msg) < 0) goto fail_genl; if ((err = -nl_recvmsgs_default(sock)) > 0) goto fail_genl; nlmsg_free(msg); nl_socket_free(sock); return 0; fail_genl: nl_socket_free(sock); sock = NULL; nlmsg_free(msg); errno = err; return -1; }
int SoftapController::executeScanLinkCmd(const char *iface, int *iface_freq) { struct nl_cb *cb; struct nl_msg *msg; int devidx = 0; int err; // initialize to non-valid freq *iface_freq = 0; devidx = if_nametoindex(iface); if (devidx == 0) { LOGE("failed to translate ifname to idx"); return -errno; } msg = nlmsg_alloc(); if (!msg) { LOGE("failed to allocate netlink message"); return 2; } cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) { LOGE("failed to allocate netlink callbacks"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); // iface_freq will be filled out by the callback nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, linkDumpCbHandler, iface_freq); err = nl_send_auto_complete(nl_soc, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, NlErrorHandler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, NlFinishHandler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, NlAckHandler, &err); while (err > 0) nl_recvmsgs(nl_soc, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; nla_put_failure: LOGW("building message failed"); return 2; }
void ptp_work_send_rtc_change(struct work_struct *work) { struct ptp_device *ptp = container_of(work, struct ptp_device, work_send_rtc_change); struct sk_buff *skb; uint8_t commandByte; void *msgHead; int returnValue = 0; skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if(skb == NULL) return; /* Decide which command byte to send with the message based upon the lock state */ if(ptp->rtcLockState == PTP_RTC_LOCKED) { commandByte = PTP_EVENTS_C_RTC_LOCK; } else { commandByte = PTP_EVENTS_C_RTC_UNLOCK; } /* Create the message headers */ msgHead = genlmsg_put(skb, 0, ptp->netlinkSequence++, &ptp_events_genl_family, 0, commandByte); if(msgHead == NULL) { returnValue = -ENOMEM; goto rtc_change_fail; } /* Write the PTP domain identifier to the message */ returnValue = nla_put_u8(skb, PTP_EVENTS_A_DOMAIN, ptp->properties.domainNumber); if(returnValue != 0) goto rtc_change_fail; /* Finalize the message and multicast it */ genlmsg_end(skb, msgHead); returnValue = genlmsg_multicast(skb, 0, rtc_mcast.id, GFP_ATOMIC); skb = NULL; switch(returnValue) { case 0: case -ESRCH: // Success or no process was listening, simply break break; default: // This is an actual error, print the return code printk(KERN_INFO DRIVER_NAME ": Failure delivering multicast Netlink message: %d\n", returnValue); goto rtc_change_fail; } rtc_change_fail: if (NULL != skb) { nlmsg_free(skb); skb = NULL; } }
/* NOTE: this function consumes 'msg' */ static int _nl80211_send_and_recv (struct nl_sock *nl_sock, struct nl_cb *nl_cb, struct nl_msg *msg, int (*valid_handler) (struct nl_msg *, void *), void *valid_data) { struct nl_cb *cb; int err, done; g_return_val_if_fail (msg != NULL, -ENOMEM); cb = nl_cb_clone (nl_cb); if (!cb) { err = -ENOMEM; goto out; } err = nl_send_auto_complete (nl_sock, msg); if (err < 0) goto out; done = 0; nl_cb_err (cb, NL_CB_CUSTOM, error_handler, &done); nl_cb_set (cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &done); nl_cb_set (cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &done); if (valid_handler) nl_cb_set (cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, valid_data); /* Loop until one of our NL callbacks says we're done; on success * done will be 1, on error it will be < 0. */ while (!done) { err = nl_recvmsgs (nl_sock, cb); if (err && err != -NLE_AGAIN) { /* Kernel scan list can change while we are dumping it, as new scan * results from H/W can arrive. BSS info is assured to be consistent * and we don't need consistent view of whole scan list. Hence do * not warn on DUMP_INTR error for get scan command. */ if (err == -NLE_DUMP_INTR && genlmsg_hdr(nlmsg_hdr(msg))->cmd == NL80211_CMD_GET_SCAN) break; nm_log_warn (LOGD_WIFI, "nl_recvmsgs() error: (%d) %s", err, nl_geterror (err)); break; } } if (err == 0 && done < 0) err = done; out: nl_cb_put (cb); nlmsg_free (msg); return err; }
static int nl80211_add_mon_if(struct nl80211_state *state, const char *device, const char *mondevice) { int ifindex, ret; struct nl_msg *msg; ifindex = device_ifindex(device); msg = nl80211_nlmsg_xalloc(); genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_NEW_INTERFACE, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR); ret = nl_send_auto_complete(state->nl_sock, msg); if (ret < 0) { if (ret == -ENFILE) { nlmsg_free(msg); return -EBUSY; } panic("Cannot send_auto_complete!\n"); } ret = nl_wait_for_ack(state->nl_sock); if (ret < 0) { if (ret == -ENFILE) { nlmsg_free(msg); return -EBUSY; } panic("Waiting for netlink ack failed!\n"); } nlmsg_free(msg); return 0; nla_put_failure: panic("nla put failure!\n"); return -EIO; /* dummy */ }
static int ipvs_nl_fill_service_attr(struct nl_msg *msg, ipvs_service_t *svc) { struct nlattr *nl_service; struct ip_vs_flags flags = { .flags = svc->flags, .mask = ~0 }; nl_service = nla_nest_start(msg, IPVS_CMD_ATTR_SERVICE); if (!nl_service) return -1; NLA_PUT_U16(msg, IPVS_SVC_ATTR_AF, svc->af); if (svc->fwmark) { NLA_PUT_U32(msg, IPVS_SVC_ATTR_FWMARK, svc->fwmark); } else { NLA_PUT_U16(msg, IPVS_SVC_ATTR_PROTOCOL, svc->protocol); NLA_PUT(msg, IPVS_SVC_ATTR_ADDR, sizeof(svc->addr), &(svc->addr)); NLA_PUT_U16(msg, IPVS_SVC_ATTR_PORT, svc->port); } NLA_PUT_STRING(msg, IPVS_SVC_ATTR_SCHED_NAME, svc->sched_name); if (svc->pe_name[0]) NLA_PUT_STRING(msg, IPVS_SVC_ATTR_PE_NAME, svc->pe_name); NLA_PUT(msg, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags); NLA_PUT_U32(msg, IPVS_SVC_ATTR_TIMEOUT, svc->timeout); NLA_PUT_U32(msg, IPVS_SVC_ATTR_NETMASK, svc->netmask); nla_nest_end(msg, nl_service); return 0; nla_put_failure: return -1; } #endif int ipvs_add_service(ipvs_service_t *svc) { ipvs_func = ipvs_add_service; #ifdef LIBIPVS_USE_NL if (try_nl) { struct nl_msg *msg = ipvs_nl_message(IPVS_CMD_NEW_SERVICE, 0); if (!msg) return -1; if (ipvs_nl_fill_service_attr(msg, svc)) { nlmsg_free(msg); return -1; } return ipvs_nl_send_message(msg, ipvs_nl_noop_cb, NULL); } #endif CHECK_COMPAT_SVC(svc, -1); return setsockopt(sockfd, IPPROTO_IP, IP_VS_SO_SET_ADD, (char *)svc, sizeof(struct ip_vs_service_kern)); out_err: return -1; }
/** Sends a user message to remote node via associated kernel connection. */ int send_user_message(int target_slot_type, int target_slot_index, int data_length, char* data) { struct nl_msg* msg = NULL; struct nl_msg *ans_msg = NULL; struct nlmsghdr *nl_hdr; struct genlmsghdr* genl_hdr; struct nlattr *nla; int ret_val = 0; if ( (ret_val=prepare_request_message(state.handle, DIRECTOR_SEND_GENERIC_USER_MESSAGE, state.gnl_fid, &msg) ) != 0 ) { goto done; } ret_val = nla_put_u32(msg, DIRECTOR_A_SLOT_TYPE, target_slot_type); if (ret_val != 0) goto done; ret_val = nla_put_u32(msg, DIRECTOR_A_SLOT_INDEX, target_slot_index); if (ret_val != 0) goto done; ret_val = nla_put_u32(msg, DIRECTOR_A_LENGTH, data_length); if (ret_val != 0) goto done; ret_val = nla_put(msg, DIRECTOR_A_USER_DATA, data_length, data); if (ret_val != 0) goto done; if ( (ret_val = send_request_message(state.handle, msg, 1) ) != 0 ) goto done; if ( (ret_val = read_message(state.handle, &ans_msg) ) != 0 ) { goto done; } // TODO: We are not checking, the ack is for this request. Check it! while ( !is_ack_message(ans_msg) ) { // We can get different than ack messega here.. in this case we have to process it handle_incoming_message(ans_msg); if ( (ret_val = read_message(state.handle, &ans_msg) ) != 0 ) { goto done; } } done: nlmsg_free(ans_msg); return ret_val; }
void match_nl_free_msg(struct match_msg *msg) { if(msg) { if (msg->nlbuf) nlmsg_free(msg->nlbuf); else free(msg->msg); free(msg); } }
static struct nl80211_msg_conveyor * nl80211_msg(const char *ifname, int cmd, int flags) { static struct nl80211_msg_conveyor cv; int ifidx = -1, phyidx = -1; struct nl_msg *req = NULL; struct nl_cb *cb = NULL; if (nl80211_init() < 0) goto err; if (!strncmp(ifname, "phy", 3)) phyidx = atoi(&ifname[3]); else if (!strncmp(ifname, "radio", 5)) phyidx = atoi(&ifname[5]); else if (!strncmp(ifname, "mon.", 4)) ifidx = if_nametoindex(&ifname[4]); else ifidx = if_nametoindex(ifname); if ((ifidx < 0) && (phyidx < 0)) return NULL; req = nlmsg_alloc(); if (!req) goto err; cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) goto err; genlmsg_put(req, 0, 0, genl_family_get_id(nls->nl80211), 0, flags, cmd, 0); if (ifidx > -1) NLA_PUT_U32(req, NL80211_ATTR_IFINDEX, ifidx); if (phyidx > -1) NLA_PUT_U32(req, NL80211_ATTR_WIPHY, phyidx); cv.msg = req; cv.cb = cb; return &cv; err: nla_put_failure: if (cb) nl_cb_put(cb); if (req) nlmsg_free(req); return NULL; }
/* * Allocate a Report State Change message * * @header: save it, you need it for _send() * * Creates and fills a basic state change message; different code * paths can then add more attributes to the message as needed. * * Use wimax_gnl_re_state_change_send() to send the returned skb. * * Returns: skb with the genl message if ok, IS_ERR() ptr on error * with an errno code. */ static struct sk_buff *wimax_gnl_re_state_change_alloc( struct wimax_dev *wimax_dev, enum wimax_st new_state, enum wimax_st old_state, void **header) { int result; struct device *dev = wimax_dev_to_dev(wimax_dev); void *data; struct sk_buff *report_skb; d_fnstart(3, dev, "(wimax_dev %p new_state %u old_state %u)\n", wimax_dev, new_state, old_state); result = -ENOMEM; report_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (report_skb == NULL) { dev_err(dev, "RE_STCH: can't create message\n"); goto error_new; } /* FIXME: sending a group ID as the seq is wrong */ data = genlmsg_put(report_skb, 0, wimax_gnl_family.mcgrp_offset, &wimax_gnl_family, 0, WIMAX_GNL_RE_STATE_CHANGE); if (data == NULL) { dev_err(dev, "RE_STCH: can't put data into message\n"); goto error_put; } *header = data; result = nla_put_u8(report_skb, WIMAX_GNL_STCH_STATE_OLD, old_state); if (result < 0) { dev_err(dev, "RE_STCH: Error adding OLD attr: %d\n", result); goto error_put; } result = nla_put_u8(report_skb, WIMAX_GNL_STCH_STATE_NEW, new_state); if (result < 0) { dev_err(dev, "RE_STCH: Error adding NEW attr: %d\n", result); goto error_put; } result = nla_put_u32(report_skb, WIMAX_GNL_STCH_IFIDX, wimax_dev->net_dev->ifindex); if (result < 0) { dev_err(dev, "RE_STCH: Error adding IFINDEX attribute\n"); goto error_put; } d_fnend(3, dev, "(wimax_dev %p new_state %u old_state %u) = %p\n", wimax_dev, new_state, old_state, report_skb); return report_skb; error_put: nlmsg_free(report_skb); error_new: d_fnend(3, dev, "(wimax_dev %p new_state %u old_state %u) = %d\n", wimax_dev, new_state, old_state, result); return ERR_PTR(result); }
int handle_immigration_request(struct nl_msg *req_msg) { struct nl_msg *msg = NULL; struct nlattr *nla; int ret = 0; int seq; struct internal_state* state = get_current_state(); // In params int uid; int slot_index; char* name; // Out params int accept = 1; seq = nlmsg_hdr(req_msg)->nlmsg_seq; nla = nlmsg_find_attr(nlmsg_hdr(req_msg), sizeof(struct genlmsghdr), DIRECTOR_A_UID); if (nla == NULL) return -EBADMSG; uid = nla_get_u32(nla); nla = nlmsg_find_attr(nlmsg_hdr(req_msg), sizeof(struct genlmsghdr), DIRECTOR_A_INDEX); if (nla == NULL) return -EBADMSG; slot_index = nla_get_u32(nla); nla = nlmsg_find_attr(nlmsg_hdr(req_msg), sizeof(struct genlmsghdr), DIRECTOR_A_NAME); if (nla == NULL) return -EBADMSG; //name = nl_data_get(nla_get_data(nla)); name = nla_data(nla); //printf("NPM CALLED FOR NAME: %s\n", name); if ( immigration_request_callback ) immigration_request_callback(uid, slot_index, name, &accept); if ( (ret=prepare_response_message(state->handle, DIRECTOR_IMMIGRATION_REQUEST_RESPONSE, state->gnl_fid, seq, &msg) ) != 0 ) { goto done; } ret = nla_put_u32(msg, DIRECTOR_A_DECISION, accept); if (ret != 0) goto error_del_resp; ret = send_request_message(state->handle, msg, 0); goto done; error_del_resp: nlmsg_free(msg); done: return ret; }
static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags, struct nl_msg **result) { struct nl_msg *msg; int err; msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK_EXP, cmd, flags, nfnl_exp_get_family(exp), 0); if (msg == NULL) return -NLE_NOMEM; if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0) goto err_out; if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0) goto err_out; if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0) goto err_out; if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) { if ((err = nfnl_exp_build_nat(msg, exp)) < 0) goto err_out; } if (nfnl_exp_test_class(exp)) NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp))); if (nfnl_exp_test_fn(exp)) NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp)); if (nfnl_exp_test_id(exp)) NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp))); if (nfnl_exp_test_timeout(exp)) NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp))); if (nfnl_exp_test_helper_name(exp)) NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp)); if (nfnl_exp_test_zone(exp)) NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp))); if (nfnl_exp_test_flags(exp)) NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp))); *result = msg; return 0; nla_put_failure: err_out: nlmsg_free(msg); return err; }
/** * wimax_msg_alloc - Create a new skb for sending a message to userspace * * @wimax_dev: WiMAX device descriptor * @pipe_name: "named pipe" the message will be sent to * @msg: pointer to the message data to send * @size: size of the message to send (in bytes), including the header. * @gfp_flags: flags for memory allocation. * * Returns: %0 if ok, negative errno code on error * * Description: * * Allocates an skb that will contain the message to send to user * space over the messaging pipe and initializes it, copying the * payload. * * Once this call is done, you can deliver it with * wimax_msg_send(). * * IMPORTANT: * * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. */ struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev, const char *pipe_name, const void *msg, size_t size, gfp_t gfp_flags) { int result; struct device *dev = wimax_dev->net_dev->dev.parent; size_t msg_size; void *genl_msg; struct sk_buff *skb; msg_size = nla_total_size(size) + nla_total_size(sizeof(u32)) + (pipe_name ? nla_total_size(strlen(pipe_name)) : 0); result = -ENOMEM; skb = genlmsg_new(msg_size, gfp_flags); if (skb == NULL) goto error_new; genl_msg = genlmsg_put(skb, 0, 0, &wimax_gnl_family, 0, WIMAX_GNL_OP_MSG_TO_USER); if (genl_msg == NULL) { dev_err(dev, "no memory to create generic netlink message\n"); goto error_genlmsg_put; } result = nla_put_u32(skb, WIMAX_GNL_MSG_IFIDX, wimax_dev->net_dev->ifindex); if (result < 0) { dev_err(dev, "no memory to add ifindex attribute\n"); goto error_nla_put; } if (pipe_name) { result = nla_put_string(skb, WIMAX_GNL_MSG_PIPE_NAME, pipe_name); if (result < 0) { dev_err(dev, "no memory to add pipe_name attribute\n"); goto error_nla_put; } } result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg); if (result < 0) { dev_err(dev, "no memory to add payload (msg %p size %zu) in " "attribute: %d\n", msg, size, result); goto error_nla_put; } genlmsg_end(skb, genl_msg); return skb; error_nla_put: error_genlmsg_put: error_new: nlmsg_free(skb); return ERR_PTR(result); }
static int send_log_msg(struct nl_handle *handle, struct nl_msg *msg) { int err; err = nl_send_auto_complete(handle, msg); nlmsg_free(msg); if (err < 0) return err; return nl_wait_for_ack(handle); }
/* function: send_ifaddrmsg * sends a netlink/ifaddrmsg message and hands the responses to the callbacks * type - netlink message type * flags - netlink message flags * ifa - ifaddrmsg to send * callbacks - callbacks to use with the responses */ void send_ifaddrmsg(uint16_t type, uint16_t flags, struct ifaddrmsg *ifa, struct nl_cb *callbacks) { struct nl_msg *msg = NULL; msg = nlmsg_alloc_ifaddr(type, flags, ifa); if(!msg) return; send_netlink_msg(msg, callbacks); nlmsg_free(msg); }
static int send_log_request(struct nl_sock *sk, struct nl_msg *msg) { int err; err = nl_send_auto_complete(sk, msg); nlmsg_free(msg); if (err < 0) return err; return wait_for_ack(sk); }
int nf10_reg_rd(uint32_t addr, uint32_t *val_ptr) { struct nl_msg *msg; int err; err = driver_connect(); if(err) return err; msg = nlmsg_alloc(); if(msg == NULL) { driver_disconnect(); return -NLE_NOMEM; } /* genlmsg_put will fill in the fields of the nlmsghdr and the genlmsghdr. */ genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, nf10_genl_family, 0, 0, NF10_GENL_C_REG_RD, NF10_GENL_FAMILY_VERSION); nla_put_u32(msg, NF10_GENL_A_ADDR32, addr); /* nl_send_auto will automatically fill in the PID and the sequence number, * and also add an NLM_F_REQUEST flag. It will also add an NLM_F_ACK * flag unless the netlink socket has the NL_NO_AUTO_ACK flag set. */ err = nl_send_auto(nf10_genl_sock, msg); if(err < 0) { nlmsg_free(msg); driver_disconnect(); return err; } nlmsg_free(msg); nl_socket_modify_cb(nf10_genl_sock, NL_CB_VALID, NL_CB_CUSTOM, nf10_reg_rd_recv_msg_cb, (void*)val_ptr); err = nl_recvmsgs_default(nf10_genl_sock); driver_disconnect(); return err; }
static int nl80211_create_iface_once(struct nl80211_data* ctx, int(*handler)(struct nl_msg *, void *), void *arg) { int ret = -ENOBUFS; struct nl_msg *msg; struct nlattr *flags; int ifidx; const char *ifname = ctx->monitor_name; fprintf(stderr, "nl80211: Create monitor interface %s\n", ifname); msg = nl80211_cmd_msg(ctx, 0, NL80211_CMD_NEW_INTERFACE); if (!msg) goto fail; if (nla_put_string(msg, NL80211_ATTR_IFNAME, ifname)) goto fail; if (nla_put_u32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR)) goto fail; flags = nla_nest_start(msg, NL80211_ATTR_MNTR_FLAGS); if (!flags) goto fail; if (nla_put_flag(msg, NL80211_MNTR_FLAG_COOK_FRAMES)) goto fail; nla_nest_end(msg, flags); /* * Tell cfg80211 that the interface belongs to the socket that created * it, and the interface should be deleted when the socket is closed. */ if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER)) goto fail; ret = send_and_recv_msgs(ctx, msg, handler, arg); msg = NULL; if (ret) { fail: nlmsg_free(msg); fprintf(stderr, "nl80211: Failed to create Monitor interface: %d (%s)\n", ret, strerror(-ret)); return -1; } ifidx = if_nametoindex(ifname); fprintf(stderr, "nl80211: New interface %s created at ifindex=%d\n", ifname, ifidx); if (ifidx <= 0) return -1; return ifidx; }
int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags, struct nl_msg **result) { struct nl_msg *msg; struct rtnl_tc_ops *ops; struct tcmsg tchdr = { .tcm_family = AF_UNSPEC, .tcm_ifindex = tc->tc_ifindex, .tcm_handle = tc->tc_handle, .tcm_parent = tc->tc_parent, }; int err = -NLE_MSGSIZE; msg = nlmsg_alloc_simple(type, flags); if (!msg) return -NLE_NOMEM; if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) goto nla_put_failure; if (tc->ce_mask & TCA_ATTR_KIND) NLA_PUT_STRING(msg, TCA_KIND, tc->tc_kind); ops = rtnl_tc_get_ops(tc); if (ops && (ops->to_msg_fill || ops->to_msg_fill_raw)) { struct nlattr *opts; void *data = rtnl_tc_data(tc); if (ops->to_msg_fill) { if (!(opts = nla_nest_start(msg, TCA_OPTIONS))) goto nla_put_failure; if ((err = ops->to_msg_fill(tc, data, msg)) < 0) goto nla_put_failure; nla_nest_end(msg, opts); } else if ((err = ops->to_msg_fill_raw(tc, data, msg)) < 0) goto nla_put_failure; } *result = msg; return 0; nla_put_failure: nlmsg_free(msg); return err; } void tca_set_kind(struct rtnl_tc *t, const char *kind) { strncpy(t->tc_kind, kind, sizeof(t->tc_kind) - 1); t->ce_mask |= TCA_ATTR_KIND; }
static int go_offchan_freq(struct nl80211_state *state, int devidx, int freq) { struct nl_cb *cb; struct nl_cb *s_cb; struct nl_msg *msg; int err; msg = nlmsg_alloc(); if (!msg) { fprintf(stderr, "failed to allocate netlink message\n"); return 2; } cb = nl_cb_alloc(nl_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); s_cb = nl_cb_alloc(nl_debug ? NL_CB_DEBUG : NL_CB_DEFAULT); if (!cb || !s_cb) { fprintf(stderr, "failed to allocate netlink callbacks\n"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 0, NL80211_CMD_REMAIN_ON_CHANNEL, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); /* 5 seconds is the max allowed, values passed are in ms */ NLA_PUT_U32(msg, NL80211_ATTR_DURATION, 60); nl_socket_set_cb(state->nl_sock, s_cb); err = nl_send_auto_complete(state->nl_sock, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); while (err > 0) nl_recvmsgs(state->nl_sock, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; nla_put_failure: fprintf(stderr, "building message failed\n"); return 2; }
int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info) { struct sk_buff *msg; struct net_device *dev = NULL; int rc = -ENOBUFS; struct ieee802154_mlme_ops *ops; void *hdr; struct ieee802154_llsec_params params; pr_debug("%s\n", __func__); dev = ieee802154_nl_get_dev(info); if (!dev) return -ENODEV; ops = ieee802154_mlme_ops(dev); if (!ops->llsec) { rc = -EOPNOTSUPP; goto out_dev; } msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!msg) goto out_dev; hdr = genlmsg_put(msg, 0, info->snd_seq, &nl802154_family, 0, IEEE802154_LLSEC_GETPARAMS); if (!hdr) goto out_free; rc = ops->llsec->get_params(dev, ¶ms); if (rc < 0) goto out_free; if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || nla_put_u8(msg, IEEE802154_ATTR_LLSEC_ENABLED, params.enabled) || nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVEL, params.out_level) || nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, be32_to_cpu(params.frame_counter)) || ieee802154_llsec_fill_key_id(msg, ¶ms.out_key)) goto out_free; dev_put(dev); return ieee802154_nl_reply(msg, info); out_free: nlmsg_free(msg); out_dev: dev_put(dev); return rc; }
void lowpansocket::getAddress(struct ieee802154_addr *ret, const vinterface &iface) { #if defined HAVE_LIBNL || HAVE_LIBNL3 #ifdef HAVE_LIBNL3 struct nl_sock *nl = nl_socket_alloc(); #else struct nl_handle *nl = nl_handle_alloc(); #endif unsigned char *buf = NULL; struct sockaddr_nl nla; struct nlattr *attrs[IEEE802154_ATTR_MAX+1]; struct genlmsghdr *ghdr; struct nlmsghdr *nlh; struct nl_msg *msg; int family; if (!nl) return; genl_connect(nl); /* Build and send message */ msg = nlmsg_alloc(); family = genl_ctrl_resolve(nl, "802.15.4 MAC"); genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_ECHO, IEEE802154_LIST_IFACE, 1); nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, iface.toString().c_str()); nl_send_auto_complete(nl, msg); nlmsg_free(msg); /* Receive and parse answer */ nl_recv(nl, &nla, &buf, NULL); nlh = (struct nlmsghdr*)buf; genlmsg_parse(nlh, 0, attrs, IEEE802154_ATTR_MAX, ieee802154_policy); ghdr = (genlmsghdr*)nlmsg_data(nlh); if (!attrs[IEEE802154_ATTR_SHORT_ADDR] || !attrs[IEEE802154_ATTR_SHORT_ADDR]) return; // We only handle short addresses right now ret->addr_type = IEEE802154_ADDR_SHORT; ret->pan_id = nla_get_u16(attrs[IEEE802154_ATTR_PAN_ID]); ret->short_addr = nla_get_u16(attrs[IEEE802154_ATTR_SHORT_ADDR]); free(buf); nl_close(nl); #ifdef HAVE_LIBNL3 nl_socket_free(nl); #else nl_handle_destroy(nl); #endif #endif }
TError TNlCgFilter::Create(const TNlLink &link) { TError error = TError::Success(); struct nl_msg *msg; int ret; struct tcmsg tchdr; tchdr.tcm_family = AF_UNSPEC; tchdr.tcm_ifindex = link.GetIndex(); tchdr.tcm_handle = Handle; tchdr.tcm_parent = Parent; tchdr.tcm_info = TC_H_MAKE(FilterPrio << 16, htons(ETH_P_ALL)); msg = nlmsg_alloc_simple(RTM_NEWTFILTER, NLM_F_EXCL|NLM_F_CREATE); if (!msg) return TError(EError::Unknown, "Unable to add filter: no memory"); ret = nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret)); goto free_msg; } ret = nla_put(msg, TCA_KIND, strlen(FilterType) + 1, FilterType); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret)); goto free_msg; } ret = nla_put(msg, TCA_OPTIONS, 0, NULL); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret)); goto free_msg; } L() << "netlink " << link.GetDesc() << ": add tfilter id 0x" << std::hex << Handle << " parent 0x" << Parent << std::dec << std::endl; ret = nl_send_sync(link.GetSock(), msg); if (ret) error = TError(EError::Unknown, std::string("Unable to add filter: ") + nl_geterror(ret)); if (!Exists(link)) error = TError(EError::Unknown, "BUG: created filter doesn't exist"); return error; free_msg: nlmsg_free(msg); return error; }
static int wl1251_nl_reg_read(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; u32 addr, val; int ret = 0; struct sk_buff *msg; void *hdr; if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) return -EINVAL; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); return -EINVAL; } addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); mutex_lock(&wl->mutex); val = wl1251_reg_read32(wl, addr); mutex_unlock(&wl->mutex); hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); if (IS_ERR(hdr)) { ret = PTR_ERR(hdr); goto nla_put_failure; } NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, val); ret = genlmsg_end(msg, hdr); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } return genlmsg_reply(msg, info); nla_put_failure: nlmsg_free(msg); return ret; }