/** * Add qdisc * @arg sk Netlink socket * @arg qdisc Qdisc to add * @arg flags Additional netlink message flags * * Builds a \c RTM_NEWQDISC netlink message requesting the addition * of a new qdisc and sends the message to the kernel. The configuration * of the qdisc is derived from the attributes of the specified qdisc. * * The following flags may be specified: * - \c NLM_F_CREATE: Create qdisc if it does not exist, otherwise * -NLE_OBJ_NOTFOUND is returned. * - \c NLM_F_REPLACE: If another qdisc is already attached to the * parent, replace it even if the handles mismatch. * - \c NLM_F_EXCL: Return -NLE_EXISTS if a qdisc with matching * handle exists already. * * Existing qdiscs with matching handles will be updated, unless the * flag \c NLM_F_EXCL is specified. If their handles do not match, the * error -NLE_EXISTS is returned unless the flag \c NLM_F_REPLACE is * specified in which case the existing qdisc is replaced with the new * one. If no matching qdisc exists, it will be created if the flag * \c NLM_F_CREATE is set, otherwise the error -NLE_OBJ_NOTFOUND is * returned. * * After sending, the function will wait for the ACK or an eventual * error message to be received and will therefore block until the * operation has been completed. * * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause * this function to return immediately after sending. In this case, * it is the responsibility of the caller to handle any error * messages returned. * * @return 0 on success or a negative error code. */ int rtnl_qdisc_add(struct nl_sock *sk, struct rtnl_qdisc *qdisc, int flags) { struct nl_msg *msg; int err; if ((err = rtnl_qdisc_build_add_request(qdisc, flags, &msg)) < 0) return err; return nl_send_sync(sk, msg); }
/** * Delete classifier * @arg sk Netlink socket * @arg cls Classifier to delete * @arg flags Additional netlink message flags * * Builds a \c RTM_DELTFILTER netlink message requesting the deletion * of a classifier and sends the message to the kernel. * * The message is constructed out of the following attributes: * - \c ifindex (required) * - \c prio (required) * - \c protocol (required) * - \c handle (required) * - \c parent (optional, if not specified parent equals root-qdisc) * - \c kind (optional, must match if provided) * * All other classifier attributes including all class type specific * attributes are ignored. * * After sending, the function will wait for the ACK or an eventual * error message to be received and will therefore block until the * operation has been completed. * * @note Disabling auto-ack (nl_socket_disable_auto_ack()) will cause * this function to return immediately after sending. In this case, * it is the responsibility of the caller to handle any error * messages returned. * * @return 0 on success or a negative error code. */ int rtnl_cls_delete(struct nl_sock *sk, struct rtnl_cls *cls, int flags) { struct nl_msg *msg; int err; if ((err = rtnl_cls_build_delete_request(cls, flags, &msg)) < 0) return err; return nl_send_sync(sk, msg); }
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 get_interface_info(struct config *conf) { struct nl_msg *msg; nl802154_init(conf); /* Build and send message */ nl_socket_modify_cb(conf->nl_sock, NL_CB_VALID, NL_CB_CUSTOM, nl_msg_cb, conf); msg = nlmsg_alloc(); genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, conf->nl802154_id, 0, NLM_F_DUMP, NL802154_CMD_GET_INTERFACE, 0); nla_put_string(msg, NL802154_ATTR_IFNAME, "conf->interface"); nl_send_sync(conf->nl_sock, msg); nl802154_cleanup(conf); return 0; }
/** * Query the wireless device for information * about the current connection */ bool wireless_network::query(bool accumulate) { if (!network::query(accumulate)) { return false; } struct nl_sock* sk = nl_socket_alloc(); if (sk == nullptr) { return false; } if (genl_connect(sk) < 0) { return false; } int driver_id = genl_ctrl_resolve(sk, "nl80211"); if (driver_id < 0) { nl_socket_free(sk); return false; } if (nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, scan_cb, this) != 0) { nl_socket_free(sk); return false; } struct nl_msg* msg = nlmsg_alloc(); if (msg == nullptr) { nl_socket_free(sk); return false; } if ((genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, driver_id, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0) == nullptr) || nla_put_u32(msg, NL80211_ATTR_IFINDEX, m_ifid) < 0) { nlmsg_free(msg); nl_socket_free(sk); return false; } // nl_send_sync always frees msg if (nl_send_sync(sk, msg) < 0) { nl_socket_free(sk); return false; } nl_socket_free(sk); return true; }
TError TNlLink::AddXVlan(const std::string &vlantype, const std::string &master, uint32_t type, const std::string &hw, int mtu) { TError error = TError::Success(); int ret; uint32_t masterIdx; struct nl_msg *msg; struct nlattr *linkinfo, *infodata; struct ifinfomsg ifi = { 0 }; struct ether_addr *ea = nullptr; auto Name = GetName(); if (hw.length()) { // FIXME THREADS ea = ether_aton(hw.c_str()); if (!ea) return TError(EError::Unknown, "Invalid " + vlantype + " mac address " + hw); } TNlLink masterLink(Nl, master); error = masterLink.Load(); if (error) return error; masterIdx = masterLink.GetIndex(); msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_CREATE); if (!msg) return TError(EError::Unknown, "Unable to add " + vlantype + ": no memory"); ret = nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO); if (ret < 0) { error = TError(EError::Unknown, "Unable to add " + vlantype + ": " + nl_geterror(ret)); goto free_msg; } /* link configuration */ ret = nla_put(msg, IFLA_LINK, sizeof(uint32_t), &masterIdx); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_LINK: ") + nl_geterror(ret)); goto free_msg; } ret = nla_put(msg, IFLA_IFNAME, Name.length() + 1, Name.c_str()); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_IFNAME: ") + nl_geterror(ret)); goto free_msg; } if (mtu > 0) { ret = nla_put(msg, IFLA_MTU, sizeof(int), &mtu); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_MTU: ") + nl_geterror(ret)); goto free_msg; } } if (ea) { struct nl_addr *addr = nl_addr_build(AF_LLC, ea, ETH_ALEN); ret = nla_put(msg, IFLA_ADDRESS, nl_addr_get_len(addr), nl_addr_get_binary_addr(addr)); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_ADDRESS: ") + nl_geterror(ret)); goto free_msg; } nl_addr_put(addr); } /* link type */ linkinfo = nla_nest_start(msg, IFLA_LINKINFO); if (!linkinfo) { error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_LINKINFO"); goto free_msg; } ret = nla_put(msg, IFLA_INFO_KIND, vlantype.length() + 1, vlantype.c_str()); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_INFO_KIND: ") + nl_geterror(ret)); goto free_msg; } /* xvlan specific */ infodata = nla_nest_start(msg, IFLA_INFO_DATA); if (!infodata) { error = TError(EError::Unknown, "Unable to add " + vlantype + ": can't nest IFLA_INFO_DATA"); goto free_msg; } if (vlantype == "macvlan") { ret = nla_put(msg, IFLA_MACVLAN_MODE, sizeof(uint32_t), &type); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_MACVLAN_MODE: ") + nl_geterror(ret)); goto free_msg; } #ifdef IFLA_IPVLAN_MAX } else if (vlantype == "ipvlan") { uint16_t mode = type; ret = nla_put(msg, IFLA_IPVLAN_MODE, sizeof(uint16_t), &mode); if (ret < 0) { error = TError(EError::Unknown, std::string("Unable to put IFLA_IPVLAN_MODE: ") + nl_geterror(ret)); goto free_msg; } #endif } nla_nest_end(msg, infodata); nla_nest_end(msg, linkinfo); L() << "netlink: add " << vlantype << " " << Name << " master " << master << " type " << type << " hw " << hw << " mtu " << mtu << std::endl; ret = nl_send_sync(GetSock(), msg); if (ret) return Error(ret, "Cannot add " + vlantype); return Load(); free_msg: nlmsg_free(msg); return error; }