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 #endifMainAssist.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 #endifxSocket.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 #endifxUtil.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:


댓글 달기