diff options
-rw-r--r-- | src/vpn/gnunet-helper-vpn.c | 553 |
1 files changed, 313 insertions, 240 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c index 1d21a431f..c2ebe6c7b 100644 --- a/src/vpn/gnunet-helper-vpn.c +++ b/src/vpn/gnunet-helper-vpn.c | |||
@@ -20,7 +20,9 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file vpn/gnunet-daemon-vpn.c | 22 | * @file vpn/gnunet-daemon-vpn.c |
23 | * @brief | 23 | * @brief the helper for various vpn-daemons. Opens a virtual network-interface, |
24 | * sends data received on the if to stdout, sends data received on stdin to the | ||
25 | * interface | ||
24 | * @author Philipp Tölke | 26 | * @author Philipp Tölke |
25 | */ | 27 | */ |
26 | #include <platform.h> | 28 | #include <platform.h> |
@@ -31,280 +33,351 @@ | |||
31 | #include "gnunet-vpn-helper-p.h" | 33 | #include "gnunet-vpn-helper-p.h" |
32 | 34 | ||
33 | #ifndef _LINUX_IN6_H | 35 | #ifndef _LINUX_IN6_H |
34 | // This is in linux/include/net/ipv6.h. | ||
35 | 36 | ||
36 | #define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader)) | 37 | #define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader)) |
37 | 38 | ||
38 | struct in6_ifreq { | 39 | // This is in linux/include/net/ipv6.h. |
39 | struct in6_addr ifr6_addr; | 40 | struct in6_ifreq |
40 | uint32_t ifr6_prefixlen; | 41 | { |
41 | unsigned int ifr6_ifindex; | 42 | struct in6_addr ifr6_addr; |
43 | uint32_t ifr6_prefixlen; | ||
44 | unsigned int ifr6_ifindex; | ||
42 | }; | 45 | }; |
43 | 46 | ||
44 | #endif | 47 | #endif |
45 | 48 | ||
46 | int running = 1; | 49 | static int running = 1; |
47 | 50 | ||
48 | void term(int sig) { | 51 | static void |
49 | fprintf(stderr, "Got SIGTERM...\n"); | 52 | term (int sig) |
50 | if (sig == SIGTERM) | 53 | { |
51 | running = 0; | 54 | fprintf (stderr, "Got SIGTERM...\n"); |
55 | if (sig == SIGTERM) | ||
56 | running = 0; | ||
52 | } | 57 | } |
53 | 58 | ||
54 | static void set_address6(char* dev, char* address, unsigned long prefix_len) { /* {{{ */ | 59 | /** |
55 | int fd = socket(AF_INET6, SOCK_DGRAM, 0); | 60 | * @brief Sets the IPv6-Address given in address on the interface dev |
56 | 61 | * | |
57 | if (fd < 0) | 62 | * @param dev the interface to configure |
58 | { | 63 | * @param address the IPv6-Address |
59 | fprintf(stderr, "error creating socket: %m\n"); | 64 | * @param prefix_len the length of the network-prefix |
60 | exit(1); | 65 | */ |
61 | } | 66 | static void |
62 | 67 | set_address6 (char *dev, char *address, unsigned long prefix_len) | |
63 | struct ifreq ifr; | 68 | { /* {{{ */ |
64 | struct in6_ifreq ifr6; | 69 | int fd = socket (AF_INET6, SOCK_DGRAM, 0); |
65 | |||
66 | struct sockaddr_in6 sa6; | ||
67 | memset(&sa6, 0, sizeof(struct sockaddr_in6)); | ||
68 | |||
69 | sa6.sin6_family = AF_INET6; | ||
70 | |||
71 | int r = inet_pton(AF_INET6, address, sa6.sin6_addr.s6_addr); | ||
72 | if (r < 0) | ||
73 | { | ||
74 | fprintf(stderr, "error at inet_pton: %m\n"); | ||
75 | exit(1); | ||
76 | } | ||
77 | |||
78 | memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr)); | ||
79 | |||
80 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); | ||
81 | |||
82 | if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) { | ||
83 | perror("SIOGIFINDEX"); | ||
84 | } | ||
85 | 70 | ||
86 | ifr6.ifr6_ifindex = ifr.ifr_ifindex; | 71 | if (fd < 0) |
87 | ifr6.ifr6_prefixlen = prefix_len; | 72 | { |
73 | fprintf (stderr, "error creating socket: %m\n"); | ||
74 | exit (1); | ||
75 | } | ||
88 | 76 | ||
89 | if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) { | 77 | struct ifreq ifr; |
90 | perror("SIOCSIFADDR"); | 78 | struct in6_ifreq ifr6; |
91 | } | ||
92 | 79 | ||
93 | (void)ioctl(fd, SIOCGIFFLAGS, &ifr); | 80 | struct sockaddr_in6 sa6; |
94 | ifr.ifr_flags |= IFF_UP | IFF_RUNNING; | 81 | memset (&sa6, 0, sizeof (struct sockaddr_in6)); |
95 | (void)ioctl(fd, SIOCSIFFLAGS, &ifr); | ||
96 | close(fd); | ||
97 | } /* }}} */ | ||
98 | |||
99 | static void set_address4(char* dev, char* address, char* mask) { /* {{{ */ | ||
100 | int fd=0; | ||
101 | struct sockaddr_in* addr; | ||
102 | struct ifreq ifr; | ||
103 | |||
104 | memset(&ifr, 0, sizeof(struct ifreq)); | ||
105 | addr = (struct sockaddr_in *)&(ifr.ifr_addr); | ||
106 | memset(addr, 0, sizeof(struct sockaddr_in)); | ||
107 | addr->sin_family = AF_INET; | ||
108 | addr->sin_addr.s_addr = inet_addr(address); | ||
109 | |||
110 | int r = inet_pton(AF_INET, address, &addr->sin_addr.s_addr); | ||
111 | if (r < 0) | ||
112 | { | ||
113 | fprintf(stderr, "error at inet_pton: %m\n"); | ||
114 | exit(1); | ||
115 | } | ||
116 | |||
117 | fd = socket(PF_INET, SOCK_DGRAM, 0); | ||
118 | if(fd < 0) { | ||
119 | perror("socket()"); | ||
120 | return; | ||
121 | } | ||
122 | 82 | ||
123 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); | 83 | sa6.sin6_family = AF_INET6; |
124 | 84 | ||
125 | if(ioctl(fd, SIOCSIFADDR, &ifr) != 0 ) { | 85 | int r = inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr); |
126 | perror("SIOCSIFADDR"); | 86 | if (r < 0) |
127 | close(fd); | 87 | { |
128 | return; | 88 | fprintf (stderr, "error at inet_pton: %m\n"); |
129 | } | 89 | exit (1); |
130 | 90 | } | |
131 | addr = (struct sockaddr_in*)&(ifr.ifr_netmask); | ||
132 | r = inet_pton(AF_INET, mask, &addr->sin_addr.s_addr); | ||
133 | if (r < 0) | ||
134 | { | ||
135 | fprintf(stderr, "error at inet_pton: %m\n"); | ||
136 | exit(1); | ||
137 | } | ||
138 | |||
139 | if(ioctl(fd, SIOCSIFNETMASK, &ifr) != 0 ) { | ||
140 | perror("SIOCSIFNETMASK"); | ||
141 | close(fd); | ||
142 | return; | ||
143 | } | ||
144 | 91 | ||
145 | (void)ioctl(fd, SIOCGIFFLAGS, &ifr); | 92 | memcpy ((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, |
146 | ifr.ifr_flags |= IFF_UP | IFF_RUNNING; | 93 | sizeof (struct in6_addr)); |
147 | (void)ioctl(fd, SIOCSIFFLAGS, &ifr); | ||
148 | close(fd); | ||
149 | } /* }}} */ | ||
150 | 94 | ||
151 | void setnonblocking(int fd) {/*{{{*/ | 95 | strncpy (ifr.ifr_name, dev, IFNAMSIZ); |
152 | int opts; | ||
153 | 96 | ||
154 | opts = fcntl(fd,F_GETFL); | 97 | if (ioctl (fd, SIOGIFINDEX, &ifr) < 0) |
155 | if (opts < 0) { | 98 | { |
156 | perror("fcntl(F_GETFL)"); | 99 | perror ("SIOGIFINDEX"); |
157 | } | 100 | } |
158 | opts = (opts | O_NONBLOCK); | ||
159 | if (fcntl(fd,F_SETFL,opts) < 0) { | ||
160 | perror("fcntl(F_SETFL)"); | ||
161 | } | ||
162 | return; | ||
163 | }/*}}}*/ | ||
164 | 101 | ||
165 | int main(int argc, char** argv) { | 102 | ifr6.ifr6_ifindex = ifr.ifr_ifindex; |
166 | unsigned char buf[MAX_SIZE]; | 103 | ifr6.ifr6_prefixlen = prefix_len; |
167 | 104 | ||
168 | char dev[IFNAMSIZ]; | 105 | if (ioctl (fd, SIOCSIFADDR, &ifr6) < 0) |
169 | memset(dev, 0, IFNAMSIZ); | 106 | { |
107 | perror ("SIOCSIFADDR"); | ||
108 | } | ||
170 | 109 | ||
171 | signal(SIGTERM, &term); | 110 | (void) ioctl (fd, SIOCGIFFLAGS, &ifr); |
111 | ifr.ifr_flags |= IFF_UP | IFF_RUNNING; | ||
112 | (void) ioctl (fd, SIOCSIFFLAGS, &ifr); | ||
113 | close (fd); | ||
114 | } /* }}} */ | ||
172 | 115 | ||
173 | int fd_tun = init_tun(dev); | 116 | static void |
117 | /** | ||
118 | * @brief Sets the IPv4-Address given in address on the interface dev | ||
119 | * | ||
120 | * @param dev the interface to configure | ||
121 | * @param address the IPv4-Address | ||
122 | * @param mask the netmask | ||
123 | */ | ||
124 | set_address4 (char *dev, char *address, char *mask) | ||
125 | { /* {{{ */ | ||
126 | int fd = 0; | ||
127 | struct sockaddr_in *addr; | ||
128 | struct ifreq ifr; | ||
129 | |||
130 | memset (&ifr, 0, sizeof (struct ifreq)); | ||
131 | addr = (struct sockaddr_in *) &(ifr.ifr_addr); | ||
132 | memset (addr, 0, sizeof (struct sockaddr_in)); | ||
133 | addr->sin_family = AF_INET; | ||
134 | addr->sin_addr.s_addr = inet_addr (address); | ||
135 | |||
136 | int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr); | ||
137 | if (r < 0) | ||
138 | { | ||
139 | fprintf (stderr, "error at inet_pton: %m\n"); | ||
140 | exit (1); | ||
141 | } | ||
142 | |||
143 | fd = socket (PF_INET, SOCK_DGRAM, 0); | ||
144 | if (fd < 0) | ||
145 | { | ||
146 | perror ("socket()"); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | strncpy (ifr.ifr_name, dev, IFNAMSIZ); | ||
151 | |||
152 | if (ioctl (fd, SIOCSIFADDR, &ifr) != 0) | ||
153 | { | ||
154 | perror ("SIOCSIFADDR"); | ||
155 | close (fd); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | addr = (struct sockaddr_in *) &(ifr.ifr_netmask); | ||
160 | r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr); | ||
161 | if (r < 0) | ||
162 | { | ||
163 | fprintf (stderr, "error at inet_pton: %m\n"); | ||
164 | exit (1); | ||
165 | } | ||
166 | |||
167 | if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0) | ||
168 | { | ||
169 | perror ("SIOCSIFNETMASK"); | ||
170 | close (fd); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | (void) ioctl (fd, SIOCGIFFLAGS, &ifr); | ||
175 | ifr.ifr_flags |= IFF_UP | IFF_RUNNING; | ||
176 | (void) ioctl (fd, SIOCSIFFLAGS, &ifr); | ||
177 | close (fd); | ||
178 | } /* }}} */ | ||
174 | 179 | ||
175 | if (fd_tun < 0) { | 180 | /** |
176 | fprintf(stderr, "Could not initialize tun-interface: %s\n", strerror(errno)); | 181 | * @brief sets the socket to nonblocking |
177 | exit(1); | 182 | * |
178 | } | 183 | * @param fd the socket |
184 | */ | ||
185 | static void | ||
186 | setnonblocking (int fd) | ||
187 | { /*{{{ */ | ||
188 | int opts; | ||
189 | |||
190 | opts = fcntl (fd, F_GETFL); | ||
191 | if (opts < 0) | ||
192 | { | ||
193 | perror ("fcntl(F_GETFL)"); | ||
194 | } | ||
195 | opts = (opts | O_NONBLOCK); | ||
196 | if (fcntl (fd, F_SETFL, opts) < 0) | ||
197 | { | ||
198 | perror ("fcntl(F_SETFL)"); | ||
199 | } | ||
200 | return; | ||
201 | } /*}}} */ | ||
202 | |||
203 | int | ||
204 | main (int argc, char **argv) | ||
205 | { | ||
206 | unsigned char buf[MAX_SIZE]; | ||
207 | |||
208 | char dev[IFNAMSIZ]; | ||
209 | memset (dev, 0, IFNAMSIZ); | ||
210 | |||
211 | signal (SIGTERM, &term); | ||
212 | |||
213 | int fd_tun = init_tun (dev); | ||
214 | |||
215 | if (fd_tun < 0) | ||
216 | { | ||
217 | fprintf (stderr, "Could not initialize tun-interface: %s\n", | ||
218 | strerror (errno)); | ||
219 | exit (1); | ||
220 | } | ||
221 | |||
222 | { | ||
223 | // TODO: get this out of argv | ||
224 | char address[] = "1234::1"; | ||
225 | unsigned long prefix_len = 16; | ||
226 | |||
227 | set_address6 (dev, address, prefix_len); | ||
228 | } | ||
229 | |||
230 | { | ||
231 | char address[] = "10.10.10.1"; | ||
232 | char mask[] = "255.255.255.252"; | ||
233 | |||
234 | set_address4 (dev, address, mask); | ||
235 | } | ||
236 | |||
237 | uid_t uid = getuid (); | ||
238 | if (setresuid (uid, uid, uid) != 0) | ||
239 | fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); | ||
240 | |||
241 | setnonblocking (0); | ||
242 | setnonblocking (1); | ||
243 | setnonblocking (fd_tun); | ||
244 | |||
245 | fd_set fds_w; | ||
246 | fd_set fds_r; | ||
247 | |||
248 | int rea = 1; | ||
249 | int wri = 1; | ||
250 | |||
251 | int write_fd_possible = 0; | ||
252 | int write_stdout_possible = 0; | ||
253 | outer: | ||
254 | while ((rea == 1 || wri == 1) && running == 1) | ||
255 | { | ||
256 | FD_ZERO (&fds_w); | ||
257 | FD_ZERO (&fds_r); | ||
179 | 258 | ||
259 | if (rea) | ||
180 | { | 260 | { |
181 | // TODO: get this out of argv | 261 | FD_SET (fd_tun, &fds_r); |
182 | char address[] = "1234::1"; | 262 | if (!write_stdout_possible) |
183 | unsigned long prefix_len = 16; | 263 | FD_SET (1, &fds_w); |
184 | |||
185 | set_address6(dev, address, prefix_len); | ||
186 | } | 264 | } |
187 | 265 | ||
266 | if (wri) | ||
188 | { | 267 | { |
189 | char address[] = "10.10.10.1"; | 268 | FD_SET (0, &fds_r); |
190 | char mask[] = "255.255.255.252"; | 269 | if (!write_fd_possible) |
191 | 270 | FD_SET (fd_tun, &fds_w); | |
192 | set_address4(dev, address, mask); | ||
193 | } | 271 | } |
194 | 272 | ||
195 | uid_t uid = getuid (); | 273 | int r = select (fd_tun + 1, &fds_r, &fds_w, (fd_set *) 0, 0); |
196 | if (setresuid (uid, uid, uid) != 0 ) | ||
197 | fprintf (stderr, "Failed to setresuid: %s\n", strerror(errno)); | ||
198 | |||
199 | setnonblocking(0); | ||
200 | setnonblocking(1); | ||
201 | setnonblocking(fd_tun); | ||
202 | 274 | ||
203 | fd_set fds_w; | 275 | if (r > 0) |
204 | fd_set fds_r; | 276 | { |
205 | 277 | if (FD_ISSET (fd_tun, &fds_w)) | |
206 | int rea = 1; | 278 | write_fd_possible = 1; |
207 | int wri = 1; | 279 | if (FD_ISSET (1, &fds_w)) |
208 | 280 | write_stdout_possible = 1; | |
209 | int write_fd_possible = 0; | 281 | |
210 | int write_stdout_possible = 0; | 282 | if (FD_ISSET (0, &fds_r) && write_fd_possible) |
211 | outer: | 283 | { |
212 | while((rea == 1 || wri == 1) && running == 1) { | 284 | write_fd_possible = 0; |
213 | FD_ZERO(&fds_w); | 285 | struct suid_packet *pkt = (struct suid_packet *) buf; |
214 | FD_ZERO(&fds_r); | 286 | r = read (0, buf, sizeof (struct GNUNET_MessageHeader)); |
215 | 287 | if (r <= 0) | |
216 | if (rea) { | 288 | { |
217 | FD_SET(fd_tun, &fds_r); | 289 | fprintf (stderr, "read-error: %s\n", strerror (errno)); |
218 | if (!write_stdout_possible) | 290 | shutdown (fd_tun, SHUT_WR); |
219 | FD_SET(1, &fds_w); | 291 | shutdown (0, SHUT_RD); |
292 | wri = 0; | ||
293 | goto outer; | ||
220 | } | 294 | } |
221 | 295 | if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER)) | |
222 | if (wri) { | 296 | abort (); |
223 | FD_SET(0, &fds_r); | 297 | while (r < ntohs (pkt->hdr.size)) |
224 | if (!write_fd_possible) | 298 | { |
225 | FD_SET(fd_tun, &fds_w); | 299 | int t = read (0, buf + r, ntohs (pkt->hdr.size) - r); |
300 | if (r < 0) | ||
301 | { | ||
302 | fprintf (stderr, "read-error: %s\n", strerror (errno)); | ||
303 | shutdown (fd_tun, SHUT_WR); | ||
304 | shutdown (0, SHUT_RD); | ||
305 | wri = 0; | ||
306 | goto outer; | ||
307 | } | ||
308 | r += t; | ||
226 | } | 309 | } |
227 | 310 | r = 0; | |
228 | int r = select(fd_tun+1, &fds_r, &fds_w, (fd_set*)0, 0); | 311 | while (r < |
229 | 312 | ntohs (pkt->hdr.size) - | |
230 | if(r > 0) { | 313 | sizeof (struct GNUNET_MessageHeader)) |
231 | if (FD_ISSET(fd_tun, &fds_w)) write_fd_possible = 1; | 314 | { |
232 | if (FD_ISSET(1, &fds_w)) write_stdout_possible = 1; | 315 | int t = write (fd_tun, pkt->data, |
233 | 316 | ntohs (pkt->hdr.size) - | |
234 | if (FD_ISSET(0, &fds_r) && write_fd_possible) { | 317 | sizeof (struct GNUNET_MessageHeader) - r); |
235 | write_fd_possible = 0; | 318 | if (t < 0) |
236 | struct suid_packet *pkt = (struct suid_packet*) buf; | 319 | { |
237 | r = read(0, buf, sizeof(struct GNUNET_MessageHeader)); | 320 | fprintf (stderr, "write-error 3: %s\n", |
238 | if (r <= 0) { | 321 | strerror (errno)); |
239 | fprintf(stderr, "read-error: %s\n", strerror (errno)); | 322 | shutdown (fd_tun, SHUT_WR); |
240 | shutdown(fd_tun, SHUT_WR); | 323 | shutdown (0, SHUT_RD); |
241 | shutdown(0, SHUT_RD); | 324 | wri = 0; |
242 | wri=0; | 325 | goto outer; |
243 | goto outer; | 326 | } |
244 | } | 327 | r += t; |
245 | if(pkt->hdr.type != ntohs(GNUNET_MESSAGE_TYPE_VPN_HELPER)) abort(); | 328 | } |
246 | while (r < ntohs(pkt->hdr.size)) { | 329 | } |
247 | int t = read(0, buf + r, ntohs(pkt->hdr.size) - r); | 330 | else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r)) |
248 | if (r < 0) { | 331 | { |
249 | fprintf(stderr, "read-error: %s\n", strerror (errno)); | 332 | write_stdout_possible = 0; |
250 | shutdown(fd_tun, SHUT_WR); | 333 | r = read (fd_tun, buf, MAX_SIZE); |
251 | shutdown(0, SHUT_RD); | 334 | if (r <= 0) |
252 | wri=0; | 335 | { |
253 | goto outer; | 336 | fprintf (stderr, "read-error: %s\n", strerror (errno)); |
254 | } | 337 | shutdown (fd_tun, SHUT_RD); |
255 | r += t; | 338 | shutdown (1, SHUT_WR); |
256 | } | 339 | rea = 0; |
257 | r = 0; | 340 | goto outer; |
258 | while (r < ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader)) { | 341 | } |
259 | int t = write(fd_tun, pkt->data, ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader) - r); | 342 | struct GNUNET_MessageHeader hdr = {.size = |
260 | if (t < 0) { | 343 | htons (r + sizeof (struct GNUNET_MessageHeader)),.type = |
261 | fprintf(stderr, "write-error 3: %s\n", strerror (errno)); | 344 | htons (GNUNET_MESSAGE_TYPE_VPN_HELPER) |
262 | shutdown(fd_tun, SHUT_WR); | 345 | }; |
263 | shutdown(0, SHUT_RD); | 346 | r = 0; |
264 | wri = 0; | 347 | while (r < sizeof (struct GNUNET_MessageHeader)) |
265 | goto outer; | 348 | { |
266 | } | 349 | int t = |
267 | r += t; | 350 | write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - r); |
268 | } | 351 | if (t < 0) |
269 | } else if (write_stdout_possible && FD_ISSET(fd_tun, &fds_r)) { | 352 | { |
270 | write_stdout_possible = 0; | 353 | fprintf (stderr, "write-error 2: %s\n", |
271 | r = read(fd_tun, buf, MAX_SIZE); | 354 | strerror (errno)); |
272 | if (r <= 0) { | 355 | shutdown (fd_tun, SHUT_RD); |
273 | fprintf(stderr, "read-error: %s\n", strerror (errno)); | 356 | shutdown (1, SHUT_WR); |
274 | shutdown(fd_tun, SHUT_RD); | 357 | rea = 0; |
275 | shutdown(1, SHUT_WR); | 358 | goto outer; |
276 | rea = 0; | 359 | } |
277 | goto outer; | 360 | r += t; |
278 | } | 361 | } |
279 | struct GNUNET_MessageHeader hdr = { .size = htons(r + sizeof(struct GNUNET_MessageHeader)), .type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER) }; | 362 | while (r < ntohs (hdr.size)) |
280 | r = 0; | 363 | { |
281 | while(r < sizeof(struct GNUNET_MessageHeader)) { | 364 | int t = write (1, buf, ntohs (hdr.size) - r); |
282 | int t = write(1, &hdr, sizeof(struct GNUNET_MessageHeader) - r); | 365 | if (t < 0) |
283 | if (t < 0) { | 366 | { |
284 | fprintf(stderr, "write-error 2: %s\n", strerror (errno)); | 367 | fprintf (stderr, "write-error 1: %s, written %d/%d\n", |
285 | shutdown(fd_tun, SHUT_RD); | 368 | strerror (errno), r, ntohs (hdr.size)); |
286 | shutdown(1, SHUT_WR); | 369 | shutdown (fd_tun, SHUT_RD); |
287 | rea = 0; | 370 | shutdown (1, SHUT_WR); |
288 | goto outer; | 371 | rea = 0; |
289 | } | 372 | goto outer; |
290 | r += t; | 373 | } |
291 | } | 374 | r += t; |
292 | while(r < ntohs(hdr.size)) { | ||
293 | int t = write(1, buf, ntohs(hdr.size) - r); | ||
294 | if (t < 0) { | ||
295 | fprintf(stderr, "write-error 1: %s, written %d/%d\n", strerror(errno), r, ntohs(hdr.size)); | ||
296 | shutdown(fd_tun, SHUT_RD); | ||
297 | shutdown(1, SHUT_WR); | ||
298 | rea = 0; | ||
299 | goto outer; | ||
300 | } | ||
301 | r += t; | ||
302 | } | ||
303 | } | ||
304 | } | 375 | } |
376 | } | ||
305 | } | 377 | } |
378 | } | ||
306 | 379 | ||
307 | close(fd_tun); | 380 | close (fd_tun); |
308 | 381 | ||
309 | return 0; | 382 | return 0; |
310 | } | 383 | } |