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 }