Linux下C语言操作网卡的几个代码实例?特别实用

发布时间:2024-02-28  

那么如何使用直接操作?

本文引用地址:

比如读写IP地址、读写MAC地址等。

一、原理

主要通过系统用socket()、ioctl()、实现

int socket(int domain, int type, int protocol);
功能:
    创建套接字
参数:
 domain: 
  Name                Purpose                          Man page
  AF_UNIX, AF_LOCAL   Local communication              unix(7)
  AF_INET             IPv4 Internet protocols          ip(7)

 type:
  SOCK_STREAM     Provides sequenced, reliable, two-way, connection-based                      byte  streams.  An out-of-band data transmission mecha‐
                      nism may be supported.
      SOCK_DGRAM      Supports datagrams (connectionless, unreliable messages
                      of a fixed maximum length).
 protocol:
  通常为0
返回值:
 成功:新的套接字的文件描述符
 失败:错误码,负值
int ioctl(int fd, unsigned long request, ...);
参数:
   fd :文件描述符
   request:命令
   ... :参数

其中网络用到的request定义头文件位于:

/usr/include/linux/sockios.h
/* Linux-specific socket ioctls */#define SIOCINQ  FIONREAD#define SIOCOUTQ TIOCOUTQ        /* output queue size (not sent + not acked) *//* Routing table calls. */#define SIOCADDRT 0x890B  /* add routing table entry */#define SIOCDELRT 0x890C  /* delete routing table entry */#define SIOCRTMSG 0x890D  /* call to routing system *//* Socket configuration controls. */#define SIOCGIFNAME 0x8910  /* get iface name  */#define SIOCSIFLINK 0x8911  /* set iface channel  */#define SIOCGIFCONF 0x8912  /* get iface list  */#define SIOCGIFFLAGS 0x8913  /* get flags   */#define SIOCSIFFLAGS 0x8914  /* set flags   */#define SIOCGIFADDR 0x8915  /* get PA address  */#define SIOCSIFADDR 0x8916  /* set PA address  */#define SIOCGIFDSTADDR 0x8917  /* get remote PA address */#define SIOCSIFDSTADDR 0x8918  /* set remote PA address */#define SIOCGIFBRDADDR 0x8919  /* get broadcast PA address */#define SIOCSIFBRDADDR 0x891a  /* set broadcast PA address */#define SIOCGIFNETMASK 0x891b  /* get network PA mask  */#define SIOCSIFNETMASK 0x891c  /* set network PA mask  */#define SIOCGIFMETRIC 0x891d  /* get metric   */#define SIOCSIFMETRIC 0x891e  /* set metric   */#define SIOCGIFMEM 0x891f  /* get memory address (BSD) */#define SIOCSIFMEM 0x8920  /* set memory address (BSD) */#define SIOCGIFMTU 0x8921  /* get MTU size   */#define SIOCSIFMTU 0x8922  /* set MTU size   */#define SIOCSIFNAME 0x8923  /* set interface name */#define SIOCSIFHWADDR 0x8924  /* set hardware address  */#define SIOCGIFENCAP 0x8925  /* get/set encapsulations       */#define SIOCSIFENCAP 0x8926  #define SIOCGIFHWADDR 0x8927  /* Get hardware address  */#define SIOCGIFSLAVE 0x8929  /* Driver slaving support */#define SIOCSIFSLAVE 0x8930#define SIOCADDMULTI 0x8931  /* Multicast address lists */#define SIOCDELMULTI 0x8932#define SIOCGIFINDEX 0x8933  /* name -> if_index mapping */#define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */#define SIOCSIFPFLAGS 0x8934  /* set/get extended flags set */#define SIOCGIFPFLAGS 0x8935#define SIOCDIFADDR 0x8936  /* delete PA address  */#define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */#define SIOCGIFCOUNT 0x8938  /* get number of devices */……

其中ioctl的参数需要借助结构体struct ifreq, 定义头文件:

/usr/include/linux/if.h
#if __UAPI_DEF_IF_IFREQstruct ifreq {#define IFHWADDRLEN 6
 union
 {  char ifrn_name[IFNAMSIZ];  /* if name, e.g. "en0" */
 } ifr_ifrn; 
 union {  struct sockaddr ifru_addr;
  struct sockaddr ifru_dstaddr;
  struct sockaddr ifru_broadaddr;
  struct sockaddr ifru_netmask;
  struct  sockaddr ifru_hwaddr;
  short ifru_flags;  int ifru_ivalue;  int ifru_mtu;  struct  ifmap ifru_map;
  char ifru_slave[IFNAMSIZ]; /* Just fits the size */
  char ifru_newname[IFNAMSIZ];  void * ifru_data;  struct if_settings ifru_settings;
 } ifr_ifru;
};#endif /* __UAPI_DEF_IF_IFREQ */#define ifr_name ifr_ifrn.ifrn_name /* interface name  */#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address   */#define ifr_addr ifr_ifru.ifru_addr /* address  */#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */#define ifr_flags ifr_ifru.ifru_flags /* flags  */#define ifr_metric ifr_ifru.ifru_ivalue /* metric  */#define ifr_mtu  ifr_ifru.ifru_mtu /* mtu   */#define ifr_map  ifr_ifru.ifru_map /* device map  */#define ifr_slave ifr_ifru.ifru_slave /* slave device  */#define ifr_data ifr_ifru.ifru_data /* for use by interface */#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */#define ifr_bandwidth ifr_ifru.ifru_ivalue    /* link bandwidth */#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length  */#define ifr_newname ifr_ifru.ifru_newname /* New name  */#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/

二、函数实现

下面将实现不同功能的函数一一列举。

0. 列出所有可用

int list_all_port(){        struct ifconf ifconf;
        struct ifreq *ifr;
        int m, n, s, fd;        if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {            return -11;
        }

        s = sizeof(struct ifreq)*5;        for (;;) {
            ifr = malloc(s);

            ifconf.ifc_len = s;
            ifconf.ifc_req = ifr;            
            if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0) {
    perror("SIOCGIFCONF:");                free(ifr);
                close(fd);                return 1;
            }                
            
            if (ifconf.ifc_len != s)                break;                
            free(ifr);
            s *= 2;
        }

        close(fd);
        
        m = ifconf.ifc_len/sizeof(struct ifreq);        for (n = 0; n < m; n++)
  {   printf("port:t%sn",ifconf.ifc_req[n].ifr_name);
  }        free(ifr);
}

1. 获取指定网卡IP

int getLocalIp(const char *eth, char *ip) {    struct ifreq ifr;
    struct sockaddr_in sin;
    int fd;
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {        return -1;
    }    strcpy(ifr.ifr_name, eth);    if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) {
        close(fd);        return -1;
    }    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));
    close(fd);    return 0;
}

2. 设置本网卡IP地址

int setIpAddrManual(const char *eth, char *ipstr) {    int fd;    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {        return -1;
    }    strcpy(ifr.ifr_name, eth); sin.sin_addr.s_addr = inet_addr(ipstr); 
 sin.sin_family = AF_INET;    memcpy(&ifr.ifr_addr, &sin, sizeof(sin)); 
    if (ioctl(fd, SIOCSIFADDR, &ifr) < 0)
    {
     perror("");
        close(fd);        return -1;
    }
    close(fd);    return 0;
}

3. 获取本机网卡Mac地址

int getLocalMac(const char *eth, char *mac) {    int fd;    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {        return -1;
    }    strcpy(ifr.ifr_name, eth);    if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
    {
        close(fd);        return -1;
    }   snprintf(mac,18, "%02x:%02x:%02x:%02x:%02x:%02x",
         (unsigned char) ifr.ifr_hwaddr.sa_data[0],
         (unsigned char) ifr.ifr_hwaddr.sa_data[1],
         (unsigned char) ifr.ifr_hwaddr.sa_data[2],
         (unsigned char) ifr.ifr_hwaddr.sa_data[3],
         (unsigned char) ifr.ifr_hwaddr.sa_data[4],
         (unsigned char) ifr.ifr_hwaddr.sa_data[5]);
    close(fd);    return 0;

}

4. 设置网卡mac地址

/*
support format [00:11:22:33:44:55]
*/#define MAC_ARRAY(mac_array)  (unsigned int *)&mac_array[0],(unsigned int *)&mac_array[1],(unsigned int *)&mac_array[2],(unsigned int *)&mac_array[3],(unsigned int *)&mac_array[4],(unsigned int *)&mac_array[5] int setLocalMac(const char *eth, char *mac) {    int fd;    struct ifreq ifr;
 unsigned char mac_array[6] = {0};
 
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {        return -1;
    }    strcpy(ifr.ifr_name, eth);
 ifr.ifr_hwaddr.sa_family = AF_LOCAL; 
 sscanf(mac,"%02x:%02x:%02x:%02x:%02x:%02x",
  MAC_ARRAY(mac_array)); memcpy(ifr.ifr_hwaddr.sa_data,mac_array,6);    if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0)
    {
     perror("SIOCSIFHWADDR:");
        close(fd);        return -1;
    }

    close(fd);    return 0;
}

注意:

  • 网卡地址的第一字节必须是偶数

  • sa_family 值必须为:AF_LOCAL

5. 获取网卡mtu

int getMtu(const char *eth, char *mtu) {    int fd;    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {        return -1;
    }    strcpy(ifr.ifr_name, eth);    if (ioctl(fd, SIOCGIFMTU, &ifr) < 0)
    {
        close(fd);        return -1;
    } 
    snprintf(mtu,64, "%d", (unsigned char) ifr.ifr_mtu);
    close(fd);    return 0;
}

6. 获取广播地址

int getBroadAddr(const char *eth, char *ip) {    int fd;    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {        return -1;
    }    strcpy(ifr.ifr_name, eth);    if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0)
    {
     perror("");
        close(fd);        return -1;
    }    memcpy(&sin, &ifr.ifr_broadaddr, sizeof(sin));    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(fd);    return 0;
}

7. 获取掩码

int getNetMask(const char *eth, char *mask) {    int fd;    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {        return -1;
    }    strcpy(ifr.ifr_name, eth);    if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0)
    {
     perror("");
        close(fd);        return -1;
    }    memcpy(&sin, &ifr.ifr_netmask, sizeof(sin));    snprintf(mask, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(fd);    return 0;
}

8. 获取网卡flag

int getFlags(const char *eth, char *fg) {    int fd;    struct sockaddr_in sin;
    struct ifreq ifr;
    bzero(&ifr, sizeof(ifr));    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {        return -1;
    }    strcpy(ifr.ifr_name, eth);    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
    {
     perror("");
        close(fd);        return -1;
    } snprintf(fg, IP_SIZE, "%x", ifr.ifr_flags);

    close(fd);    return 0;
}

三、测试

1. 测试程序

int main(int argc, char **argv){ int fg=0; char mac[32]={}; char ip[IP_SIZE]={0}; char buf[64];

 getBroadAddr(ethname,ip); printf("broad ip:t%sn",ip);

 getNetMask(ethname,ip); printf("mask:t%sn",ip);
 
 setIpAddrManual(ethname, "1.1.1.1");
 getLocalIp(ethname,ip); printf("ip:t%sn",ip);
 
 setLocalMac(ethname,"00:11:22:33:44:55");
 getLocalMac(ethname,mac); printf("mac:t%sn",mac);

 getMtu(ethname,buf); printf("mtu:t%sn",buf); 

 return 1;
}

2. 执行结果



执行后结果:

peng@ubuntu:~/work/test/ip$ ifconfig 
eth0      Link encap:Ethernet  HWaddr 00:11:22:33:44:55  
          inet addr:1.1.1.1  Bcast:1.255.255.255  Mask:255.0.0.0
          inet6 addr: fe80::d9d4:d42b:a04a:9d40/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:188577 errors:0 dropped:0 overruns:0 frame:0
          TX packets:208116 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:53762370 (53.7 MB)  TX bytes:172094089 (172.0 MB)


文章来源于:电子产品世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    GCC中的内嵌汇编语言;一.声明   虽然Linux的核心代码大部分是用C语言编写的,但是不可避免的其中还是有一部分是用汇编语言写成的。有些汇编语言代码是直接写在汇编源程序中的,特别是Linux的启动代码......
    在屏幕前显示冷冰冰一些字符。 而单片机则有趣的多,你只要会C语言入门语句,再加一点单片机寄存器配置就能点亮电路板上的一个灯。 这个时候你会更有成就感,感觉你学的东西可以很快看到成果,很快......
    干什么是由所使用的C语言编译器决定的。 一、问题提出 今天在单片机led模块定义函数中看到一个有趣的问题。提问者在进行基本的C51编程实验,编写了一个简单的C51程序如下: 程序执行完之后,可以......
    S3C2440中的GPIO(2024-07-17)
    令行,首先进入bin文件所在的目录,然后执行oflash led_on.bin,下载到开发板中即可执行。 5.C语言点亮GPF4 我们编写如下C语言代码控制LED, int main......
    较少情况可以一起处理 按键较多推荐分开处理,程序层次分明 二、完整的C语言代码 #define SYS_CLK 12000000L//设置定时器、串口频率参数 #define KEY_POWER 0x01......
    转到编辑 》 复制为 》 C以复制 C 语言格式的代码。   然后将此代码粘贴到 Arduino IDE 中。 代码说明 非接触式ESP32 音频播放器的完整代码在页面末尾给出。在这里,我们将解释代码......
    的变换;Park变换是两相静止坐标系α-β到两相旋转坐标系d、q之间的变换;Anti-Park变换是Park的逆变换。 本篇文章将讲述Clark变换,从公式推导到仿真实现,最后到C语言代码......
    如何得当使用C语言的特殊的用法;C语言有很多特殊的用法,如果这些特殊用法使用得当,会是你的代码变得更加有健壮,更加容易维护。 比如我们在使用STM32库的断言(assert),你会......
    分是指图形化配置工具软件STM32CubeMX,它可以让STM32开发者通过图形化界面进行有关管脚、时钟等基本配置并最终生成初始化C语言代码。整个操作非常简单,往往只需动动鼠标或个别数据填写即可完成。 另外一部分就是指基于STM32各系......
    我将GuiLite移植到了STM32F4开发板上;摘要:最近在做Github找到一个有趣的开源Gui框架:GuiLite,按照说明移植了GuiLite到STM32F4OLED屏幕上,分析......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>