#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/in.h>
#include <features.h> /* for the glibc version number */
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
int set_promisc_dev(int sSocket, char *dev, int flag)
{
int res;
struct ifreq ifr;
strncpy(ifr.ifr_name, dev, 16);
if(ioctl(sSocket, SIOCGIFFLAGS, &ifr) < 0) return -2;
if(!flag)
ifr.ifr_flags |= IFF_PROMISC;
else
ifr.ifr_flags &= ~IFF_PROMISC;
res = ioctl(sSocket, SIOCSIFFLAGS, &ifr);
return (res < 0)? -2 : 1;
}
#define MaxSizeOfPktSize 65535
void conv_macaddr(char *addr, char *result)
{
unsigned int i;
u_int8_t *ptmp = (unsigned char *)addr;
char hexbyte[16];
strcpy(result, "");
for (i = 0; i <= 5; i++) {
sprintf(hexbyte, "%02X", *ptmp);
strcat(result, hexbyte);
ptmp++;
}
}
void conv_pkt_ipaddr(unsigned char *data, char *result)
{
int i;
char temp[16];
strcpy(result, "");
for(i=0;i<4;i++)
{
if(i==3)
{
snprintf(temp, sizeof(temp), "%d", data[i]);
strcat(result, temp);
}
else
{
snprintf(temp, sizeof(temp), "%d.", data[i]);
strcat(result, temp);
}
}
}
int main(void)
{
int i = 0;
fd_set fd_r;
int fRet = 0;
int nRead = 0;
int sSocket = -1;
char *pszRcvBuffer = NULL;
socklen_t addrLen = 0;
struct sockaddr_ll socketLink; // link layer structure
sSocket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // creating a raw socket
if(sSocket < 0) {
fprintf(stderr, "socket : %s \n", strerror(errno));
exit(1);
}
fRet = set_promisc_dev(sSocket, "eth0", 0); // set a promiscuous mode to a specific NIC
// for capturing all packets from everywhere
if(fRet < 0) {
fprintf(stderr, "set_promisc_dev : %s\n", strerror(errno));
exit(1);
}
pszRcvBuffer = (char *)malloc(MaxSizeOfPktSize); // allocating memory cell to store captured packet
memset(pszRcvBuffer, 0, sizeof(MaxSizeOfPktSize));
while(1) {
int chCount = 0;
struct ether_header *ep;
char pkt_from[20], pkt_to[20];
FD_ZERO(&fd_r);
FD_SET(sSocket, &fd_r);
if(select(sSocket + 1, &fd_r, NULL, NULL, NULL) < 0) {
fprintf(stderr, "select = %s\n", strerror(errno));
exit(1);
}
if(!FD_ISSET(sSocket, &fd_r)) continue;
nRead = recvfrom(sSocket, pszRcvBuffer, MaxSizeOfPktSize, 0, (struct sockaddr *)&socketLink, &addrLen);
if(nRead < 0) {
fprintf(stderr, "recvfrom = %s\n", strerror(errno));
exit(1);
}
/*
taken from /usr/include/linux/if_packet.h
struct sockaddr_ll
{
unsigned short sll_family;
unsigned short sll_protocol;
int sll_ifindex;
unsigned short sll_hatype;
unsigned char sll_pkttype;
unsigned char sll_halen;
unsigned char sll_addr[8];
};
*/
fprintf(stderr, "This packet is captured from NIC(%d) \n", socketLink.sll_ifindex);
fprintf(stderr, "sll_family = %d, sll_protocol = %d, sll_hatype = %d, sll_pkttype = %d\n",
socketLink.sll_family, socketLink.sll_protocol, socketLink.sll_hatype, socketLink.sll_pkttype);
// sll_family = address family = declared in /usr/include/sys/socket.h
// sll_protocol = type of protocol = declared in /usr/include/netinet/in.h
/*
taken from /usr/include/net/ethernet.h
struct ether_header
{
u_int8_t ether_dhost[ETH_ALEN]; / destination eth addr /
u_int8_t ether_shost[ETH_ALEN]; / source ether addr /
u_int16_t ether_type; / packet type ID field /
} __attribute__ ((__packed__));
*/
ep = (struct ether_header *)pszRcvBuffer;
conv_macaddr((char *)ep->ether_shost, pkt_from);
conv_macaddr((char *)ep->ether_dhost, pkt_to);
fprintf(stderr, "Packet Type = %d\n", ntohs(ep->ether_type));
fprintf(stderr, "FROM: %s ====> TO: %s\n", pkt_from, pkt_to);
while(nRead--) {
fprintf(stdout, "%02X ", *pszRcvBuffer++);
if((++chCount % 8) == 0) fprintf(stdout, "\n");
}
memset(pszRcvBuffer, 0, sizeof(MaxSizeOfPktSize));
}
free(pszRcvBuffer);
close(sSocket);
return 0;
}