/* * Netlink helper functions for driver wrappers * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "priv_netlink.h" #include "netlink.h" int netlink_send_oper_ifla(int sock, int ifindex, int linkmode, int operstate) { struct { struct nlmsghdr hdr; struct ifinfomsg ifinfo; char opts[16]; } req; struct rtattr *rta; static int nl_seq; ssize_t ret; os_memset(&req, 0, sizeof(req)); req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.hdr.nlmsg_type = RTM_SETLINK; req.hdr.nlmsg_flags = NLM_F_REQUEST; req.hdr.nlmsg_seq = ++nl_seq; req.hdr.nlmsg_pid = 0; req.ifinfo.ifi_family = AF_UNSPEC; req.ifinfo.ifi_type = 0; req.ifinfo.ifi_index = ifindex; req.ifinfo.ifi_flags = 0; req.ifinfo.ifi_change = 0; if (linkmode != -1) { rta = aliasing_hide_typecast( ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)), struct rtattr); rta->rta_type = IFLA_LINKMODE; rta->rta_len = RTA_LENGTH(sizeof(char)); *((char *) RTA_DATA(rta)) = linkmode; req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + RTA_LENGTH(sizeof(char)); } if (operstate != -1) { rta = aliasing_hide_typecast( ((char *) &req + NLMSG_ALIGN(req.hdr.nlmsg_len)), struct rtattr); rta->rta_type = IFLA_OPERSTATE; rta->rta_len = RTA_LENGTH(sizeof(char)); *((char *) RTA_DATA(rta)) = operstate; req.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) + RTA_LENGTH(sizeof(char)); } wpa_printf(MSG_DEBUG, "netlink: Operstate: linkmode=%d, operstate=%d", linkmode, operstate); ret = send(sock, &req, req.hdr.nlmsg_len, 0); if (ret < 0) { wpa_printf(MSG_DEBUG, "netlink: Sending operstate IFLA " "failed: %s (assume operstate is not supported)", strerror(errno)); } return ret < 0 ? -1 : 0; }