comparison src/common.c @ 41:54d28a81ca99

Small updates in preparation for stateful protocols
author Ivo Smits <Ivo@UCIS.nl>
date Thu, 16 May 2013 01:15:01 +0200
parents 47a34fe75c57
children e896392f7e03
comparison
equal deleted inserted replaced
40:ed9581189d6b 41:54d28a81ca99
60 int offset_enc; 60 int offset_enc;
61 int (*encode)(struct qtsession* sess, char* raw, char* enc, int len); 61 int (*encode)(struct qtsession* sess, char* raw, char* enc, int len);
62 int (*decode)(struct qtsession* sess, char* enc, char* raw, int len); 62 int (*decode)(struct qtsession* sess, char* enc, char* raw, int len);
63 int (*init)(struct qtsession* sess); 63 int (*init)(struct qtsession* sess);
64 int protocol_data_size; 64 int protocol_data_size;
65 void (*idle)(struct qtsession* sess);
65 }; 66 };
66 struct qtsession { 67 struct qtsession {
67 struct qtproto protocol; 68 struct qtproto protocol;
68 void* protocol_data; 69 void* protocol_data;
69 int fd_socket; 70 int fd_socket;
70 int fd_dev; 71 int fd_dev;
71 int remote_float; 72 int remote_float;
72 struct sockaddr_in remote_addr; 73 struct sockaddr_in remote_addr;
73 int use_pi; 74 int use_pi;
75 int poll_timeout;
76 void (*sendnetworkpacket)(struct qtsession* sess, char* msg, int len);
74 }; 77 };
75 78
76 #ifdef COMBINED_BINARY 79 #ifdef COMBINED_BINARY
77 extern char* (*getconf)(const char*); 80 extern char* (*getconf)(const char*);
78 extern int errorexit(const char*); 81 extern int errorexit(const char*);
99 void print_header() { 102 void print_header() {
100 fprintf(stderr, "UCIS QuickTun "QT_VERSION" (c) 2010-2013 Ivo Smits <Ivo@UCIS.nl>\n"); 103 fprintf(stderr, "UCIS QuickTun "QT_VERSION" (c) 2010-2013 Ivo Smits <Ivo@UCIS.nl>\n");
101 fprintf(stderr, "More information: http://wiki.ucis.nl/QuickTun\n"); 104 fprintf(stderr, "More information: http://wiki.ucis.nl/QuickTun\n");
102 } 105 }
103 106
104 int init_udp(struct qtsession* session) { 107 static int init_udp(struct qtsession* session) {
105 char* envval; 108 char* envval;
106 fprintf(stderr, "Initializing UDP socket...\n"); 109 fprintf(stderr, "Initializing UDP socket...\n");
107 int sfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 110 int sfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
108 if (sfd < 0) return errorexitp("Could not create UDP socket"); 111 if (sfd < 0) return errorexitp("Could not create UDP socket");
109 struct sockaddr_in udpaddr; 112 struct sockaddr_in udpaddr;
144 } 147 }
145 session->fd_socket = sfd; 148 session->fd_socket = sfd;
146 return sfd; 149 return sfd;
147 } 150 }
148 151
149 int init_tuntap(struct qtsession* session) { 152 static int init_tuntap(struct qtsession* session) {
150 char* envval; 153 char* envval;
151 fprintf(stderr, "Initializing tun/tap device...\n"); 154 fprintf(stderr, "Initializing tun/tap device...\n");
152 int ttfd; //Tap device file descriptor 155 int ttfd; //Tap device file descriptor
153 int tunmode = 0; 156 int tunmode = 0;
154 if (envval = getconf("TUN_MODE")) tunmode = atoi(envval); 157 if (envval = getconf("TUN_MODE")) tunmode = atoi(envval);
202 else if (*src >= 'A' && *src <= 'F') *dest += *src - 'A' + 10; 205 else if (*src >= 'A' && *src <= 'F') *dest += *src - 'A' + 10;
203 src++; dest++; 206 src++; dest++;
204 } 207 }
205 } 208 }
206 209
207 int drop_privileges() { 210 static int drop_privileges() {
208 char* envval; 211 char* envval;
209 if (envval = getconf("SETUID")) { 212 if (envval = getconf("SETUID")) {
210 if (setgroups(0, NULL) == -1) return errorexitp("setgroups"); 213 if (setgroups(0, NULL) == -1) return errorexitp("setgroups");
211 struct passwd *pw = getpwnam(envval); 214 struct passwd *pw = getpwnam(envval);
212 if (!pw) return errorexitp("getpwnam"); 215 if (!pw) return errorexitp("getpwnam");
214 if (setuid(pw->pw_uid) == -1) return errorexitp("setuid"); 217 if (setuid(pw->pw_uid) == -1) return errorexitp("setuid");
215 } 218 }
216 chdir("/"); 219 chdir("/");
217 } 220 }
218 221
222 static void qtsendnetworkpacket(struct qtsession* session, char* msg, int len) {
223 if (session->remote_float == 0) {
224 len = write(session->fd_socket, msg, len);
225 } else if (session->remote_float == 2) {
226 len = sendto(session->fd_socket, msg, len, 0, (struct sockaddr*)&session->remote_addr, sizeof(struct sockaddr_in));
227 }
228 }
229
219 int qtrun(struct qtproto* p) { 230 int qtrun(struct qtproto* p) {
220 if (getconf("DEBUG")) debug = 1; 231 if (getconf("DEBUG")) debug = 1;
221 struct qtsession session; 232 struct qtsession session;
233 session.poll_timeout = -1;
222 session.protocol = *p; 234 session.protocol = *p;
223 235
224 if (init_udp(&session) < 0) return -1; 236 if (init_udp(&session) < 0) return -1;
225 int sfd = session.fd_socket; 237 int sfd = session.fd_socket;
238
239 session.sendnetworkpacket = qtsendnetworkpacket;
226 240
227 if (init_tuntap(&session) < 0) return -1; 241 if (init_tuntap(&session) < 0) return -1;
228 int ttfd = session.fd_dev; 242 int ttfd = session.fd_dev;
229 243
230 char protocol_data[p->protocol_data_size]; 244 char protocol_data[p->protocol_data_size];
251 char buffer_enc_a[p->buffersize_enc]; 265 char buffer_enc_a[p->buffersize_enc];
252 char* buffer_raw = buffer_raw_a; 266 char* buffer_raw = buffer_raw_a;
253 char* buffer_enc = buffer_enc_a; 267 char* buffer_enc = buffer_enc_a;
254 268
255 while (1) { 269 while (1) {
256 int len = poll(fds, 2, -1); 270 int len = poll(fds, 2, session.poll_timeout);
257 if (len < 0) return errorexitp("poll error"); 271 if (len < 0) return errorexitp("poll error");
258 else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) return errorexit("poll error on tap device"); 272 else if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) return errorexit("poll error on tap device");
259 else if (fds[1].revents & (POLLHUP | POLLNVAL)) return errorexit("poll error on udp socket"); 273 else if (fds[1].revents & (POLLHUP | POLLNVAL)) return errorexit("poll error on udp socket");
274 if (len == 0 && p->idle) p->idle(&session);
260 if (fds[0].revents & POLLIN) { 275 if (fds[0].revents & POLLIN) {
261 len = read(ttfd, buffer_raw + p->offset_raw, p->buffersize_raw + pi_length); 276 len = read(ttfd, buffer_raw + p->offset_raw, p->buffersize_raw + pi_length);
262 if (len < pi_length) errorexit("read packet smaller than header from tun device"); 277 if (len < pi_length) errorexit("read packet smaller than header from tun device");
263 if (session.remote_float == 0 || session.remote_float == 2) { 278 if (session.remote_float == 0 || session.remote_float == 2) {
264 len = p->encode(&session, buffer_raw + pi_length, buffer_enc, len - pi_length); 279 len = p->encode(&session, buffer_raw + pi_length, buffer_enc, len - pi_length);
265 if (len < 0) return len; 280 if (len < 0) return len;
266 if (session.remote_float == 0) { 281 if (len == 0) continue; //encoding is not yet possible
267 len = write(sfd, buffer_enc + p->offset_enc, len); 282 qtsendnetworkpacket(&session, buffer_enc + p->offset_enc, len);
268 } else {
269 len = sendto(sfd, buffer_enc + p->offset_enc, len, 0, (struct sockaddr*)&session.remote_addr, sizeof(session.remote_addr));
270 }
271 } 283 }
272 } 284 }
273 if (fds[1].revents & POLLERR) { 285 if (fds[1].revents & POLLERR) {
274 int out; 286 int out;
275 len = sizeof(out); 287 len = sizeof(out);
285 } 297 }
286 if (len < 0) { 298 if (len < 0) {
287 long long out; 299 long long out;
288 len = sizeof(out); 300 len = sizeof(out);
289 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); 301 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len);
290 fprintf(stderr, "Received end of file on udp socket (error %d)\n", out); 302 fprintf(stderr, "Received end of file on udp socket (error %lld)\n", out);
291 } else { 303 } else {
292 len = p->decode(&session, buffer_enc, buffer_raw + pi_length, len); 304 len = p->decode(&session, buffer_enc, buffer_raw + pi_length, len);
293 if (len < 0) return len; 305 if (len < 0) continue;
294 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)) { 306 if (session.remote_float != 0 && (session.remote_addr.sin_addr.s_addr != recvaddr.sin_addr.s_addr || session.remote_addr.sin_port != recvaddr.sin_port)) {
295 fprintf(stderr, "Remote endpoint has changed to %08X:%d\n", ntohl(recvaddr.sin_addr.s_addr), ntohs(recvaddr.sin_port)); 307 fprintf(stderr, "Remote endpoint has changed to %08X:%d\n", ntohl(recvaddr.sin_addr.s_addr), ntohs(recvaddr.sin_port));
296 session.remote_addr = recvaddr; 308 session.remote_addr = recvaddr;
297 session.remote_float = 2; 309 session.remote_float = 2;
298 } 310 }
299 if (session.use_pi == 2) { 311 if (len > 0 && session.use_pi == 2) {
300 int ipver = 0; 312 int ipver = (buffer_raw[p->offset_raw + pi_length] >> 4) & 0xf;
301 if (len >= 1) ipver = (buffer_raw[p->offset_raw + pi_length] >> 4) & 0xf;
302 int pihdr = 0; 313 int pihdr = 0;
303 #if defined linux 314 #if defined linux
304 if (ipver == 4) pihdr = 0x0000 | (0x0008 << 16); //little endian: flags and protocol are swapped 315 if (ipver == 4) pihdr = 0x0000 | (0x0008 << 16); //little endian: flags and protocol are swapped
305 else if (ipver == 6) pihdr = 0x0000 | (0xdd86 << 16); 316 else if (ipver == 6) pihdr = 0x0000 | (0xdd86 << 16);
306 #else 317 #else
307 if (ipver == 4) pihdr = htonl(AF_INET); 318 if (ipver == 4) pihdr = htonl(AF_INET);
308 else if (ipver == 6) pihdr = htonl(AF_INET6); 319 else if (ipver == 6) pihdr = htonl(AF_INET6);
309 #endif 320 #endif
310 *(int*)(buffer_raw + p->offset_raw) = ipver; 321 *(int*)(buffer_raw + p->offset_raw) = ipver;
311 } 322 }
312 write(ttfd, buffer_raw + p->offset_raw, len + pi_length); 323 if (len > 0) write(ttfd, buffer_raw + p->offset_raw, len + pi_length);
313 } 324 }
314 } 325 }
315 } 326 }
316 return 0; 327 return 0;
317 } 328 }
318 329
319 char* getconfcmdargs(const char* name) { 330 static char* getconfcmdargs(const char* name) {
320 int i; 331 int i;
321 for (i = 1; i < gargc - 2; i++) { 332 for (i = 1; i < gargc - 2; i++) {
322 if (strcmp(gargv[i], "-c")) continue; 333 if (strcmp(gargv[i], "-c")) continue;
323 if (strcmp(gargv[i + 1], name)) continue; 334 if (strcmp(gargv[i + 1], name)) continue;
324 return gargv[i + 2]; 335 return gargv[i + 2];