컴퓨터공부

raw socket 사용법

achivenKakao 2006. 9. 4. 18:20

#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;
}