Raw 소켓을 사용한 ping 프로그램 오류가 나요 ㅜㅜ

happyu_u의 이미지

생 소켓을 사용해서 ICMP 기반의 Ping 프로그램을 작성하고 있는데요..

실행하게 되면
recvfrom() error
not ICMP packet.
이 두문장이 계속해서 무한루프 됩니다ㅜㅜ
문제가 뭘까요?
대체 뭐가 잘못된건지 헤매고 있습니다...도와주세요

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#define BUFSIZE 1500
char sendbuf[BUFSIZE], recvbuf[BUFSIZE];
int seqnum;
pid_t pid;
int sockfd;
int datalen = 56;
struct sockaddr_in dstaddr, srcaddr;
int send_ping();
int print_ping(char *ipdata, int readlen);
void sig_alrm(int);
void tv_sub(struct timeval *, struct timeval *);
uint16_t in_cksum(uint16_t *addr, int len);
void error_print(char *);
int main(int argc, char **argv){
  int readlen, addrlen;
  if(argc!=2){
    printf("Usage : %s ip_address \n", argv[0]);
    exit(1);
  }
  bzero(&srcaddr, sizeof(struct sockaddr));
  bzero(&dstaddr, sizeof(struct sockaddr));
  dstaddr.sin_family = AF_INET;
  dstaddr.sin_addr.s_addr = inet_addr(argv[1]);
  dstaddr.sin_port = htons(0);
  sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  if(sockfd < 0)
    error_print("raw socket creation fail.");
  if(connect(sockfd, (struct sockaddr *)&dstaddr,
    sizeof(struct sockaddr))!=0 )
    error_print("connect for raw socket fail.");
  pid = getpid() & 0xffff;
  signal(SIGALRM, sig_alrm);
  addrlen = sizeof(srcaddr);
  sig_alrm(SIGALRM);
  while(1){
    readlen = recvfrom(sockfd, recvbuf, sizeof(recvbuf),0,(struct sockaddr *)&srcaddr, &addrlen);
    if(readlen < 0)
      error_print("recvfrom() error");
    print_ping(recvbuf, readlen);
  }
  exit(0);
}
uint16_t in_cksum(uint16_t *addr, int len){
  int nleft = len;
  uint32_t sum = 0;
  uint16_t *w = addr;
  uint16_t answer = 0;
  while(nleft>1){
    sum += *w++;
    nleft -= 2;
  }
  if(nleft == 1){
    *(unsigned char *)(&answer) = *(unsigned char *)w;
    sum += answer;
  }
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);
  answer = ~sum;
  return(answer);
}
int send_ping(){
  int len;
  struct icmp *icmp;
  icmp = (struct icmp *) sendbuf;
  bzero((char *)icmp, sizeof(struct icmp));
  icmp->icmp_type = ICMP_ECHO;
  icmp->icmp_code = 0;
  icmp->icmp_id = pid;
  icmp->icmp_seq = seqnum++;
  memset(icmp->icmp_data, 0xa5, datalen);
  gettimeofday((struct timeval *)icmp->icmp_data,NULL); 
  len = 8 + datalen;
  icmp->icmp_cksum = 0;
  icmp->icmp_cksum = in_cksum((u_short *) icmp, len);
  sendto(sockfd, sendbuf, len, 0, (struct sockaddr *)&dstaddr, sizeof(dstaddr));
}
void sig_alrm(int signo){
  send_ping();
  alarm(2);
  return;
}
void tv_sub(struct timeval *out, struct timeval *in){
  if ((out->tv_usec -= in->tv_usec) < 0){
    --out->tv_sec;
    out->tv_sec += 1000000;
    }
    out->tv_sec -= in->tv_sec;
}
print_ping(char *ipdata, int recvsize){
  int ip_headlen, icmp_len;
  double rtt;
  struct icmp *icmp;
  struct iphdr *ip;
  struct timeval *tvsend, tvrecv;
  char buf[512];
  gettimeofday(&tvrecv, NULL);
  ip = (struct iphdr *) ipdata;
  ip_headlen = ip->ihl *4;
  if(ip->protocol != IPPROTO_ICMP){
    printf("not ICMP packet.\n");
    return;
  }
  icmp = (struct icmp *) (ipdata + ip_headlen);
  icmp_len = recvsize - ip_headlen;
  tvsend = (struct timeval *)icmp->icmp_data;
  tv_sub(&tvrecv, tvsend);
  rtt = tvrecv.tv_sec * 1000.0 + tvrecv.tv_usec / 1000.0;
  inet_ntop(AF_INET, (void *)&ip->saddr, buf, sizeof(buf));
  printf("%d bytes recv from %s: seq = %u, ttl = %d, rtt = %.3fms\n",
    icmp_len, buf, icmp->icmp_seq, ip->ttl, rtt);
}
void error_print(char *message){
  fputs(message, stderr);
  fputc('\n', stderr);
  exit;
}
ymir의 이미지

recvfrom 의 errno 를 한번 찍어보세요.
몇 가지 사소한 문법 에러가 있고, byte order 도 전혀 신경쓰지 않고 있기는 하지만..
정상적인 환경에서라면 그럭저럭 동작하는 코드입니다.

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

되면 한다! / feel no sorrow, feel no pain, feel no hurt, there's nothing gained.. only love will then remain.. 『 Mizz 』

acekila의 이미지

root 권한으로 실행하니 소스 수정 없이 잘 되네요~

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.