基于网卡序号双网卡数据共享(网卡转发)

这篇具有很好参考价值的文章主要介绍了基于网卡序号双网卡数据共享(网卡转发)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 基于网卡序号:ifr.ifr_ifindex;

实现网卡之间的数据转发文章来源地址https://www.toymoban.com/news/detail-690690.html

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
 
#define    RET_ERROR             -1 
#define    RET_FAIL              0 
#define    RET_SUCCESS              1 
 
#define       NIC1_NIC_IND          1 
#define       NIC2_NIC_IND          2 
 
int g_eth1_index = 0;
int g_eth2_index = 0;
 
const char  ETH_NIC_DEV1[16]        = "eth0";
const char  ETH_NIC_DEV2[16]        = "eth1";
 
/*
函数名称:inline int active_dev( const int sockFd, const char * dev)
功能说明:激活网口
输入参数:
    sockFd:套接字描述符
    dev:对应的网口
输出参数:无
返回值:
    int 成功返回1,失败返回0
关系函数:socket()
线程安全:否
*/
static int active_dev(const int sockFd, const char* dev)
{
    int     ret;
    struct  ifreq req;
 
    bzero(&req, sizeof(struct ifreq));
 
    strncpy(req.ifr_name, dev, sizeof(req.ifr_name));
 
    ret = ioctl(sockFd, SIOCGIFFLAGS, &req);
    if (ret == -1)
    {
        return(RET_FAIL);
    }
    req.ifr_flags |= IFF_UP;
 
    ret = ioctl(sockFd, SIOCSIFFLAGS, &req);
    if (ret == -1)
    {
        return(RET_FAIL);
    }
 
    return(RET_SUCCESS);
}
 
/*
    函数名称:inline int open_socket( int & sockFd)
    功能说明:新建套接字。
    输入参数:sockFd:套接字描述符
    输出参数:无
    返回值:
        int 成功返回新建的套接字描述符,失败返回0
    关系函数:无
    线程安全:否
*/
int open_socket(void)
{
    struct ifreq ifr;
    int s;
    int ret;
    int sockFd = 0;
 
    sockFd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sockFd < 0)
    {
        exit(0);
    }
 
    ret = active_dev(sockFd, ETH_NIC_DEV1);
    if (ret == RET_FAIL)
    {
        close(sockFd);
        exit(0);
    }
 
    strncpy(ifr.ifr_name, ETH_NIC_DEV1, sizeof(ifr.ifr_name));
    s = ioctl(sockFd, SIOCGIFFLAGS, &ifr);
    if (s < 0)
    {
        close(sockFd);
        exit(0);
    }
 
    ifr.ifr_flags |= IFF_PROMISC;
    ifr.ifr_flags |= IFF_UP;
 
    s = ioctl(sockFd, SIOCSIFFLAGS, &ifr);
    if (s < 0)
    {
    }
 
    ioctl(sockFd, SIOCGIFINDEX, &ifr);
    //sl.sll_ifindex = ifr.ifr_ifindex;
    g_eth1_index = ifr.ifr_ifindex;
 
    ret = active_dev(sockFd, ETH_NIC_DEV2);
    if (ret == RET_FAIL)
    {
        close(sockFd);
        exit(0);
    }
 
    strncpy(ifr.ifr_name, ETH_NIC_DEV2, sizeof(ifr.ifr_name));
    s = ioctl(sockFd, SIOCGIFFLAGS, &ifr);
    if (s < 0)
    {
        close(sockFd);
        exit(0);
    }
 
    ifr.ifr_flags |= IFF_PROMISC;
    ifr.ifr_flags |= IFF_UP;
 
    s = ioctl(sockFd, SIOCSIFFLAGS, &ifr);
    if (s < 0)
    {
    }
 
    ioctl(sockFd, SIOCGIFINDEX, &ifr);
    //sl.sll_ifindex = ifr.ifr_ifindex;
    g_eth2_index = ifr.ifr_ifindex;
    return(sockFd);
}
 
/*
    函数名称:inline int set_sockopt( const int sockFd)
    功能说明:对新建的套接字进行设置。
    输入参数:
        sockFd:套接字描述符
    输出参数:无
    返回值:
        int 成功返回0,失败返回0
    关系函数:无
    线程安全:否
*/
int set_sockopt(const int sockFd)
{
    int optval = 0;
    int optlen = 0;
    int ret;
 
    ret = getsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, &optval, (socklen_t*)&optlen);
    if (ret < 0)
    {
        return(RET_FAIL);
    }
 
    optval = 1024 * 128;// * 16;
    optlen = sizeof(optval);
    ret = setsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, &optval, (socklen_t)optlen);
    if (ret < 0)
    {
        return(RET_FAIL);
    }
    ret = getsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, &optval, (socklen_t*)&optlen);
    if (ret < 0)
    {
        return(RET_FAIL);
    }
    optval = 1024 * 512;// * 8;
    optlen = sizeof(optval);
    ret = setsockopt(sockFd, SOL_SOCKET, SO_SNDBUF, &optval, (socklen_t)optlen);
    if (ret < 0)
    {
        return(RET_FAIL);
    }
    ret = getsockopt(sockFd, SOL_SOCKET, SO_SNDBUF, &optval, (socklen_t*)&optlen);
    if (ret < 0)
    {
        return(RET_FAIL);
    }
    return(RET_SUCCESS);
}
 
/*
    函数名称:int recv_via_dev( const int sockFd, char & devInd,char * data, const
int len)
    功能说明:封装的接收函数
    输入参数:
        sockFd:套接字描述符
        devInd:网口标识
        data:接收的数据
        Len:接收数据的长度
    输出参数:无
    返回值:int 成功返回1,失败返回0
    关系函数:无
    线程安全:是
*/
int recv_via_dev(const int sockFd, int* devInd, char* data, int len)
{
    int ret = 0;
    struct sockaddr_ll sa;
    socklen_t sz = sizeof(sa);
 
    ret = recvfrom(sockFd, data, len, 0, (struct sockaddr*)&sa, &sz);   //function defined in system
    if (ret == -1)
    {
        return -1;
    }
 
    if (sa.sll_ifindex == g_eth1_index)
    {
        *devInd = NIC1_NIC_IND;
    }
    else if (sa.sll_ifindex == g_eth2_index)
    {
        *devInd = NIC2_NIC_IND;
    }
    else
    {
        return -1;
    }
 
    return(ret);
}
 
 
/*
    函数名称:int send_via_dev( const int sockFd, const char devInd, char * & data,
int & len, unsigned short vlanid=0)
    功能说明:封装的发送函数
    输入参数:
            sockFd:套接字描述符
            devInd:网口标识
            data:发送的数据
            Len:发送数据的长度
            vlanid:vlan标识
    输出参数:无
    返回值:int 成功返回1,失败返回0
    关系函数:无
    线程安全:是
*/
int send_via_dev(const int sockFd, int devInd, char* data, int len)
{
    int ret = 0;
    struct sockaddr_ll sa;
 
    sa.sll_family = AF_INET;
    memcpy(sa.sll_addr, data, 6);
    sa.sll_halen = 6;
    if (devInd == NIC1_NIC_IND)
    {
        sa.sll_ifindex = g_eth1_index;
    }
    else if (devInd == NIC2_NIC_IND)
    {
        sa.sll_ifindex = g_eth2_index;
    }
    else
    {
        return -1;
    }
 
    ret = sendto(sockFd, data, len, 0, (struct sockaddr*)&sa, sizeof(sa));
    if (ret < 0)
    {
    }
 
    return(ret);
}
 
int main(void)
{
    char data[1500] = {0};
    int sockFd = open_socket();
    int devInd = 0;
    int recvLen = 0;
    struct ethhdr *     eth;
 
    set_sockopt(sockFd);
    while(1)
    {
        recvLen = recv_via_dev(sockFd, &devInd, data, 1500);
        if (recvLen >= 0)
        {
            //eth = (struct ethhdr*)data;
            //printf("port eth%d recv proto %x\n", devInd, ntohs(eth->h_proto));
            if (NIC1_NIC_IND == devInd)
            {
                devInd = NIC2_NIC_IND;
            }
            else if (NIC2_NIC_IND == devInd)
            {
                devInd = NIC1_NIC_IND;
            }
            send_via_dev(sockFd, devInd, data, recvLen);
        }
        //fflush(stdout);
        //fflush(stderr);
    }
    return 0;
}

到了这里,关于基于网卡序号双网卡数据共享(网卡转发)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 双网卡同时上网 双网卡共享上网 网络带宽叠加实现方法[图文]

    双网卡同时上网;双网卡共享上网;网络带宽叠加。 前言: 越来越多的用户拥有双网卡,可是默认情况下只能使用一张网卡上internet网,我们应该如何设置才能把多网卡利用起来,达到尽其物用其材!以下方法适合2张及2张以上网卡。当然这里的双网卡可包含任意的两张及两

    2024年02月05日
    浏览(52)
  • iptables、共享上网SNAT、端口转发DNAT

    封端⼝,封ip 实现NAT功能 共享上⽹ 端⼝映射(端⼝转发),ip映射 硬件:整个企业入口 软件:开源软件 网站内部 封ip iptables 云防火墙 安全组 NAT网关 waf应用防火墙 容器、表、链、规则 1.防⽕墙是 层层过滤 的,实际是按照配置规则的 顺序从上到下 ,从前到后进⾏过滤的。 2.如

    2024年02月10日
    浏览(36)
  • 通过3G上网卡进行共享上网的方法介绍

    一、现在3G上网卡一般有两种: 1、插在USB接口的上网卡(包括内置在机器里面的),需要安装驱动及软件后连接3G网络上网; 2、类似3G网卡路由器,可供多个设备上网(一般控制在5个内); 由于第二种已经可以使多个设备同时连接上网,基本不涉及如何共享,下文只要描述

    2024年02月05日
    浏览(35)
  • VMware虚拟机配置网卡和共享磁盘步骤图解

    作为一名DBA新手,安装部署达梦数据库的共享存储集群时,遍寻网上茫茫技术博客,找不到比较正确且有效的配置网卡和共享磁盘的方法。因而在此,简单记录一下安装部署DMDSC的前期准备——配置网卡和配置共享磁盘的步骤。 1.VMware 编辑 虚拟网络编辑器 更改设置(管理员

    2024年02月06日
    浏览(50)
  • 006-基础入门-抓包技术&HTTPS协议&APP&小程序&PC应用&WEB&转发联动

    先找到目标目录下的相关文件:在此文件目录打开cmd 安装过java的直接输入 java -jar BurpSuiteLoader_v2022.jar 准备工作: 1、浏览器安装证书:解决本地抓HTTPS 2.模拟器安装证书:解决模拟器抓HTTPS 实现目的: 掌握几种抓包工具证书安装操作 掌握几种HTTP/S抓包工具的使用 学会Web,A

    2024年01月19日
    浏览(53)
  • linux c++ 多网卡情况下,如何判断原始套接字接收到的是哪个网卡的数据

    在Linux系统中,使用原始套接字(raw socket)接收网络数据时,可以通过解析IP头部来判断接收到的数据是哪块网卡接收的。这是因为在Linux系统中,每个网卡接收到数据包后,会将数据转发到与之对应的raw套接字。 要判断接收到的数据是哪块网卡接收的,你需要: 创建一个原

    2024年04月16日
    浏览(40)
  • 配置linux net.ipv4.ip_forward数据包转发

    出于系统安全考虑,在默认情况下,Linux系统是禁止数据包转发的。数据包转发指的是当主机拥有多个网卡时,通过一个网卡接收到的数据包,根据目的IP地址来转发数据包到其他网卡。这个功能通常用于路由器。 如果在Linux系统中需要开启路由转发功能,必须要配置一个内核

    2024年02月11日
    浏览(49)
  • Linux多进程数据交换--共享内存

    个人博客地址: https://cxx001.gitee.io 在linux系统开发当中,时常需要在多个进程之间交换数据,在多个进程之间交换数据,有很多方法,但最高效的方法莫过于共享内存。 linux共享内存是通过tmpfs这个文件系统来实现的,tmpfs文件系的目录为/dev/shm,/dev/shm是驻留在内存 RAM 当中的

    2024年02月12日
    浏览(43)
  • 更换Mysql数据库-----基于Abo.io 的书籍管理Web应用程序

    1. 其新的ABP框架可方便的开发微服务并使它们相互通信。亦可作为微服务单独部署,或者可以嵌入到单个应用程序中; 2. 模块化。最明显的就是更加模块化,使项目更加清晰明了,设计更合理; 3. 更多可扩展性。新的ABP框架为内置服务提供了更多的扩展点和覆盖的能力;

    2024年02月06日
    浏览(47)
  • Docker(镜像、容器、仓库)工具安装使用命令行选项及构建、共享和运行容器化应用程序

    👧个人主页:@小沈YO. 😚小编介绍:欢迎来到我的乱七八糟小星球🌝 🔑本章内容:Docker工具安装使用、命令行选项及构建、共享和运行容器化应用程序时的主要步骤 记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~ 提示:以下是本篇文章正文内容,下面案例可供参考 以下是在常

    2024年02月05日
    浏览(67)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包