Есть ли способ программно установить MTU интерфейса с помощью C в Linux?

В данный момент моя программа делает system() вызов ifconfig для этого.

Это выглядит немного запутанно — возможно, ifconfig находится не на пути или в каком-то нестандартном месте. И тогда мне нужно будет проверить эквивалент iproute2 в случае сбоя.

Есть ли способ установить это программно с помощью C?


person James    schedule 29.07.2014    source источник


Ответы (2)


Вы можете установить поле SIOCSIFMTU в вызове ioctl примерно так:

struct ifreq ifr; 
ifr.ifr_addr.sa_family = AF_INET;//address family
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));//interface name where you want to set the MTU
ifr.ifr_mtu = 9100; //your MTU size here
if (ioctl(sockfd, SIOCSIFMTU, (caddr_t)&ifr) < 0)
  //failed to set MTU. handle error.

Приведенный выше код установит MTU устройства (как в ifr.name), используя поле ifr_mtu в структуре ifreq.

См.: http://linux.die.net/man/7/netdevice

person askmish    schedule 30.07.2014
comment
Спасибо, это работает! Любая идея, почему для этого нужен сокет fd? Я всегда думал, что MTU - это свойство ссылки, а не сокета. - person James; 30.07.2014
comment
Цитата со страницы руководства: Linux поддерживает стандартные ioctl для настройки сетевых устройств. Их можно использовать в любом файловом дескрипторе сокета, независимо от семейства или типа. Они передают структуру ifreq. См.: linux.die.net/man/7/netdevice - person askmish; 31.07.2014

Вы также можете использовать netlink. Полный пример:

#include <stdio.h>
#include <string.h>
#include <net/if.h>
#include <sys/socket.h>
#include <linux/rtnetlink.h>

#define IFACE_NAME "enp5s0"

int main(void) {
     int ret, nl_sock;
     unsigned int mtu = 8000;
     struct rtattr  *rta;
     struct {
          struct nlmsghdr nh;
          struct ifinfomsg  ifinfo;
          char   attrbuf[512];
     } req;

     nl_sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
     if(nl_sock < 0) {
          perror("socket():");
          return -1;
     }

     memset(&req, 0, sizeof req);
     req.nh.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg));
     req.nh.nlmsg_flags = NLM_F_REQUEST;
     req.nh.nlmsg_type  = RTM_NEWLINK; // RTM_SETLINK
     req.ifinfo.ifi_family = AF_UNSPEC;
     req.ifinfo.ifi_index  = if_nametoindex(IFACE_NAME);
     if(!req.ifinfo.ifi_index) {
          perror("if_nametoindex():");
          return -1;
     }
     printf("%s index: %d\n", IFACE_NAME, req.ifinfo.ifi_index);
     req.ifinfo.ifi_change = 0xffffffff;
     rta = (struct rtattr *)(((char *) &req) + NLMSG_ALIGN(req.nh.nlmsg_len));
     rta->rta_type = IFLA_MTU;
     rta->rta_len = RTA_LENGTH(sizeof(unsigned int));
     req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + RTA_LENGTH(sizeof mtu);
     memcpy(RTA_DATA(rta), &mtu, sizeof mtu);

     ret = send(nl_sock, &req, req.nh.nlmsg_len, 0);
     if(ret < 0) {
          perror("send():");
          return -1;
     }

     return 0;
}

Также читайте: rtnetlink(3), rtnetlink(7)

person red0ct    schedule 04.12.2019