随笔 - 23  文章 - 0 评论 - 68 
<2007年10月>
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

广告中国绩效网,注册立刻送10元 广告中国绩效网,注册立刻送10元

常用链接

留言簿(7)

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜


#define INTERFACE "eth0"
#define MAX_SIZE 65535

int init_raw_socket();
int open_promisc(char *interface, int sockfd);

int main()
{
    int sockfd;
    int bytes_recv;
    int addr_len;

    char recv_buff[MAX_SIZE];
    struct sockaddr_in from_addr;
    struct ip *ip;
    struct tcp *tcp;

    sockfd = init_raw_socket();
    open_promisc(INTERFACE, sockfd);

    addr_len = sizeof(from_addr);

    while (1)
    {
        bytes_recv = recvfrom(sockfd, recv_buff, MAX_SIZE - 1, 0,
            (struct sockaddr_in*)&from_addr, &addr_len));
        if (bytes_recv < 0)
        {
            perror("recvfrom error");
            exit(EXIT_FAILURE);
        }

        printf("receive %d bytes from %s\n", bytes_recv,
            inet_ntoa(from_addr.sin_addr));

        ip = (struct ip*)recv_buff;
        if (ip->ip_protocol == 6)
        {
            printf("IP header length ::: %d\n",ip->ip_length);  
            printf("Protocol ::: %d\n",ip->ip_protocol);  
            tcp = (struct tcp *)(buffer + (4*ip->ip_length));  
            printf("Source port ::: %d\n",ntohs(tcp->tcp_source_port));  
            printf("Dest port ::: %d\n",ntohs(tcp->tcp_dest_port));  
        }
    }
    return 0;
}

int init_raw_socket()
{
    int sockfd;
    sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
    if (sockfd < 0)
    {
        perror("create socker error");
        exit(EXIT_FAILURE);
    }
    
    return sockfd;
}

int open_promisc(char *interface, int sockfd)
{
    struct ifreq ifr;
    strncpy(ifr.ifr_name, interface, strlen(interface) + 1);
    if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1)
    {
        perror("couldn't rettrive flags for the interface");
        exit(EXIT_FAILURE);
    }

    ifr.ifr_flags |= IFF_PROMISC;
    if (ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1)
    {
        perror("couldn't set the promisc flags");
        exit(EXIT_FAILURE);
    }

    printf("set interface: %s to promisc\n", interface);
    return 0;
}


关于open_promisc打开网口混合模式
#include <sys/ioctl.h>
#include <net/if.h>

Linux 支持 一些 配置 网络设备 的 标准 ioctl. 他们 用于 任意的 套接字 描述符, 而 无须 了解 其 类型 或 系列. 他们 传递 一个 ifreq 结构:

struct ifreq
{
char ifr_name[IFNAMSIZ]; /* Interface name */
union {
struct sockaddr ifr_addr;
struct sockaddr ifr_dstaddr;
struct sockaddr ifr_broadaddr;
struct sockaddr ifr_netmask;
struct sockaddr ifr_hwaddr;
short ifr_flags;
int ifr_ifindex;
int ifr_metric;
int ifr_mtu;
struct ifmap ifr_map;
char ifr_slave[IFNAMSIZ];
char ifr_newname[IFNAMSIZ];
char * ifr_data;
};
}

struct ifconf
{
int ifc_len; /* size of buffer */
union {
char * ifc_buf; /* buffer address */
struct ifreq *ifc_req; /* array of structures */
};
};

一般说来, ioctl 通过 把 ifr_name 设置为 接口 的 名字 来 指定 将要 操作 的 设备. 结构的 其他成员 可以 分享 内存.

如果 某个 ioctl 标记为 特权操作, 那么 操作时 需要 有效uid 为 0, 或者 拥有 CAP_NET_ADMIN 能力. 否则 将 返回 EPERM .

SIOCGIFNAME
给定 ifr_ifindex, 返回 ifr_name 中 的 接口名字. 这是 唯一 返回 ifr_name 内容 的 ioctl.
SIOCGIFINDEX
把 接口 的 索引 存入 ifr_ifindex.
SIOCGIFFLAGS, SIOCSIFFLAGS
读取 或 设置 设备的 活动标志字. ifr_flags 包含 下列值 的 屏蔽位:

设备标志
IFF_UP 接口正在运行.
IFF_BROADCAST 有效的广播地址集.
IFF_DEBUG 内部调试标志.
IFF_LOOPBACK 这是自环接口.
IFF_POINTOPOINT 这是点到点的链路接口.
IFF_RUNNING 资源已分配.
IFF_NOARP 无arp协议, 没有设置第二层目的地址.
IFF_PROMISC 接口为杂凑(promiscuous)模式.
IFF_NOTRAILERS 避免使用trailer .
IFF_ALLMULTI 接收所有组播(multicast)报文.
IFF_MASTER 主负载平衡群(bundle).
IFF_SLAVE 从负载平衡群(bundle).
IFF_MULTICAST 支持组播(multicast).
IFF_PORTSEL 可以通过ifmap选择介质(media)类型.
IFF_AUTOMEDIA 自动选择介质.
IFF_DYNAMIC 接口关闭时丢弃地址.

设置 活动标志字 是 特权操作, 但是 任何进程 都可以 读取 标志字.

SIOCGIFMETRIC, SIOCSIFMETRIC
使用 ifr_metric 读取 或 设置 设备的 metric 值. 该功能 目前 还没有 实现. 读取操作 使 ifr_metric 置 0, 而 设置操作 则 返回 EOPNOTSUPP.
SIOCGIFMTU, SIOCSIFMTU
使用 ifr_mtu 读取 或 设置 设备的 MTU(最大传输单元). 设置 MTU 是 特权操作. 过小的 MTU 可能 导致 内核 崩溃.
SIOCGIFHWADDR, SIOCSIFHWADDR
使用 ifr_hwaddr 读取 或 设置 设备的 硬件地址. 设置 硬件地址 是 特权操作.
SIOCSIFHWBROADCAST
使用 ifr_hwaddr 读取 或 设置 设备的 硬件广播地址. 这是个 特权操作.
SIOCGIFMAP, SIOCSIFMAP
使用 ifr_map 读取 或 设置 接口的 硬件参数. 设置 这个参数 是 特权操作.
struct ifmap 
{
unsigned long mem_start;
unsigned long mem_end;
unsigned short base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
};

对 ifmap 结构 的 解释 取决于 设备驱动程序 和 体系结构.

SIOCADDMULTI, SIOCDELMULTI
使用 ifr_hwaddr 在 设备的 链路层 组播过滤器 (multicase filter) 中 添加 或 删除 地址. 这些是 特权操作. 
SIOCGIFTXQLEN, SIOCSIFTXQLEN
使用 ifr_qlen 读取 或 设置 设备的 传输队列长度. 设置 传输队列长度 是 特权操作.
SIOCSIFNAME
ifr_ifindex 中 指定的 接口名字 改成 ifr_newname. 这是个 特权操作.
SIOCGIFCONF
返回 接口地址(传输层) 列表. 出于 兼容性, 目前 只代表 AF_INET 地址. 用户 传送 一个 ifconf 结构 作为 ioctl 的 参数. 其中 ifc_req 包含 一个 指针 指向 ifreq 结构数组, 他的 长度 以字节 为单位 存放在 ifc_len 中. 内核 用 所有 当前的 L3(第三层?) 接口地址 填充 ifreqs, 这些 接口 正在 运行: ifr_name 存放 接口名字 (eth0:1等), ifr_addr 存放 地址. 内核 在 ifc_len 中 返回 实际长度; 如果 他 等于 初始长度, 表示 溢出了, 用户 应该 换一个 大些的 缓冲区 重试 一下. 没有 发生 错误时 ioctl 返回 0, 否则 返回 -1, 溢出 不算 错误.

相关结构体:
/*structure of an ip header*/   
struct ip {     
unsigned int ip_length:4; /*little-endian*/   
unsigned int ip_version:4;  
unsigned char ip_tos;   
unsigned short ip_total_length;    
unsigned short ip_id;    
unsigned short ip_flags;  
unsigned char ip_ttl;  
unsigned char ip_protocol;  
unsigned short ip_cksum;  
unsigned int ip_source; unsigned int ip_dest;    
};  
    
/* Structure of a TCP header */  
struct tcp {  
unsigned short tcp_source_port;  
unsigned short tcp_dest_port;  
unsigned int tcp_seqno;    
unsigned int tcp_ackno;  
unsigned int tcp_res1:4, /*little-endian*/  
tcp_hlen:4,  
tcp_fin:1,  
tcp_syn:1,  
tcp_rst:1,  
tcp_psh:1,  
tcp_ack:1,  
tcp_urg:1,  
tcp_res2:2;  
unsigned short tcp_winsize;  
unsigned short tcp_cksum;  
unsigned short tcp_urgent;  
};  
/*********************EOF***********************************/  

posted on 2007-10-15 22:58 吴剑 阅读(638) 评论(0)  编辑 收藏 引用 所属分类: 代码摘抄
只有注册用户登录后才能发表评论。