struct set_req {
struct nlmsghdr hdr;
struct ifinfomsg ifi;
char payload[1024];
};
#define NLMSG_TAIL(nmsg) ((struct rtattr*)(((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
int addattr_l(struct nlmsghdr* n, unsigned int maxlen, int type, const void* data, int alen) {
unsigned int len = RTA_LENGTH(alen);
struct rtattr* rta;
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n", maxlen);
return -1;
}
rta = NLMSG_TAIL(n);
rta->rta_type = type;
rta->rta_len = len;
if (alen) memcpy(RTA_DATA(rta), data, alen);
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
return 0;
}
struct rtattr* addattr_nest(struct nlmsghdr* n, int maxlen, int type) {
struct rtattr* nest = NLMSG_TAIL(n);
addattr_l(n, maxlen, type, nullptr, 0);
return nest;
}
int addattr_nest_end(struct nlmsghdr* n, struct rtattr* nest) {
nest->rta_len = (char*)NLMSG_TAIL(n) - (char*)nest;
return n->nlmsg_len;
}
int addattr32(struct nlmsghdr* n, int maxlen, int type, __u32 data) {
return addattr_l(n, maxlen, type, &data, sizeof(__u32));
}
bool setBitRate(const std::string& ifname, uint32_t bitrate) {
int ret;
can_bittiming bt{};
rtattr *linkinfo = nullptr, *data = nullptr;
const char* type = "can";
set_seq req{};
int ifindex = -1;
int sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(ifinfomsg));
req.hdr.nlmsg_flags = NLM_F_REQUEST;
req.hdr.nlmsg_type = RTM_NEWLINK;
req.ifi.ifi_family = AF_UNSPEC;
ifindex = if_nametoindex(ifname.c_str());
if (ifindex == 0) {
fprintf(stderr, "no dev %s\n", ifname.c_str());
return false;
}
addattr32(&req.hdr, sizeof(req), IFLA_LINK, ifindex);
req.ifi.ifi_index = ifindex;
linkinfo = addattr_nest(&req.hdr, sizeof(req), IFLA_LINKINFO);
addattr_l(&req.hdr, sizeof(req), IFLA_INFO_KIND, (void*)type, strlen(type));
data = addattr_nest(&req.hdr, sizeof(req), IFLA_INFO_DATA);
addattr_l(&req.hdr, 1024, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
addattr_nest_end(&req.hdr, data);
addattr_nest_end(&req.hdr, linkinfo);
iovec iov = {
.iov_base = &req.hdr,
.iov_len = req.hdr.nlmsg_len,
};
sockaddr_nl nladdr = {
.nl_family = AF_NETLINK,
};
msghdr msg = {
.msg_name = &nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};
req.hdr.nlmsg_flags |= NLM_F_ACK;
req.hdr.nlmsg_seq = 1;
ret = sendmsg(sock, &msg, 0);
if (ret < 0) {
PLOG(ERROR) << "sendmsg FAIL:" << strerror(errno);
return false;
}
return ret > 0;
}
struct netlink_req {
struct nlmsghdr hdr;
struct ifinfomsg ifi;
};
static void fill_message(struct netlink_req *req, const std::string &ifname) {
req->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(req->ifi));
req->hdr.nlmsg_type = RTM_NEWLINK;
req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
req->ifi.ifi_family = AF_UNSPEC;
req->ifi.ifi_index = if_nametoindex(ifname.c_str());
}
bool ifup(const std::string &ifname) {
struct netlink_req req{};
struct sockaddr_nl kernel_sa{};
int ret;
int sock = socket_create();
if (sock < 0)
return -1;
fill_message(&req, ifname);
req.ifi.ifi_change = IFF_UP;
req.ifi.ifi_flags |= IFF_UP;
kernel_sa.nl_family = AF_NETLINK;
struct iovec iov = {
&req.hdr,
req.hdr.nlmsg_len,
};
struct msghdr msg = {
&kernel_sa,
sizeof(kernel_sa),
&iov,
1,
nullptr,
0,
0,
};
ret = sendmsg(sock, &msg, 0);
close(sock);
return ret > 0;
}
bool ifdown(const std::string &ifname) {
struct netlink_req req{};
struct sockaddr_nl kernel_sa{};
int ret;
int sock = socket_create();
if (sock < 0)
return -1;
fill_message(&req, ifname);
req.ifi.ifi_change = IFF_UP;
req.ifi.ifi_flags &= ~IFF_UP;
kernel_sa.nl_family = AF_NETLINK;
struct iovec iov = {
&req.hdr,
req.hdr.nlmsg_len,
};
struct msghdr msg = {
&kernel_sa,
sizeof(kernel_sa),
&iov,
1,
nullptr,
0,
0,
};
ret = sendmsg(sock, &msg, 0);
close(sock);
return ret > 0;
}
以上代码摘抄自iprout2