Mercurial > hg > quicktun
comparison src/common.c @ 15:1fa5b5fa49e1 V2.1.5
Fixed a race condition caused by reception of ICMP errors
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Sun, 13 Feb 2011 23:56:54 +0100 |
parents | f7e0145d8e2a |
children | 38d495566d1c |
comparison
equal
deleted
inserted
replaced
14:d9dfeeaff7e8 | 15:1fa5b5fa49e1 |
---|---|
142 | 142 |
143 int init_tuntap() { | 143 int init_tuntap() { |
144 char* envval; | 144 char* envval; |
145 fprintf(stderr, "Initializing tun/tap device...\n"); | 145 fprintf(stderr, "Initializing tun/tap device...\n"); |
146 int ttfd; //Tap device file descriptor | 146 int ttfd; //Tap device file descriptor |
147 #ifdef linux | |
148 struct ifreq ifr; //required for tun/tap setup | |
149 memset(&ifr, 0, sizeof(ifr)); | |
150 if ((ttfd = open("/dev/net/tun", O_RDWR)) < 0) return errorexitp("Could not open tun/tap device file"); | |
151 if (envval = getconf("INTERFACE")) strcpy(ifr.ifr_name, envval); | |
152 ifr.ifr_flags = getconf("TUN_MODE") ? IFF_TUN : IFF_TAP; | |
153 ifr.ifr_flags |= getconf("USE_PI") ? 0 : IFF_NO_PI; | |
154 if (ioctl(ttfd, TUNSETIFF, (void *)&ifr) < 0) return errorexitp("TUNSETIFF ioctl failed"); | |
155 #else | |
147 #ifdef SOLARIS | 156 #ifdef SOLARIS |
148 int ip_fd = -1, if_fd = -1, ppa = 0; | 157 int ip_fd = -1, if_fd = -1, ppa = 0; |
149 #endif | 158 if ((ttfd = open("/dev/tun", O_RDWR)) < 0) return errorexitp("Could not open tun device file"); |
150 #ifdef linux | 159 if ((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) return errorexitp("Could not open /dev/ip"); |
151 struct ifreq ifr; //required for tun/tap setup | 160 if ((envval = getconf("INTERFACE"))) { |
152 memset(&ifr, 0, sizeof(ifr)); | 161 while (*envval && !isdigit((int)*envval)) envval++; |
153 if ((ttfd = open("/dev/net/tun", O_RDWR)) < 0) return errorexitp("Could not open tun/tap device file"); | 162 ppa = atoi(envval); |
154 if (envval = getconf("INTERFACE")) strcpy(ifr.ifr_name, envval); | 163 } |
155 ifr.ifr_flags = getconf("TUN_MODE") ? IFF_TUN : IFF_TAP; | 164 if ((ppa = ioctl(ttfd, TUNNEWPPA, ppa)) < 0) return errorexitp("Could not assign new PPA"); |
156 ifr.ifr_flags |= getconf("USE_PI") ? 0 : IFF_NO_PI; | 165 if ((if_fd = open("/dev/tun", O_RDWR, 0)) < 0) return errorexitp("Could not open tun device file again"); |
157 if (ioctl(ttfd, TUNSETIFF, (void *)&ifr) < 0) return errorexitp("TUNSETIFF ioctl failed"); | 166 if (ioctl(if_fd, I_PUSH, "ip") < 0) return errorexitp("Could not push IP module"); |
158 #else | 167 if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) return errorexitp("Could not set PPA"); |
159 #ifdef SOLARIS | 168 if (ioctl(ip_fd, I_LINK, if_fd) < 0) return errorexitp("Could not link TUN device to IP"); |
160 if ((ttfd = open("/dev/tun", O_RDWR)) < 0) | 169 #else |
161 return errorexitp("Could not open tun device file"); | 170 if (!(envval = getconf("INTERFACE"))) envval = "/dev/tun0"; |
162 | 171 if ((ttfd = open(envval, O_RDWR)) < 0) return errorexitp("Could not open tun device file"); |
163 if ((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) | 172 #endif |
164 return errorexitp("Could not open /dev/ip"); | |
165 | |
166 if ((envval = getconf("INTERFACE"))) { | |
167 while (*envval && !isdigit((int)*envval)) | |
168 envval++; | |
169 ppa = atoi(envval); | |
170 } | |
171 | |
172 if ((ppa = ioctl(ttfd, TUNNEWPPA, ppa)) < 0) | |
173 return errorexitp("Could not assign new PPA"); | |
174 | |
175 if ((if_fd = open("/dev/tun", O_RDWR, 0)) < 0) | |
176 return errorexitp("Could not open tun device file again"); | |
177 | |
178 if (ioctl(if_fd, I_PUSH, "ip") < 0) | |
179 return errorexitp("Could not push IP module"); | |
180 | |
181 if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) | |
182 return errorexitp("Could not set PPA"); | |
183 | |
184 if (ioctl(ip_fd, I_LINK, if_fd) < 0) | |
185 return errorexitp("Could not link TUN device to IP"); | |
186 #else | |
187 if (!(envval = getconf("INTERFACE"))) envval = "/dev/tun0"; | |
188 if ((ttfd = open(envval, O_RDWR)) < 0) return errorexitp("Could not open tun device file"); | |
189 #endif | |
190 #endif | 173 #endif |
191 return ttfd; | 174 return ttfd; |
192 } | 175 } |
193 | 176 |
194 void hex2bin(unsigned char* dest, unsigned char* src, int count) { | 177 void hex2bin(unsigned char* dest, unsigned char* src, int count) { |
246 len = read(ttfd, buffer_raw + p->offset_raw, p->buffersize_raw); | 229 len = read(ttfd, buffer_raw + p->offset_raw, p->buffersize_raw); |
247 if (session.remote_float == 0 || session.remote_float == 2) { | 230 if (session.remote_float == 0 || session.remote_float == 2) { |
248 len = p->encode(&session, buffer_raw, buffer_enc, len); | 231 len = p->encode(&session, buffer_raw, buffer_enc, len); |
249 if (len < 0) return len; | 232 if (len < 0) return len; |
250 if (session.remote_float == 0) { | 233 if (session.remote_float == 0) { |
251 write(sfd, buffer_enc + p->offset_enc, len); | 234 len = write(sfd, buffer_enc + p->offset_enc, len); |
252 } else { | 235 } else { |
253 sendto(sfd, buffer_enc + p->offset_enc, len, 0, (struct sockaddr*)&session.remote_addr, sizeof(session.remote_addr)); | 236 len = sendto(sfd, buffer_enc + p->offset_enc, len, 0, (struct sockaddr*)&session.remote_addr, sizeof(session.remote_addr)); |
254 } | 237 } |
255 } | 238 } |
239 } | |
240 if (fds[1].revents & POLLERR) { | |
241 int out; | |
242 len = sizeof(out); | |
243 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); | |
244 fprintf(stderr, "Received error %d on udp socket\n", out); | |
256 } | 245 } |
257 if (fds[1].revents & POLLIN) { | 246 if (fds[1].revents & POLLIN) { |
258 socklen_t recvaddr_len = sizeof(recvaddr); | 247 socklen_t recvaddr_len = sizeof(recvaddr); |
259 if (session.remote_float == 0) { | 248 if (session.remote_float == 0) { |
260 len = read(sfd, buffer_enc + p->offset_enc, p->buffersize_enc); | 249 len = read(sfd, buffer_enc + p->offset_enc, p->buffersize_enc); |
261 } else { | 250 } else { |
262 len = recvfrom(sfd, buffer_enc + p->offset_enc, p->buffersize_enc, 0, (struct sockaddr*)&recvaddr, &recvaddr_len); | 251 len = recvfrom(sfd, buffer_enc + p->offset_enc, p->buffersize_enc, 0, (struct sockaddr*)&recvaddr, &recvaddr_len); |
263 } | 252 } |
264 if (len < 0) { | 253 if (len < 0) { |
265 int out; | 254 long long out; |
266 len = 4; | 255 len = sizeof(out); |
267 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); | 256 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); |
268 fprintf(stderr, "End of file on udp socket"); | 257 fprintf(stderr, "Received end of file on udp socket (error %d)\n", out); |
269 } else { | 258 } else { |
270 len = p->decode(&session, buffer_enc, buffer_raw, len); | 259 len = p->decode(&session, buffer_enc, buffer_raw, len); |
271 if (len != 0 && session.remote_float != 0 && (session.remote_addr.sin_addr.s_addr != recvaddr.sin_addr.s_addr || session.remote_addr.sin_port != recvaddr.sin_port)) { | 260 if (len != 0 && session.remote_float != 0 && (session.remote_addr.sin_addr.s_addr != recvaddr.sin_addr.s_addr || session.remote_addr.sin_port != recvaddr.sin_port)) { |
272 fprintf(stderr, "Remote endpoint has changed to %08X:%d\n", recvaddr.sin_addr, ntohs(recvaddr.sin_port)); | 261 fprintf(stderr, "Remote endpoint has changed to %08X:%d\n", recvaddr.sin_addr.s_addr, ntohs(recvaddr.sin_port)); |
273 session.remote_addr = recvaddr; | 262 session.remote_addr = recvaddr; |
274 session.remote_float = 2; | 263 session.remote_float = 2; |
275 } | 264 } |
276 if (len < 0) return len; | 265 if (len < 0) return len; |
277 write(ttfd, buffer_raw + p->offset_raw, len); | 266 write(ttfd, buffer_raw + p->offset_raw, len); |