#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 設置爲 接口 的 名字 來 指定 將要 操做 的 設備. 結構的 其餘成員 能夠 分享 內存.socket
若是 某個 ioctl 標記爲 特權操做, 那麼 操做時 須要 有效uid 爲 0, 或者 擁有 CAP_NET_ADMIN 能力. 不然 將 返回 EPERM .tcp
設備標誌 | |
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 | 接口關閉時丟棄地址. |
設置 活動標誌字 是 特權操做, 可是 任何進程 均可以 讀取 標誌字.ui
struct ifmap
{
unsigned long mem_start;
unsigned long mem_end;
unsigned short base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
};
對 ifmap 結構 的 解釋 取決於 設備驅動程序 和 體系結構.spa
相關結構體:
/*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***********************************/ 指針