traceroute 구현하고 있습니다. recvfrom에서 BLOCK현상이 일어
글쓴이: nayana / 작성시간: 목, 2004/10/14 - 10:51오전
고수님들 답변 부탁드리겠습니다.
MainAssist.h
1 #ifndef __MAINASSIST_H__ 2 #define __MAINASSIST_H__ 3 4 #include "xSocket.h" 5 #include "xUtil.h" 6 7 #define BUFSIZE 1500 8 #define NI_MAXHOST 1025 9 10 struct rec 11 { 12 unsigned short rec_seq; 13 unsigned short rec_ttl; 14 struct timeval rec_tv; 15 }; 16 17 class MainAssist 18 { 19 friend char* IcmpCode( int code ); 20 friend int Recv( int seq, struct timeval *tv, int recvfd, char* recvbuf, unsigned short sport, unsigned short dport ); 21 22 public : 23 MainAssist(); 24 ~MainAssist(); 25 26 void InitInstance( int argc, char **argv ); 27 void TraceRoute( int argc, char **argv ); 28 void traceloop(); 29 char* sock_ntop_host( const struct sockaddr* sa, socklen_t salen ); 30 31 private : 32 int max_ttl, ttl; 33 int datalen; 34 unsigned int dport, sport; 35 char recvbuf[ BUFSIZE ]; 36 char sendbuf[ BUFSIZE ]; 37 int sendfd, recvfd; 38 int Probe, nProbes; 39 40 private : 41 xSocket Socket; 42 xUtil Util; 43 }; 44 45 #endif
MainAssist.cpp
1 #include <cstdlib> 2 #include <new> 3 #include <cstdio> 4 #include <cstring> 5 #include <unistd.h> 6 #include <errno.h> 7 #include <signal.h> 8 #include <sys/types.h> 9 #include <sys/time.h> 10 #include <netdb.h> 11 #include <sys/socket.h> 12 #include <arpa/inet.h> 13 #include <netinet/in.h> 14 #include <netinet/ip.h> 15 #include <netinet/udp.h> 16 #include <netinet/ip_icmp.h> 17 18 #include "MainAssist.h" 19 20 struct Ptroto 21 { 22 char *(*icmpcode) ( int ); 23 int (*recv) ( int, struct timeval*, int, char*, unsigned short, unsigned short ); 24 struct sockaddr *sasend; 25 struct sockaddr *sarecv; 26 struct sockaddr *salast; 27 struct sockaddr *sabind; 28 socklen_t salen; 29 int icmpPtroto; 30 int ttllevel; 31 int ttloptname; 32 33 } *Ptr; 34 35 //-------------------------------------------------------------------------------------------------- 36 struct Ptroto Ptroto = { IcmpCode, Recv, NULL, NULL, NULL, NULL, 0, IPPROTO_ICMP, IPPROTO_IP, IP_TTL }; 37 //-------------------------------------------------------------------------------------------------- 38 39 //---------------------------------------------------------------------------------------------- 40 MainAssist::MainAssist() 41 //---------------------------------------------------------------------------------------------- 42 { 43 max_ttl = 30; 44 datalen = sizeof( struct rec ); 45 dport = 32768 + 666; 46 recvfd = 0; 47 sendfd = 0; 48 ttl = 0; 49 Probe = 0; 50 nProbes = 3; 51 } 52 53 MainAssist::~MainAssist() 54 { 55 56 } 57 58 void MainAssist::InitInstance( int argc, char **argv ) 59 { 60 Util.GetOpt( argc, argv ); 61 TraceRoute( argc, argv ); 62 } 63 //---------------------------------------------------------------------------------------------- 64 void MainAssist::TraceRoute( int argc, char **argv ) 65 //---------------------------------------------------------------------------------------------- 66 { 67 char *Host; 68 struct addrinfo *ai; 69 70 if ( optind != argc - 1 ) perror( "main -g Hostname" ); 71 Host = argv[ optind ]; 72 73 Util.WakeSignal(); 74 ai = Socket.Host_serv( Host, NULL, 0, 0 ); 75 76 printf( "TRACEROUTE to %s ( %s ) : %d Hops Max, %d data bytes\n", ai->ai_canonname, 77 sock_ntop_host( ai->ai_addr, ai->ai_addrlen ), max_ttl, datalen ); 78 79 if ( ai->ai_family == AF_INET ) Ptr = &Ptroto; 80 else perror( "Can't Address" ); 81 82 Ptr->sasend = ai->ai_addr; 83 Ptr->sarecv = Util.Calloc( 1, ai->ai_addrlen ); 84 Ptr->salast = Util.Calloc( 1, ai->ai_addrlen ); 85 Ptr->sabind = Util.Calloc( 1, ai->ai_addrlen ); 86 Ptr->salen = ai->ai_addrlen; 87 88 traceloop(); 89 } 90 91 //----------------------------------------------------------------------------------------------------- 92 void MainAssist::traceloop() 93 //----------------------------------------------------------------------------------------------------- 94 { 95 int seq, code, done; 96 double rtt; 97 struct rec *rec; 98 struct timeval tvrecv; 99 100 recvfd = Socket.pSocket( Ptr->sasend->sa_family, SOCK_RAW, Ptr->icmpPtroto ); 101 setuid( getuid() ); 102 103 sendfd = Socket.pSocket( Ptr->sasend->sa_family, SOCK_DGRAM, 0 ); 104 105 Ptr->sabind->sa_family = Ptr->sasend->sa_family; 106 sport = (getpid() & 0xffff) | 0x8000; 107 108 Socket.sock_set_port( Ptr->sabind, Ptr->salen, htons( sport ) ); 109 110 Socket.Bind( sendfd, Ptr->sabind, Ptr->salen); 111 112 Util.sig_alrm( SIGALRM ); 113 114 seq = 0; 115 done = 0; 116 117 for ( ttl = 1; ttl <= max_ttl && done == 0; ttl++) 118 { 119 Socket.Setsockopt( sendfd, Ptr->ttllevel, Ptr->ttloptname, &ttl, sizeof( int ) ); 120 bzero( Ptr->salast, Ptr->salen ); 121 122 printf("%2d ", ttl ); 123 fflush( stdout ); 124 125 for ( Probe = 0; Probe < nProbes; Probe++ ) 126 { 127 rec = (struct rec *)sendbuf; 128 rec->rec_seq = ++seq; 129 rec->rec_ttl = ttl; 130 gettimeofday( &rec->rec_tv, NULL ); 131 132 Socket.sock_set_port( Ptr->sasend, Ptr->salen, htons( dport + seq ) ); 133 Socket.Sendto( sendfd, sendbuf, datalen, 0, Ptr->sasend, Ptr->salen ); 134 135 if ( ( code = (*Ptr->recv)( seq, &tvrecv, recvfd, recvbuf, sport, dport ) ) == -3 ) 136 printf(" *"); 137 else 138 { 139 char str[ NI_MAXHOST ]; 140 141 if ( Socket.sock_cmp_addr( Ptr->sarecv, Ptr->salast, Ptr->salen ) != 0 ) 142 { 143 if ( getnameinfo( Ptr->sarecv, Ptr->salen, str, sizeof(str), NULL, 0, 0 ) == 0 ) 144 { 145 146 printf(" %s (%s)", str, sock_ntop_host( Ptr->sarecv, Ptr->salen ) ); 147 } 148 else 149 printf(" %s", sock_ntop_host( Ptr->sarecv, Ptr->salen ) ); 150 151 memcpy( Ptr->salast, Ptr->sarecv, Ptr->salen ); 152 } 153 Util.SubTv( &tvrecv, &rec->rec_tv ); 154 155 rtt = tvrecv.tv_sec * 1000.0 + tvrecv.tv_usec / 1000.0; 156 printf(" %.3f ms", rtt ); 157 158 if ( code == -1 ) done++; 159 else if ( code >= 0 ) printf(" (ICMP %s)", ( *Ptr->icmpcode )( code ) ); 160 } 161 fflush( stdout ); 162 } 163 printf("\n"); 164 } 165 } 166 167 //---------------------------------------------------------------------------------------------- 168 char* MainAssist::sock_ntop_host( const struct sockaddr *sa, socklen_t salen ) 169 //---------------------------------------------------------------------------------------------- 170 { 171 static char str[ 128 ]; 172 if ( sa->sa_family == AF_INET ) 173 { 174 struct sockaddr_in *sin = ( struct sockaddr_in* )sa; 175 176 if ( inet_ntop( AF_INET, &sin->sin_addr, str, sizeof( str ) ) == NULL ) 177 return NULL; 178 } 179 180 return str; 181 } 182 183 //---------------------------------------------------------------------------------------------- 184 char* IcmpCode( int code ) 185 //---------------------------------------------------------------------------------------------- 186 { 187 switch ( code ) 188 { 189 case 0: return( "network unreachable" ); 190 case 1: return( "host unreachable" ); 191 case 2: return( "Ptrotocol unreachable" ); 192 case 3: return( "port unreachable" ); 193 case 4: return( "fragmentation required but DF bit set" ); 194 case 5: return( "source route failed" ); 195 case 6: return( "destination network unknown" ); 196 case 7: return( "destination host unknown" ); 197 case 8: return( "source host isolated (obsolete)" ); 198 case 9: return( "destination network administratively Ptrohibited" ); 199 case 10: return( "destination host administratively Ptrohibited" ); 200 case 11: return( "network unreachable for TOS" ); 201 case 12: return( "host unreachable for TOS" ); 202 case 13: return( "communication administratively Ptrohibited by filtering" ); 203 case 14: return( "host recedence violation" ); 204 case 15: return( "Ptrecedence cutoff in effect" ); 205 default: return( "[unknown code]" ); 206 } 207 } 208 209 //---------------------------------------------------------------------------------------------- 210 int Recv( int seq, struct timeval *tv, int recvfd, char* recvbuf, unsigned short sport, unsigned short dport ) 211 //---------------------------------------------------------------------------------------------- 212 { 213 int hlen1, hlen2, icmplen; 214 socklen_t len; 215 ssize_t n; 216 struct ip *ip, *hip; 217 struct icmp *icmp; 218 struct udphdr *udp; 219 220 alarm( 3 ); 221 222 while( 1 ) 223 { 224 len = Ptr->salen; 225 n = recvfrom( recvfd, recvbuf, BUFSIZE, 0, Ptr->sarecv, &len ); 226 if ( n < 0 ) 227 { 228 if ( errno == EINTR ) return -3; 229 else perror( "recvfrom error" ); 230 } 231 232 gettimeofday( tv, NULL ); 233 234 ip = (struct ip *) recvbuf; 235 hlen1 = ip->ip_hl << 2; 236 237 icmp = (struct icmp *) ( recvbuf + hlen1 ); 238 if ( ( icmplen = n - hlen1 ) < 8 ) perror( "icmplen 8 small" ); 239 240 if ( icmp->icmp_type == ICMP_TIMXCEED && icmp->icmp_code == ICMP_TIMXCEED_INTRANS ) 241 { 242 if ( icmplen < 8 + 20 + 8 ) perror( "icmplen ( 8 + 20 + 8 ) small" ); 243 244 hip = (struct ip *) ( recvbuf + hlen1 + 8 ); 245 hlen2 = hip->ip_hl << 2; 246 udp = (struct udphdr *) ( recvbuf + hlen1 + 8 + hlen2 ); 247 248 if ( hip->ip_p == IPPROTO_UDP && udp->source == htons( sport ) 249 && udp->dest == htons( dport + seq ) ) 250 { 251 return -2; 252 } 253 254 } 255 else if ( icmp->icmp_type == ICMP_UNREACH ) 256 { 257 if ( icmplen < 8 + 20 + 8 ) perror( "icmplen (8 + 20 + 8) small" ); 258 259 hip = (struct ip *) ( recvbuf + hlen1 + 8 ); 260 hlen2 = hip->ip_hl << 2; 261 udp = (struct udphdr *) ( recvbuf + hlen1 + 8 + hlen2 ); 262 263 if ( hip->ip_p == IPPROTO_UDP && udp->source == htons( sport ) 264 && udp->dest == htons( dport + seq ) ) 265 { 266 if ( icmp->icmp_code == ICMP_UNREACH_PORT ) return -1; 267 else return icmp->icmp_code; 268 } 269 } 270 } 271 }
xSocket.h
1 #ifndef __XSOCKET_H__ 2 #define __XSOCKET_H__ 3 4 #include <sys/socket.h> 5 6 class xSocket 7 { 8 public : 9 int pSocket( int family, int type, int protocol ); 10 void Bind( int fd, const struct sockaddr *sa, socklen_t salen ); 11 void sock_set_port( struct sockaddr *sa, socklen_t salen, int port ); 12 void Setsockopt( int fd, int level, int optname, const void *optval, socklen_t optlen ); 13 void Sendto( int fd, const void *ptr, size_t nbytes, int flags, const struct sockaddr *sa, socklen_t salen ); 14 int sock_cmp_addr( const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen ); 15 struct addrinfo* Host_serv( const char* host, const char* serv, int family, int socktype ); 16 }; 17 18 #endif
xSocket.cpp
1 #include <cstring> 2 #include <sys/types.h> 3 #include <sys/socket.h> 4 #include <unistd.h> 5 #include <netdb.h> 6 #include <cstdio> 7 #include <errno.h> 8 9 #include "xSocket.h" 10 11 //--------------------------------------------------------------------------------------------------------------- 12 int xSocket::pSocket( int family, int type, int protocol ) 13 //--------------------------------------------------------------------------------------------------------------- 14 { 15 int n; 16 17 if ( ( n = socket( family, type, protocol ) ) < 0 ) 18 perror( "socket error" ); 19 20 return n; 21 } 22 23 //--------------------------------------------------------------------------------------------------------------- 24 void xSocket::Bind( int fd, const struct sockaddr *sa, socklen_t salen ) 25 //--------------------------------------------------------------------------------------------------------------- 26 { 27 if ( bind( fd, sa, salen) < 0 ) 28 perror( "Bind Error" ); 29 } 30 31 //--------------------------------------------------------------------------------------------------------------- 32 void xSocket::sock_set_port( struct sockaddr *sa, socklen_t salen, int port ) 33 //--------------------------------------------------------------------------------------------------------------- 34 { 35 if ( sa->sa_family == AF_INET ) 36 { 37 struct sockaddr_in *sin = ( struct sockaddr_in * )sa; 38 sin->sin_port = port; 39 } 40 } 41 42 //--------------------------------------------------------------------------------------------------------------- 43 void xSocket::Setsockopt( int fd, int level, int optname, const void *optval, socklen_t optlen ) 44 //--------------------------------------------------------------------------------------------------------------- 45 { 46 if ( setsockopt(fd, level, optname, optval, optlen) < 0 ) 47 perror( "setsockopt error" ); 48 } 49 50 //--------------------------------------------------------------------------------------------------------------- 51 void xSocket::Sendto( int fd, const void *ptr, size_t nbytes, int flags, const struct sockaddr *sa, 52 socklen_t salen ) 53 //--------------------------------------------------------------------------------------------------------------- 54 { 55 unsigned int _nbytes; 56 _nbytes = sendto( fd, ptr, nbytes, flags, sa, salen ); 57 58 if ( _nbytes != nbytes ) perror( "sendto error" ); 59 } 60 61 //--------------------------------------------------------------------------------------------------------------- 62 int xSocket::sock_cmp_addr( const struct sockaddr *sa1, const struct sockaddr *sa2, socklen_t salen ) 63 //--------------------------------------------------------------------------------------------------------------- 64 { 65 if (sa1->sa_family != sa2->sa_family) 66 return -1; 67 68 if ( sa1->sa_family == AF_INET ) 69 { 70 71 return( memcmp( &( ( struct sockaddr_in *) sa1 )->sin_addr, &( ( struct sockaddr_in *) sa2)->sin_addr, 72 sizeof( struct in_addr ) ) ); 73 } 74 75 76 return -1; 77 } 78 79 //----------------------------------------------------------------------------------------------------- 80 struct addrinfo* xSocket::Host_serv( const char* host, const char* serv, int family, int socktype ) 81 //--------------------------------------------------------------------------------------------------------- 82 { 83 int n; 84 struct addrinfo hints, *res; 85 86 bzero( &hints, sizeof( struct addrinfo ) ); 87 hints.ai_flags = AI_CANONNAME; 88 hints.ai_family = family; 89 hints.ai_socktype = socktype; 90 91 if ( ( n = getaddrinfo( host, serv, &hints, &res ) ) != 0 ) 92 printf( "Host_serv Error for %s, %s : %s\n", ( host == NULL ) ? "( No HostName )" : host, 93 ( serv == NULL ) ? "( No Service Name )" : serv, gai_strerror( n ) ); 94 95 return ( res ); 96 }
xUtil.h
1 #ifndef __XUTIL_H__ 2 #define __XUTIL_H__ 3 4 class xUtil 5 { 6 friend void _signal_handle_Alarm( int WakeCode ); 7 8 public : 9 xUtil(); 10 ~xUtil(); 11 void GetOpt( int argc, char** argv ); 12 bool WakeSignal(); 13 void _signal_ALARM( int iEcode ); 14 void sig_alrm( int signo ); 15 void ErrQuit( char *msg ); 16 void SubTv( struct timeval* OutPtr, struct timeval* InPtr ); 17 18 struct sockaddr* Calloc( size_t Value, size_t Size ); 19 static xUtil* GetSignal(); 20 21 22 private : 23 static xUtil* _signal_Instance; 24 struct sockaddr* CallocPtr; 25 }; 26 27 #endif
xUtil.cpp
1 #include <cstdlib> 2 #include <cstdio> 3 #include <errno.h> 4 #include <signal.h> 5 #include <unistd.h> 6 7 #include "xUtil.h" 8 9 xUtil* xUtil::_signal_Instance; 10 11 //----------------------------------------------------------------------------------------------------------- 12 xUtil::xUtil() 13 //----------------------------------------------------------------------------------------------------------- 14 { 15 CallocPtr = 0; 16 } 17 18 //----------------------------------------------------------------------------------------------------------- 19 xUtil::~xUtil() 20 //----------------------------------------------------------------------------------------------------------- 21 { 22 if ( CallocPtr != 0 ) free( CallocPtr ); 23 CallocPtr = 0; 24 25 } 26 27 void xUtil::GetOpt( int argc, char** argv ) 28 { 29 int c; 30 while( ( c = getopt( argc, argv, "mv" ) ) != EOF ) 31 { 32 switch( c ) 33 { 34 case 'm': break; 35 case 'v': break; 36 } 37 } 38 } 39 40 //----------------------------------------------------------------------------------------------------------- 41 bool xUtil::WakeSignal() 42 //----------------------------------------------------------------------------------------------------------- 43 { 44 signal( SIGALRM, _signal_handle_Alarm ); 45 46 return true; 47 } 48 49 //----------------------------------------------------------------------------------------------------------- 50 void _signal_handle_Alarm( int WakeCode ) 51 //----------------------------------------------------------------------------------------------------------- 52 { 53 xUtil::GetSignal()->_signal_ALARM( WakeCode ); 54 } 55 56 //----------------------------------------------------------------------------------------------------------- 57 xUtil* xUtil::GetSignal() 58 //----------------------------------------------------------------------------------------------------------- 59 { 60 return _signal_Instance; 61 } 62 63 //----------------------------------------------------------------------------------------------------------- 64 void xUtil::_signal_ALARM( int iEcode ) 65 //----------------------------------------------------------------------------------------------------------- 66 { 67 sig_alrm( iEcode ); 68 } 69 70 //----------------------------------------------------------------------------------------------------------- 71 void xUtil::sig_alrm( int signo ) 72 //----------------------------------------------------------------------------------------------------------- 73 { 74 return; 75 } 76 77 //----------------------------------------------------------------------------------------------------------- 78 struct sockaddr* xUtil::Calloc( size_t Value, size_t Size ) 79 //----------------------------------------------------------------------------------------------------------- 80 { 81 if ( ( CallocPtr = ( struct sockaddr* )calloc( Value, Size ) ) == NULL ) 82 perror( "Calloc Error" ); 83 84 return CallocPtr; 85 } 86 87 //----------------------------------------------------------------------------------------------------------- 88 void xUtil::SubTv( struct timeval* OutPtr, struct timeval* InPtr ) 89 //----------------------------------------------------------------------------------------------------------- 90 { 91 if ( ( OutPtr->tv_usec -= InPtr->tv_usec ) < 0 ) 92 { 93 --OutPtr->tv_sec; 94 OutPtr->tv_usec += 1000000; 95 } 96 97 OutPtr->tv_sec -= InPtr->tv_sec; 98 }
main.cpp
1 #include "MainAssist.h" 2 3 int main( int argc, char **argv ) 4 { 5 MainAssist mainAssist; 6 7 mainAssist.InitInstance( argc, argv ); 8 9 return 0; 10 }
MainAssit.cpp 파일에서 recvfrom이 3번 받다들이고 나서는 더이상
받지 못하고 ...BLOCK 현상이 일어나 버립니다. 아무리 소스코드를 보아도
잘못된곳이 없는데....이러한 현상이 일어납니다. 왜 이렇게 되는지 이해가 안됩니다.
Forums:
댓글 달기