1.根据man 7 packet 写出的抓包程序
有两种将网卡设置为promiscuous的方法,注释掉一种。
/* * Low level network programming in Linux using PF_PACKET* Need root privileges*/#include #include #include #include #include #include #include #include #include //#include //#include #include #define RED "\e[31m\e[1m"#define GREEN "\E[32m\E[1m"#define YELLOW "\E[33m\E[1m"#define BLUE "\E[34m\E[1m" #define NORMAL "\e[m"int get_nic_index(
int fd, const char* nic_name)
{ struct ifreq ifr;
if (
nic_name == NULL)
return -1;
memset(
&ifr, 0, sizeof(
ifr));
strncpy(
ifr.ifr_name, nic_name, IFNAMSIZ);
if (
ioctl(
fd, SIOCGIFINDEX, &ifr)
== -1)
{ perror(
GREEN"SIOCGIFINDEX ioctl error"NORMAL);
return -1;
} return ifr.ifr_ifindex;
}int set_Nic_promisc(
int fd, int dev_id)
{ struct packet_mreq mr;
memset(
&mr, 0, sizeof(
mr));
mr.mr_ifindex = dev_id;
mr.mr_type = PACKET_MR_PROMISC;
if (
setsockopt(
fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,&mr,sizeof(
mr))
==-1)
{ return -1;
} return 0;
}int set_nic_promisc(
int sockfd, const char *nic_name)
{ struct ifreq ethreq;
strncpy(
ethreq.ifr_name, nic_name, IFNAMSIZ);
ioctl(
sockfd, SIOCGIFFLAGS, ðreq);
ethreq.ifr_flags |= IFF_PROMISC;
ioctl(
sockfd, SIOCSIFFLAGS, ðreq);
return 0;
}int main(
int argc, char **argv)
{ if (
argc != 3)
{ printf(
"usage: ./a.out \n");
exit(
1);
} int pktfd;
int maxpak = 0, ipak = 0;
int fromlen;
char buffer[BUFSIZ]; struct iphdr *iph;
struct sockaddr_ll sll;
/* Low level socket */ pktfd = socket(
AF_PACKET, SOCK_RAW, htons(
ETH_P_ALL));
if (
pktfd == -1)
{ perror(
RED"Unable to create low level socket"NORMAL);
return -1;
} memset(
&sll, 0, sizeof(
sll));
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(
ETH_P_ALL);
sll.sll_ifindex = get_nic_index(
pktfd, argv[1]); if (
bind(
pktfd, (
struct sockaddr *)
&sll, sizeof(
sll))
!= 0)
{ perror(
YELLOW"bind error"NORMAL);
goto FAIL;
} set_nic_promisc(
pktfd, argv[1]); //if (set_Nic_promisc(pktfd, sll.sll_ifindex) == -1) { // fprintf(stderr, BLUE"set promisc failed! \n"NORMAL); // goto FAIL; //} maxpak = atoi(
argv[2]); while (
!maxpak ||
ipak < maxpak)
{ fromlen = recv(
pktfd, buffer, BUFSIZ, MSG_TRUNC);
printf(
"Buffer Length: %d bytes\n", fromlen);
struct ethhdr *ethdr = (
struct ethhdr *)
buffer;
if (
ethdr->h_proto == htons(
ETH_P_IP) )
{ iph = (
struct iphdr *) (
buffer + sizeof(
struct ethhdr));
printf(
"IP Packet from: %s\n", inet_ntoa(
*(
struct in_addr*)
&iph->saddr));
printf(
"IP Packet To: %s\n", inet_ntoa(
*(
struct in_addr*)
&iph->daddr));
printf(
"IP Protocol: %#x\n", iph->protocol);
printf(
"Buffer Content: %s\n\n", buffer);
ipak++;
} } return 0;
FAIL: close(
pktfd);
return -1;
}
测试中发现在家的pppoe拨号上网抓到的包格式解析错误,而放在虚拟机里面却正确。用wireshark听报文发现PPPoE的报文格式不同于普通报文。
pppoe拨号的报文在网络层的Type: PPPoE Session (0x8864),网络层到IP层之间还有2层:
PPP-over-Ethernet Session (6 bytes)
Point-to-Point Protocol (2 bytes) Protocol: IP (0x0021)
2.AF_PACKET 获得网卡信息- #include <stdio.h>
-
#include <string.h>
-
#include <sys/errno.h>
-
#include <stdlib.h>
-
#include <sys/socket.h>
-
#include <arpa/inet.h>
-
#include <sys/ioctl.h>
-
#include <linux/if_arp.h> //#include //#include
-
#include <linux/sockios.h>
-
#include <unistd.h>
-
-
int main(int argc, char **argv)
-
{
-
if (argc != 2) {
-
printf("usage: ./a.out nic_name");
-
exit(1);
-
}
-
-
int i, sockfd;
-
static struct ifreq ethreq;
-
struct sockaddr_ll inside_address;
-
-
/* Low level socket */
-
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-
if (sockfd == -1) {
-
perror("Unable to create low level socket");
-
return -1;
-
}
-
-
strncpy(ethreq.ifr_name, argv[1], IFNAMSIZ);
-
memset(&inside_address, 0, sizeof(inside_address));
-
inside_address.sll_family = AF_PACKET;
-
inside_address.sll_protocol = htons(ETH_P_ALL);
-
inside_address.sll_hatype = ARPOP_REQUEST;
-
inside_address.sll_pkttype = PACKET_BROADCAST;
-
inside_address.sll_halen = ETH_ALEN;
-
-
ioctl(sockfd, SIOCGIFINDEX, ðreq);
-
inside_address.sll_ifindex = ethreq.ifr_ifindex;
-
printf("%X, %X\n", inside_address.sll_ifindex, AF_INET);
-
ioctl(sockfd, SIOCGIFHWADDR, ðreq);
-
-
if (bind(sockfd, (struct sockaddr *) &inside_address,
-
sizeof(inside_address)) != 0) {
-
perror("bind error");
-
return -1;
-
}
-
-
for (i = 0; i < 6; i++)
-
inside_address.sll_addr[i] = (unsigned char) ethreq.ifr_hwaddr.sa_data[i];
-
-
for (i = 0; i < 5; i++)
-
printf("%02X:", inside_address.sll_addr[i]);
-
printf("%02X\n", inside_address.sll_addr[i]);
-
-
close(sockfd);
-
return 0;
-
}
阅读(1366) | 评论(0) | 转发(0) |