netlink进行网卡重命名

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/netlink.h>

#define MAX_PAYLOAD 1024  // 最大负载长度
#define NLMSG_ERROR 0x2    // 消息类型
  1. 初始化Netlink Socket

      初始化Netlink Socket,创建一个netlink_init函数,用于创建Netlink Socket并绑定到NETLINK_ROUTE

int netlink_init(struct sockaddr_nl *nladdr) {
    int sockfd;

    sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sockfd < 0) {
        perror("socket");
        return -1;
    }

    memset(nladdr, 0, sizeof(struct sockaddr_nl));
    nladdr->nl_family = AF_NETLINK;
    nladdr->nl_groups = RTMGRP_LINK;  // 绑定到link组

    if (bind(sockfd, (struct sockaddr *)nladdr, sizeof(struct sockaddr_nl)) < 0) {
        perror("bind");
        close(sockfd);
        return -1;
    }

    return sockfd;
}

  1. 创建Netlink消息

接下来创建Netlink消息,包括Netlink消息头和Netlink消息负载

void build_nlmsg(struct nlmsghdr *nlh, int ifindex, int flags) {
    memset(nlh, 0, NLMSG_LENGTH(sizeof(struct ifinfomsg)));

    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nlh->nlmsg_type = RTM_NEWLINK;
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    nlh->nlmsg_seq = 1;
    nlh->nlmsg_pid = getpid();

    struct ifinfomsg *ifm = (struct ifinfomsg *)NLMSG_DATA(nlh);
    ifm->ifi_family = AF_UNSPEC;
    ifm->ifi_type = 0;
    ifm->ifi_index = ifindex;
    ifm->ifi_flags = flags;
    ifm->ifi_change = 0xffffffff;
}

int send_nlmsg(int sockfd, struct nlmsghdr *nlh, struct sockaddr_nl *nladdr) {
    int ret;

    struct iovec iov = { nlh, nlh->nlmsg_len };
    struct msghdr msg = { nladdr, sizeof(struct sockaddr_nl), &iov, 1, NULL, 0, 0 };
    ret = sendmsg(sockfd, &msg, 0);
    if (ret < 0) {
        perror("sendmsg");
        return -1;
    }

    memset(nlh, 0, NLMSG_LENGTH(sizeof(struct ifinfomsg

struct ifinfomsg是Linux内核中用于表示网络接口信息的结构体,其定义如下

struct ifinfomsg {
    unsigned char ifi_family;   // 接口地址族,通常为AF_UNSPEC或AF_INET6
    unsigned short ifi_type;    // 接口类型
    int ifi_index;              // 接口索引
    unsigned int ifi_flags;     // 接口标志,如IFF_UP等
    unsigned int ifi_change;    // 接口状态改变标志
};

在使用Netlink更改网络接口的过程中,可以使用struct ifinfomsg结构体来表示要修改的网络接口的相关信息,包括接口类型、接口索引、接口标志等。在Netlink消息负载中,使用NLMSG_DATA宏来获取struct ifinfomsg结构体的地址,然后填充相关字段即可。

使用struct ifinfomsg结构体的场景包括但不限于:

  1. 在Netlink Socket中使用RTM_NEWLINK消息来创建一个新的网络接口。
  2. 在Netlink Socket中使用RTM_DELLINK消息来删除一个网络接口。
  3. 在Netlink Socket中使用RTM_SETLINK消息来修改一个网络接口的属性,比如接口标志等。

在Netlink Socket中使用RTM_NEWLINK消息来创建一个新的网络接口时,如果填充的接口名称为eth%d,内核会根据当前系统中已经存在的网络接口的数量来确定新接口的名称。

具体来说,内核会在已有的网络接口名称中查找最小的未使用的名称,并将其分配给新的网络接口。对于以eth%d为模板的接口名称,内核会从eth0开始往后逐个尝试,直到找到一个未被占用的名称为止。

因此,在使用Netlink Socket来创建一个新的网络接口时,如果填充的接口名称为eth%d,而系统中已经存在了一些网络接口,那么最终分配给新接口的名称可能会不是eth%d,而是根据内核的算法计算出的一个实际名称。

修改网卡mtu值

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#define BUFSIZE 8192

int main(int argc, char **argv) {
    struct nlmsghdr *nh;
    struct ifinfomsg *ifinfo;
    struct rtattr *attr;
    char buffer[BUFSIZE];
    int sockfd, len;

    // 创建netlink socket
    if ((sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
        perror("socket");
        return -1;
    }

    // 准备请求消息
    memset(buffer, 0, sizeof(buffer));
    nh = (struct nlmsghdr *)buffer;
    ifinfo = (struct ifinfomsg *)NLMSG_DATA(nh);
    attr = (struct rtattr *)(((char *)ifinfo) + NLMSG_ALIGN(sizeof(struct ifinfomsg)));

    nh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    nh->nlmsg_type = RTM_NEWLINK;

    ifinfo->ifi_family = AF_UNSPEC;
    ifinfo->ifi_type = ARPHRD_ETHER;
    ifinfo->ifi_index = if_nametoindex("eth0");
    ifinfo->ifi_flags = IFF_UP;
    ifinfo->ifi_change = 0xFFFFFFFF;

    // 添加MTU属性
    attr->rta_type = IFLA_MTU;
    attr->rta_len = RTA_LENGTH(sizeof(unsigned int));
    *(unsigned int *)RTA_DATA(attr) = 1500;

    nh->nlmsg_len += RTA_ALIGN(attr->rta_len);
    nh->nlmsg_flags |= NLM_F_REQUEST | NLM_F_ACK;

    // 发送netlink消息
    len = send(sockfd, nh, nh->nlmsg_len, 0);
    if (len == -1) {
        perror("send");
        close(sockfd);
        return -1;
    }

    // 接收netlink回复
    len = recv(sockfd, buffer, BUFSIZE, 0);
    if (len == -1) {
        perror("recv");
        close(sockfd);
        return -1;
    }

    // 处理netlink回复
    for (nh = (struct nlmsghdr *)buffer; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
        if (nh->nlmsg_type == NLMSG_ERROR) {
            perror("NLMSG_ERROR");
            close(sockfd);
            return -1;
        }
    }

    printf("MTU has been set to 1500.\n");
    close(sockfd);
    return 0;
}

 

实现将网卡eth0改名称为eth1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#define BUFSIZE 8192

int main(int argc, char **argv) {
    struct nlmsghdr *nh;
    struct ifinfomsg *ifinfo;
    struct rtattr *attr;
    char buffer[BUFSIZE];
    int sockfd, len;

    // 创建netlink socket
    if ((sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) {
        perror("socket");
        return -1;
    }

    // 准备请求消息
    memset(buffer, 0, sizeof(buffer));
    nh = (struct nlmsghdr *)buffer;
    ifinfo = (struct ifinfomsg *)NLMSG_DATA(nh);
    attr = (struct rtattr *)(((char *)ifinfo) + NLMSG_ALIGN(sizeof(struct ifinfomsg)));

    nh->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    nh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    nh->nlmsg_type = RTM_NEWLINK;

    ifinfo->ifi_family = AF_UNSPEC;
    ifinfo->ifi_type = ARPHRD_ETHER;
    ifinfo->ifi_index = if_nametoindex("eth0");
    ifinfo->ifi_flags = IFF_UP;
    ifinfo->ifi_change = 0xFFFFFFFF;

    // 添加新接口名属性
    attr->rta_type = IFLA_IFNAME;
    attr->rta_len = RTA_LENGTH(strlen("eth1")+1);
    strcpy(RTA_DATA(attr), "eth1");

    nh->nlmsg_len += RTA_ALIGN(attr->rta_len);
    nh->nlmsg_flags |= NLM_F_REQUEST | NLM_F_ACK;

    // 发送netlink消息
    len = send(sockfd, nh, nh->nlmsg_len, 0);
    if (len == -1) {
        perror("send");
        close(sockfd);
        return -1;
    }

    // 接收netlink回复
    len = recv(sockfd, buffer, BUFSIZE, 0);
    if (len == -1) {
        perror("recv");
        close(sockfd);
        return -1;
    }

    // 处理netlink回复
    for (nh = (struct nlmsghdr *)buffer; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
        if (nh->nlmsg_type == NLMSG_ERROR) {
            perror("NLMSG_ERROR");
            close(sockfd);
            return -1;
        }
    }

    printf("Interface name has been set to eth1.\n");
    close(sockfd);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值