Mercurial > hg > quicktun
comparison src/common.c @ 35:a1ec0d6b6f13
Added USE_PI=2 setting to automatically add/remove packet information header
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 06 May 2013 18:05:07 +0200 |
parents | b876afa5a72a |
children | 1fe62a94c28a |
comparison
equal
deleted
inserted
replaced
34:b876afa5a72a | 35:a1ec0d6b6f13 |
---|---|
67 void* protocol_data; | 67 void* protocol_data; |
68 int fd_socket; | 68 int fd_socket; |
69 int fd_dev; | 69 int fd_dev; |
70 int remote_float; | 70 int remote_float; |
71 struct sockaddr_in remote_addr; | 71 struct sockaddr_in remote_addr; |
72 int use_pi; | |
72 }; | 73 }; |
73 | 74 |
74 #ifdef COMBINED_BINARY | 75 #ifdef COMBINED_BINARY |
75 extern char* (*getconf)(const char*); | 76 extern char* (*getconf)(const char*); |
76 extern int errorexit(const char*); | 77 extern int errorexit(const char*); |
140 } | 141 } |
141 session->fd_socket = sfd; | 142 session->fd_socket = sfd; |
142 return sfd; | 143 return sfd; |
143 } | 144 } |
144 | 145 |
145 int init_tuntap() { | 146 int init_tuntap(struct qtsession* session) { |
146 char* envval; | 147 char* envval; |
147 fprintf(stderr, "Initializing tun/tap device...\n"); | 148 fprintf(stderr, "Initializing tun/tap device...\n"); |
148 int ttfd; //Tap device file descriptor | 149 int ttfd; //Tap device file descriptor |
150 int tunmode = 0; | |
151 if (envval = getconf("TUN_MODE")) tunmode = atoi(envval); | |
152 session->use_pi = 0; | |
153 if (tunmode && (envval = getconf("USE_PI"))) session->use_pi = atoi(envval); | |
149 #if defined linux | 154 #if defined linux |
150 struct ifreq ifr; //required for tun/tap setup | 155 struct ifreq ifr; //required for tun/tap setup |
151 memset(&ifr, 0, sizeof(ifr)); | 156 memset(&ifr, 0, sizeof(ifr)); |
152 if ((ttfd = open("/dev/net/tun", O_RDWR)) < 0) return errorexitp("Could not open tun/tap device file"); | 157 if ((ttfd = open("/dev/net/tun", O_RDWR)) < 0) return errorexitp("Could not open tun/tap device file"); |
153 if (envval = getconf("INTERFACE")) strcpy(ifr.ifr_name, envval); | 158 if (envval = getconf("INTERFACE")) strcpy(ifr.ifr_name, envval); |
154 if ((envval = getconf("TUN_MODE")) && atoi(envval)) { | 159 ifr.ifr_flags = tunmode ? IFF_TUN : IFF_TAP; |
155 ifr.ifr_flags = IFF_TUN; | 160 if (!session->use_pi) ifr.ifr_flags |= IFF_NO_PI; |
156 } else { | |
157 ifr.ifr_flags = IFF_TAP; | |
158 } | |
159 if (!(envval = getconf("USE_PI")) || !atoi(envval)) { | |
160 ifr.ifr_flags |= IFF_NO_PI; | |
161 } | |
162 if (ioctl(ttfd, TUNSETIFF, (void *)&ifr) < 0) return errorexitp("TUNSETIFF ioctl failed"); | 161 if (ioctl(ttfd, TUNSETIFF, (void *)&ifr) < 0) return errorexitp("TUNSETIFF ioctl failed"); |
163 #elif defined SOLARIS | 162 #elif defined SOLARIS |
164 int ip_fd = -1, if_fd = -1, ppa = 0; | 163 int ip_fd = -1, if_fd = -1, ppa = 0; |
165 if ((ttfd = open("/dev/tun", O_RDWR)) < 0) return errorexitp("Could not open tun device file"); | 164 if ((ttfd = open("/dev/tun", O_RDWR)) < 0) return errorexitp("Could not open tun device file"); |
166 if ((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) return errorexitp("Could not open /dev/ip"); | 165 if ((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) return errorexitp("Could not open /dev/ip"); |
174 if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) return errorexitp("Could not set PPA"); | 173 if (ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0) return errorexitp("Could not set PPA"); |
175 if (ioctl(ip_fd, I_LINK, if_fd) < 0) return errorexitp("Could not link TUN device to IP"); | 174 if (ioctl(ip_fd, I_LINK, if_fd) < 0) return errorexitp("Could not link TUN device to IP"); |
176 #else | 175 #else |
177 if (!(envval = getconf("INTERFACE"))) envval = "/dev/tun0"; | 176 if (!(envval = getconf("INTERFACE"))) envval = "/dev/tun0"; |
178 if ((ttfd = open(envval, O_RDWR)) < 0) return errorexitp("Could not open tun device file"); | 177 if ((ttfd = open(envval, O_RDWR)) < 0) return errorexitp("Could not open tun device file"); |
179 if ((envval = getconf("TUN_MODE")) && atoi(envval)) { | 178 if (tunmode) { |
180 int i = IFF_POINTOPOINT | IFF_MULTICAST; | 179 int i = IFF_POINTOPOINT | IFF_MULTICAST; |
181 ioctl(ttfd, TUNSIFMODE, &i); | 180 ioctl(ttfd, TUNSIFMODE, &i); |
182 if ((envval = getconf("USE_PI")) && atoi(envval)) { | 181 i = session->use_pi ? 1 : 0; |
183 i = 1; | |
184 } else { | |
185 i = 0; | |
186 } | |
187 ioctl(ttfd, TUNSIFHEAD, &i); | 182 ioctl(ttfd, TUNSIFHEAD, &i); |
188 } | 183 } |
189 #endif | 184 #endif |
185 session->fd_dev = ttfd; | |
190 return ttfd; | 186 return ttfd; |
191 } | 187 } |
192 | 188 |
193 void hex2bin(unsigned char* dest, unsigned char* src, int count) { | 189 void hex2bin(unsigned char* dest, unsigned char* src, int count) { |
194 int i; | 190 int i; |
209 struct qtsession session; | 205 struct qtsession session; |
210 session.protocol = *p; | 206 session.protocol = *p; |
211 | 207 |
212 if (init_udp(&session) < 0) return -1; | 208 if (init_udp(&session) < 0) return -1; |
213 int sfd = session.fd_socket; | 209 int sfd = session.fd_socket; |
214 if (sfd == -1) return -1; | 210 |
215 | 211 if (init_tuntap(&session) < 0) return -1; |
216 int ttfd = init_tuntap(); | 212 int ttfd = session.fd_dev; |
217 if (ttfd == -1) return -1; | |
218 session.fd_dev = ttfd; | |
219 | 213 |
220 char protocol_data[p->protocol_data_size]; | 214 char protocol_data[p->protocol_data_size]; |
221 memset(protocol_data, 0, p->protocol_data_size); | 215 memset(protocol_data, 0, p->protocol_data_size); |
222 session.protocol_data = &protocol_data; | 216 session.protocol_data = &protocol_data; |
223 if (p->init && p->init(&session) < 0) return -1; | 217 if (p->init && p->init(&session) < 0) return -1; |
230 fds[1].fd = sfd; | 224 fds[1].fd = sfd; |
231 fds[1].events = POLLIN; | 225 fds[1].events = POLLIN; |
232 | 226 |
233 struct sockaddr_in recvaddr; | 227 struct sockaddr_in recvaddr; |
234 | 228 |
235 char buffer_raw_a[p->buffersize_raw]; | 229 int pi_length = 0; |
230 if (session.use_pi == 2) pi_length = 4; | |
231 | |
232 char buffer_raw_a[p->buffersize_raw + pi_length]; | |
236 char buffer_enc_a[p->buffersize_enc]; | 233 char buffer_enc_a[p->buffersize_enc]; |
237 char* buffer_raw = buffer_raw_a; | 234 char* buffer_raw = buffer_raw_a; |
238 char* buffer_enc = buffer_enc_a; | 235 char* buffer_enc = buffer_enc_a; |
239 | 236 |
240 while (1) { | 237 while (1) { |
241 int len = poll(fds, 2, -1); | 238 int len = poll(fds, 2, -1); |
242 if (len < 0) return errorexitp("poll error"); | 239 if (len < 0) return errorexitp("poll error"); |
243 else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) return errorexit("poll error on tap device"); | 240 else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) return errorexit("poll error on tap device"); |
244 else if (fds[1].revents & (POLLHUP | POLLNVAL)) return errorexit("poll error on udp socket"); | 241 else if (fds[1].revents & (POLLHUP | POLLNVAL)) return errorexit("poll error on udp socket"); |
245 if (fds[0].revents & POLLIN) { | 242 if (fds[0].revents & POLLIN) { |
246 len = read(ttfd, buffer_raw + p->offset_raw, p->buffersize_raw); | 243 len = read(ttfd, buffer_raw + p->offset_raw, p->buffersize_raw + pi_length); |
244 if (len < pi_length) errorexit("read packet smaller than header from tun device"); | |
247 if (session.remote_float == 0 || session.remote_float == 2) { | 245 if (session.remote_float == 0 || session.remote_float == 2) { |
248 len = p->encode(&session, buffer_raw, buffer_enc, len); | 246 len = p->encode(&session, buffer_raw + pi_length, buffer_enc, len - pi_length); |
249 if (len < 0) return len; | 247 if (len < 0) return len; |
250 if (session.remote_float == 0) { | 248 if (session.remote_float == 0) { |
251 len = write(sfd, buffer_enc + p->offset_enc, len); | 249 len = write(sfd, buffer_enc + p->offset_enc, len); |
252 } else { | 250 } else { |
253 len = sendto(sfd, buffer_enc + p->offset_enc, len, 0, (struct sockaddr*)&session.remote_addr, sizeof(session.remote_addr)); | 251 len = sendto(sfd, buffer_enc + p->offset_enc, len, 0, (struct sockaddr*)&session.remote_addr, sizeof(session.remote_addr)); |
271 long long out; | 269 long long out; |
272 len = sizeof(out); | 270 len = sizeof(out); |
273 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); | 271 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); |
274 fprintf(stderr, "Received end of file on udp socket (error %d)\n", out); | 272 fprintf(stderr, "Received end of file on udp socket (error %d)\n", out); |
275 } else { | 273 } else { |
276 len = p->decode(&session, buffer_enc, buffer_raw, len); | 274 len = p->decode(&session, buffer_enc, buffer_raw + pi_length, len); |
277 if (len < 0) return len; | 275 if (len < 0) return len; |
278 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)) { | 276 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)) { |
279 fprintf(stderr, "Remote endpoint has changed to %08X:%d\n", ntohl(recvaddr.sin_addr.s_addr), ntohs(recvaddr.sin_port)); | 277 fprintf(stderr, "Remote endpoint has changed to %08X:%d\n", ntohl(recvaddr.sin_addr.s_addr), ntohs(recvaddr.sin_port)); |
280 session.remote_addr = recvaddr; | 278 session.remote_addr = recvaddr; |
281 session.remote_float = 2; | 279 session.remote_float = 2; |
282 } | 280 } |
283 write(ttfd, buffer_raw + p->offset_raw, len); | 281 if (session.use_pi == 2) { |
282 int ipver = 0; | |
283 if (len >= 1) ipver = (buffer_raw[p->offset_raw + pi_length] >> 4) & 0xf; | |
284 int pihdr = 0; | |
285 #if defined linux | |
286 if (ipver == 4) pihdr = 0x0000 | (0x0008 << 16); //little endian: flags and protocol are swapped | |
287 else if (ipver == 6) pihdr = 0x0000 | (0xdd86 << 16); | |
288 #else | |
289 if (ipver == 4) pihdr = htonl(AF_INET); | |
290 else if (ipver == 6) pihdr = htonl(AF_INET6); | |
291 #endif | |
292 *(int*)(buffer_raw + p->offset_raw) = ipver; | |
293 } | |
294 write(ttfd, buffer_raw + p->offset_raw, len + pi_length); | |
284 } | 295 } |
285 } | 296 } |
286 } | 297 } |
287 return 0; | 298 return 0; |
288 } | 299 } |