aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
Diffstat (limited to 'src/vpn')
-rw-r--r--src/vpn/gnunet-helper-vpn.c275
1 files changed, 151 insertions, 124 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c
index 25a9492eb..6dc858f97 100644
--- a/src/vpn/gnunet-helper-vpn.c
+++ b/src/vpn/gnunet-helper-vpn.c
@@ -62,17 +62,6 @@ struct suid_packet
62 unsigned char data[1]; 62 unsigned char data[1];
63} 63}
64 64
65static int running = 1;
66
67static void
68term (int sig)
69{
70 fprintf (stderr,
71 "Got SIGTERM...\n");
72 if (sig == SIGTERM)
73 running = 0;
74}
75
76 65
77/** 66/**
78 * Creates a tun-interface called dev; 67 * Creates a tun-interface called dev;
@@ -113,13 +102,14 @@ init_tun (char *dev)
113 "Error with ioctl on `%s': %s\n", 102 "Error with ioctl on `%s': %s\n",
114 "/dev/net/tun", 103 "/dev/net/tun",
115 strerror(errno)); 104 strerror(errno));
116 close(fd); 105 close (fd);
117 return -1; 106 return -1;
118 } 107 }
119 strcpy(dev, ifr.ifr_name); 108 strcpy(dev, ifr.ifr_name);
120 return fd; 109 return fd;
121} 110}
122 111
112
123/** 113/**
124 * @brief Sets the IPv6-Address given in address on the interface dev 114 * @brief Sets the IPv6-Address given in address on the interface dev
125 * 115 *
@@ -128,53 +118,83 @@ init_tun (char *dev)
128 * @param prefix_len the length of the network-prefix 118 * @param prefix_len the length of the network-prefix
129 */ 119 */
130static void 120static void
131set_address6 (char *dev, char *address, unsigned long prefix_len) 121set_address6 (const char *dev,
122 const char *address,
123 unsigned long prefix_len)
132{ 124{
133 int fd = socket (AF_INET6, SOCK_DGRAM, 0); 125 struct ifreq ifr;
126 struct in6_ifreq ifr6;
127 struct sockaddr_in6 sa6;
128 int fd;
134 129
135 if (fd < 0) 130 if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0)))
136 { 131 {
137 fprintf (stderr, "error creating socket: %m\n"); 132 fprintf (stderr,
133 "Error creating socket: %s\n",
134 strerror (errno));
138 exit (1); 135 exit (1);
139 } 136 }
140
141 struct ifreq ifr;
142 struct in6_ifreq ifr6;
143
144 struct sockaddr_in6 sa6;
145 memset (&sa6, 0, sizeof (struct sockaddr_in6)); 137 memset (&sa6, 0, sizeof (struct sockaddr_in6));
146
147 sa6.sin6_family = AF_INET6; 138 sa6.sin6_family = AF_INET6;
148 139
149 int r = inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr); 140 if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr))
150 if (r < 0)
151 { 141 {
152 fprintf (stderr, "error at inet_pton: %m\n"); 142 fprintf (stderr,
143 "Failed to parse address `%s': %s\n",
144 address,
145 strerror (errno));
153 exit (1); 146 exit (1);
154 } 147 }
155 148
156 memcpy ((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, 149 memcpy (&ifr6.ifr6_addr,
150 &sa6.sin6_addr,
157 sizeof (struct in6_addr)); 151 sizeof (struct in6_addr));
158
159 strncpy (ifr.ifr_name, dev, IFNAMSIZ); 152 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
160 153 if (-1 == ioctl (fd, SIOGIFINDEX, &ifr))
161 if (ioctl (fd, SIOGIFINDEX, &ifr) < 0)
162 { 154 {
163 perror ("SIOGIFINDEX"); 155 fprintf (stderr,
156 "ioctl failed at %d: %s\n",
157 __LINE__,
158 strerror (errno));
159 exit (1);
164 } 160 }
165 161
166 ifr6.ifr6_ifindex = ifr.ifr_ifindex; 162 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
167 ifr6.ifr6_prefixlen = prefix_len; 163 ifr6.ifr6_prefixlen = prefix_len;
168 164 if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6))
169 if (ioctl (fd, SIOCSIFADDR, &ifr6) < 0)
170 { 165 {
171 perror ("SIOCSIFADDR"); 166 fprintf (stderr,
167 "ioctl failed at line %d: %s\n",
168 __LINE__,
169 strerror (errno));
170 exit (1);
172 } 171 }
173 172
174 (void) ioctl (fd, SIOCGIFFLAGS, &ifr); 173 if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr))
174 {
175 fprintf (stderr,
176 "ioctl failed at line %d: %s\n",
177 __LINE__,
178 strerror (errno));
179 exit (1);
180 }
175 ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 181 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
176 (void) ioctl (fd, SIOCSIFFLAGS, &ifr); 182 if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr))
177 close (fd); 183 {
184 fprintf (stderr,
185 "ioctl failed at line %d: %s\n",
186 __LINE__,
187 strerror (errno));
188 exit (1);
189 }
190
191 if (0 != close (fd))
192 {
193 fprintf (stderr,
194 "close failed: %s\n",
195 strerror (errno));
196 exit (1);
197 }
178} 198}
179 199
180 200
@@ -243,79 +263,19 @@ set_address4 (char *dev, char *address, char *mask)
243} 263}
244 264
245 265
246/**
247 * @brief sets the socket to nonblocking
248 *
249 * @param fd the socket
250 */
251static void 266static void
252setnonblocking (int fd) 267run (int fd_tun)
253{ /*{{{ */
254 int opts;
255 opts = fcntl(fd,F_GETFL);
256 if (opts < 0) {
257 perror("fcntl(F_GETFL)");
258 }
259 opts = (opts | O_NONBLOCK);
260 if (fcntl(fd,F_SETFL,opts) < 0) {
261 perror("fcntl(F_SETFL)");
262 }
263 return;
264}
265
266
267int
268main(int argc, char** argv)
269{ 268{
270 unsigned char buf[MAX_SIZE]; 269 unsigned char buf[MAX_SIZE];
271
272 char dev[IFNAMSIZ];
273 memset (dev, 0, IFNAMSIZ);
274
275 signal (SIGTERM, &term);
276
277 int fd_tun = init_tun (dev);
278
279 if (fd_tun < 0)
280 {
281 fprintf (stderr, "Could not initialize tun-interface: %s\n",
282 strerror (errno));
283 exit (1);
284 }
285
286 {
287 // TODO: get this out of argv
288 char address[] = "1234::1";
289 unsigned long prefix_len = 16;
290
291 set_address6 (dev, address, prefix_len);
292 }
293
294 {
295 char address[] = "10.10.10.1";
296 char mask[] = "255.255.255.252";
297
298 set_address4 (dev, address, mask);
299 }
300
301 uid_t uid = getuid ();
302 if (setresuid (uid, uid, uid) != 0)
303 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
304
305 setnonblocking (0);
306 setnonblocking (1);
307 setnonblocking (fd_tun);
308
309 fd_set fds_w; 270 fd_set fds_w;
310 fd_set fds_r; 271 fd_set fds_r;
311
312 int rea = 1; 272 int rea = 1;
313 int wri = 1; 273 int wri = 1;
314
315 int write_fd_possible = 0; 274 int write_fd_possible = 0;
316 int write_stdout_possible = 0; 275 int write_stdout_possible = 0;
276 ssize_t tin;
317outer: 277outer:
318 while ((rea == 1 || wri == 1) && running == 1) 278 while ((1 == rea) || (1 == wri))
319 { 279 {
320 FD_ZERO (&fds_w); 280 FD_ZERO (&fds_w);
321 FD_ZERO (&fds_r); 281 FD_ZERO (&fds_r);
@@ -334,8 +294,7 @@ outer:
334 FD_SET (fd_tun, &fds_w); 294 FD_SET (fd_tun, &fds_w);
335 } 295 }
336 296
337 int r = select (fd_tun + 1, &fds_r, &fds_w, (fd_set *) 0, 0); 297 int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL);
338
339 if (r > 0) 298 if (r > 0)
340 { 299 {
341 if (FD_ISSET (fd_tun, &fds_w)) 300 if (FD_ISSET (fd_tun, &fds_w))
@@ -347,8 +306,8 @@ outer:
347 { 306 {
348 write_fd_possible = 0; 307 write_fd_possible = 0;
349 struct suid_packet *pkt = (struct suid_packet *) buf; 308 struct suid_packet *pkt = (struct suid_packet *) buf;
350 r = read (0, buf, sizeof (struct GNUNET_MessageHeader)); 309 tin = read (0, buf, sizeof (struct GNUNET_MessageHeader));
351 if (r <= 0) 310 if (tin <= 0)
352 { 311 {
353 fprintf (stderr, "read-error: %s\n", strerror (errno)); 312 fprintf (stderr, "read-error: %s\n", strerror (errno));
354 shutdown (fd_tun, SHUT_WR); 313 shutdown (fd_tun, SHUT_WR);
@@ -358,10 +317,10 @@ outer:
358 } 317 }
359 if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER)) 318 if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER))
360 abort (); 319 abort ();
361 while (r < ntohs (pkt->hdr.size)) 320 while (tin < ntohs (pkt->hdr.size))
362 { 321 {
363 int t = read (0, buf + r, ntohs (pkt->hdr.size) - r); 322 ssize_t t = read (0, buf + tin, ntohs (pkt->hdr.size) - tin);
364 if (r < 0) 323 if (t <= 0)
365 { 324 {
366 fprintf (stderr, "read-error: %s\n", strerror (errno)); 325 fprintf (stderr, "read-error: %s\n", strerror (errno));
367 shutdown (fd_tun, SHUT_WR); 326 shutdown (fd_tun, SHUT_WR);
@@ -369,17 +328,17 @@ outer:
369 wri = 0; 328 wri = 0;
370 goto outer; 329 goto outer;
371 } 330 }
372 r += t; 331 tin += t;
373 } 332 }
374 r = 0; 333 tin = 0;
375 while (r < 334 while (tin <
376 ntohs (pkt->hdr.size) - 335 ntohs (pkt->hdr.size) -
377 sizeof (struct GNUNET_MessageHeader)) 336 sizeof (struct GNUNET_MessageHeader))
378 { 337 {
379 int t = write (fd_tun, pkt->data, 338 ssize_t t = write (fd_tun, pkt->data,
380 ntohs (pkt->hdr.size) - 339 ntohs (pkt->hdr.size) -
381 sizeof (struct GNUNET_MessageHeader) - r); 340 sizeof (struct GNUNET_MessageHeader) - tin);
382 if (t < 0) 341 if (t <= 0)
383 { 342 {
384 fprintf (stderr, "write-error 3: %s\n", 343 fprintf (stderr, "write-error 3: %s\n",
385 strerror (errno)); 344 strerror (errno));
@@ -388,14 +347,14 @@ outer:
388 wri = 0; 347 wri = 0;
389 goto outer; 348 goto outer;
390 } 349 }
391 r += t; 350 tin += t;
392 } 351 }
393 } 352 }
394 else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r)) 353 else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r))
395 { 354 {
396 write_stdout_possible = 0; 355 write_stdout_possible = 0;
397 r = read (fd_tun, buf, MAX_SIZE); 356 tin = read (fd_tun, buf, MAX_SIZE);
398 if (r <= 0) 357 if (tin <= 0)
399 { 358 {
400 fprintf (stderr, "read-error: %s\n", strerror (errno)); 359 fprintf (stderr, "read-error: %s\n", strerror (errno));
401 shutdown (fd_tun, SHUT_RD); 360 shutdown (fd_tun, SHUT_RD);
@@ -407,11 +366,11 @@ outer:
407 htons (r + sizeof (struct GNUNET_MessageHeader)),.type = 366 htons (r + sizeof (struct GNUNET_MessageHeader)),.type =
408 htons (GNUNET_MESSAGE_TYPE_VPN_HELPER) 367 htons (GNUNET_MESSAGE_TYPE_VPN_HELPER)
409 }; 368 };
410 r = 0; 369 tin = 0;
411 while (r < sizeof (struct GNUNET_MessageHeader)) 370 while (tin < sizeof (struct GNUNET_MessageHeader))
412 { 371 {
413 int t = 372 ssize_t t =
414 write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - r); 373 write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - tin);
415 if (t < 0) 374 if (t < 0)
416 { 375 {
417 fprintf (stderr, "write-error 2: %s\n", 376 fprintf (stderr, "write-error 2: %s\n",
@@ -421,11 +380,11 @@ outer:
421 rea = 0; 380 rea = 0;
422 goto outer; 381 goto outer;
423 } 382 }
424 r += t; 383 tin += t;
425 } 384 }
426 while (r < ntohs (hdr.size)) 385 while (tin < ntohs (hdr.size))
427 { 386 {
428 int t = write (1, buf, ntohs (hdr.size) - r); 387 size_t t = write (1, buf, ntohs (hdr.size) - tin);
429 if (t < 0) 388 if (t < 0)
430 { 389 {
431 fprintf (stderr, "write-error 1: %s, written %d/%d\n", 390 fprintf (stderr, "write-error 1: %s, written %d/%d\n",
@@ -435,13 +394,81 @@ outer:
435 rea = 0; 394 rea = 0;
436 goto outer; 395 goto outer;
437 } 396 }
438 r += t; 397 tin += t;
439 } 398 }
440 } 399 }
441 } 400 }
442 } 401 }
402}
403
443 404
444 close (fd_tun);
445 405
406/**
407 * @brief sets the socket to nonblocking
408 *
409 * @param fd the socket
410 */
411static void
412setnonblocking (int fd)
413{
414 int opts;
415
416 if (-1 == (opts = fcntl (fd, F_GETFL)))
417 {
418 fprintf (stderr,
419 "Error in fcntl at line %d: %s\n",
420 __LINE__,
421 strerror (errno));
422 exit (1);
423 }
424 opts |= O_NONBLOCK;
425 if (-1 == fcntl (fd, F_SETFL, opts))
426 {
427 fprintf (stderr,
428 "Error in fcntl at line %d: %s\n",
429 __LINE__,
430 strerror (errno));
431 exit (1);
432 }
433}
434
435
436int
437main (int argc,
438 char** argv)
439{
440 char dev[IFNAMSIZ];
441 int fd_tun;
442
443 memset (dev, 0, IFNAMSIZ);
444 if (-1 == (fd_tun = init_tun (dev)))
445 {
446 fprintf (stderr,
447 "Fatal: could not initialize tun-interface\n");
448 return 1;
449 }
450
451 {
452 // TODO: get this out of argv
453 char address[] = "1234::1";
454 unsigned long prefix_len = 16;
455
456 set_address6 (dev, address, prefix_len);
457 }
458
459 {
460 char address[] = "10.10.10.1";
461 char mask[] = "255.255.255.252";
462
463 set_address4 (dev, address, mask);
464 }
465
466 uid_t uid = getuid ();
467 if (0 != setresuid (uid, uid, uid))
468 fprintf (stderr,
469 "Failed to setresuid: %s\n",
470 strerror (errno));
471 run (fd_tun);
472 close (fd_tun);
446 return 0; 473 return 0;
447} 474}