I wrote a simple packet receiver using raw sockets and I get strange outputs, f.e.:
Received packet: size: 124, type: PACKET_HOST (0)
Sender info: Name: n003-000-000-000.static.ge.com, IP: 3.0.0.0
Data:
74 2f 68 3c d1 9f 00 37 b7 d1 5a a7 08 00 45 00 00 6e 00 00 40
00 40 11 b6 e9 c0 a8 01 01 c0 a8 01 44 00 35 94 08 00 5a 3b aa
e1 78 81 80 00 01 00 01 00 00 00 00 01 30 01 30 01 30 01 33 07
69 6e 2d 61 64 64 72 04 61 72 70 61 00 00 0c 00 01 c0 0c 00 0c
00 01 00 00 65 95 00 20 10 6e 30 30 33 2d 30 30 30 2d 30 30 30
2d 30 30 30 06 73 74 61 74 69 63 02 67 65 03 63 6f 6d 00
When I'm browsing the internet, the packets are bigger, but the host name and address stays the same or almost the same.
Could someone help me identify the problem?
Here's the code:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/if_ether.h>
#include <netdb.h>
#include <linux/if_packet.h>
#include <netinet/ether.h>
#define PACKET_SIZE 1 << 16
void usage();
void packetTypeToStr(int type, char *str);
int main(int argc, char **argv) {
const char *iface_name;
if (argc == 2) {
iface_name = argv[1];
} else if (argc > 2) {
usage();
return 1;
} else {
iface_name = "wlan0";
}
// Opening socket in raw mode
int socketFileDesc = 0;
if ((socketFileDesc = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
perror("socket");
return errno;
}
printf("Opened raw socket\n");
// Acquiring the index of the interface
struct ifreq iface;
memset(&iface, 0, sizeof(struct ifreq));
strncpy(iface.ifr_name, iface_name, strlen(iface_name) + 1);
if (ioctl(socketFileDesc, SIOCGIFINDEX, &iface) < 0) {
perror("SIOCGIFINDEX");
usage();
close(socketFileDesc);
return errno;
}
int index = iface.ifr_ifindex;
printf("Index of the interface %s: %d\n", iface_name, index);
// Acquiring the mac address of the interface
struct ifreq iface_mac;
memset(&iface_mac, 0, sizeof(struct ifreq));
strncpy(iface_mac.ifr_name, iface_name, strlen(iface_name) + 1);
if (ioctl(socketFileDesc, SIOCGIFHWADDR, &iface_mac) < 0) {
perror("SIOCGIFHWADDR");
usage();
close(socketFileDesc);
return errno;
}
printf("MAC address of the interface %s: %s\n", iface_name, ether_ntoa((struct ether_addr*)iface_mac.ifr_hwaddr.sa_data));
// Setting interface in promiscuous mode
struct ifreq iface_options;
memset(&iface_options, 0, sizeof(struct ifreq));
strncpy(iface_options.ifr_name, iface_name, strlen(iface_name) + 1);
if (ioctl(socketFileDesc, SIOCGIFFLAGS, &iface_options) < 0) {
perror("SIOCGIFFLAGS");
close(socketFileDesc);
return errno;
}
iface_options.ifr_flags |= IFF_PROMISC;
if (ioctl(socketFileDesc, SIOCSIFFLAGS, &iface_options) < 0) {
perror("SIOCGIFFLAGS");
close(socketFileDesc);
return errno;
}
printf("Interface %s set in promiscuous mode\n", iface_name);
// Binding socket to the interface
struct sockaddr_ll socketAddress;
memset(&socketAddress, 0, sizeof(socketAddress));
socketAddress.sll_family = AF_PACKET;
socketAddress.sll_protocol = htons(ETH_P_ALL);
socketAddress.sll_ifindex = index;
if (bind(socketFileDesc, (struct sockaddr *) &socketAddress, sizeof(socketAddress)) < 0) {
perror("bind");
close(socketFileDesc);
return errno;
}
printf("Socket bound to the interface: %s\nWaiting for packets...\n", iface_name);
// Receiving packets in a loop
while (1) {
ssize_t n = 0;
uint8_t packet[PACKET_SIZE];
bzero(packet, sizeof(packet));
struct sockaddr_in address;
socklen_t length = sizeof(address);
if ((n = recvfrom(socketFileDesc, packet, sizeof(packet), 0, (struct sockaddr *) &address, &length)) < 0) {
perror("recvfrom");
close(socketFileDesc);
return errno;
}
// Null-terminated data
if (n > 0)
packet[n - 1] = '\0';
else
continue;
// IP address
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(address.sin_addr), ip, length);
// Host name
struct hostent *host = gethostbyaddr(&(address.sin_addr), length, AF_INET);
if (host == NULL) {
herror("gethostbyaddr");
return h_errno;
}
const char *hostName = host->h_name;
// Packet type
char packetType[BUFSIZ];
int type = ((struct sockaddr_ll *) &address)->sll_pkttype;
packetTypeToStr(type, packetType);
// Printing info and data
printf("\n\nReceived packet: size: %li, type: %s\n"
"Sender info: Name: %s, IP: %s\n",
n, packetType, hostName, ip);
printf("Data:\n");
int i = 0;
for (; i < n; ++i)
printf("%02x ", packet[i]);
}
return 0;
}
Since you are receiving raw packet recvfrom()
can not return IP address because data in general may not be an internet packet. For example it may be simply an arbitrary Ethernet packet, that was sent from some device that has no TCP/IP stack at all. Probably recvfrom()
treats passed sockaddr pointer as struct sockaddr_ll *
and returns physical layer address.
You can try to obtain correct IP address via parsing of received packet. If it is really IP packet - it will contain all headers, with source and destination addresses.