1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
/* Source: socat.c */
/* Copyright Gerhard Rieger and contributors (see file CHANGES) */
/* Published under the GNU General Public License V.2, see file COPYING */
/* This file contains code for the netlink operations */
#include "xiosysincludes.h"
#include "xioopen.h"
#include "xio-netlink.h"
#if HAVE_LINUX_RTNETLINK_H
int xio_netlink_mtu(
int interface_index,
unsigned int mtu)
{
/* For request */
struct {
struct nlmsghdr nh;
struct ifinfomsg intf;
char attrbuf[512];
} req;
struct rtattr *rta;
int rtnetlink_sk;
/* For answer */
int len;
struct nlmsghdr buf[8192/sizeof(struct nlmsghdr)];
struct iovec iov = { buf, sizeof(buf) };
struct sockaddr_nl sa;
struct msghdr rtmsg = { &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
struct nlmsghdr *nh;
Info2("Setting interface %d MTU to %u using netlink", interface_index, mtu);
/* Send the modified attributes - rtnetlink(7) */
rtnetlink_sk = Socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (rtnetlink_sk < 0) {
Error3("xio_netlink_mtu(index=%d, mtu=%u): socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE): %s",
interface_index, mtu, strerror(errno));
return STAT_NORETRY;
}
memset(&req, 0, sizeof(req));
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.intf));
req.nh.nlmsg_flags = NLM_F_REQUEST;
req.nh.nlmsg_type = RTM_NEWLINK;
req.intf.ifi_family = AF_UNSPEC;
req.intf.ifi_index = interface_index;
req.intf.ifi_change = 0xffffffff; /* ??? */
req.intf.ifi_change = 0x0; /* ??? */
rta = (struct rtattr *)(((char *) &req) +
NLMSG_ALIGN(req.nh.nlmsg_len));
rta->rta_type = IFLA_MTU;
rta->rta_len = RTA_LENGTH(sizeof(mtu));
req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) +
RTA_LENGTH(sizeof(mtu));
req.nh.nlmsg_flags |= NLM_F_ACK; /* netlink(7) */
memcpy(RTA_DATA(rta), &mtu, sizeof(mtu));
if (Send(rtnetlink_sk, &req, req.nh.nlmsg_len, 0) < 0) {
Error3("xio_netlink_mtu(index=%d, mtu=%u): send(): %s",
interface_index, mtu, strerror(errno));
Close(rtnetlink_sk);
return STAT_NORETRY;
}
/* Try to read the answer - netlink(7) */
if ((len = Recvmsg(rtnetlink_sk, &rtmsg, MSG_DONTWAIT)) < 0) {
Warn3("xio_netlink_mtu(index=%d, mtu=%u): recvmsg(): %s",
interface_index, mtu, strerror(errno));
Close(rtnetlink_sk);
return STAT_NORETRY;
}
for (nh = (struct nlmsghdr *)buf; NLMSG_OK (nh, len);
nh = NLMSG_NEXT(nh, len)) {
/* The end of multipart message */
if (nh->nlmsg_type == NLMSG_DONE) {
Close(rtnetlink_sk);
return STAT_OK;
}
if (nh->nlmsg_type == NLMSG_ERROR) {
/* Do some error handling */
struct nlmsgerr *err;
err = (struct nlmsgerr *)(NLMSG_DATA(&buf));
if (err->error != 0) {
Error3("xio_netlink_mtu(index=%d, mtu=%u): rtnetlink: %s",
interface_index, mtu, strerror(-err->error));
Close(rtnetlink_sk);
return STAT_NORETRY;
}
/* It is the acknowledgement, good */
}
/* Continue with parsing payload */
}
Close(rtnetlink_sk);
return 0;
}
#endif /* HAVE_LINUX_RTNETLINK_H */
|