minidlna support now Samsung TV C550/C650 (thx amir909)
[tomato.git] / release / src / router / pptp-client / pptp_gre.c
blobfda62cc590ecdcfca3caaf2ab01914647959c2a9
1 /* pptp_gre.c -- encapsulate PPP in PPTP-GRE.
2 * Handle the IP Protocol 47 portion of PPTP.
3 * C. Scott Ananian <cananian@alumni.princeton.edu>
5 * $Id: pptp_gre.c,v 1.39 2005/07/11 03:23:48 quozl Exp $
6 */
8 #include <sys/types.h>
9 #include <netinet/in.h>
10 #include <arpa/inet.h>
11 #include <sys/socket.h>
12 #include <sys/stat.h>
13 #include <sys/time.h>
14 #include <sys/uio.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include "ppp_fcs.h"
20 #include "pptp_msg.h"
21 #include "pptp_gre.h"
22 #include "util.h"
23 #include "pqueue.h"
25 #define PACKET_MAX 8196
26 /* test for a 32 bit counter overflow */
27 #define WRAPPED( curseq, lastseq) \
28 ((((curseq) & 0xffffff00) == 0) && \
29 (((lastseq) & 0xffffff00 ) == 0xffffff00))
31 static u_int32_t ack_sent, ack_recv;
32 static u_int32_t seq_sent, seq_recv;
33 static u_int16_t pptp_gre_call_id, pptp_gre_peer_call_id;
34 gre_stats_t stats;
36 typedef int (*callback_t)(int cl, void *pack, unsigned int len);
38 /* decaps_hdlc gets all the packets possible with ONE blocking read */
39 /* returns <0 if read() call fails */
40 int decaps_hdlc(int fd, callback_t callback, int cl);
41 int encaps_hdlc(int fd, void *pack, unsigned int len);
42 int decaps_gre (int fd, callback_t callback, int cl);
43 int encaps_gre (int fd, void *pack, unsigned int len);
44 int dequeue_gre(callback_t callback, int cl);
46 #if 1
47 #include <stdio.h>
48 void print_packet(int fd, void *pack, unsigned int len)
50 unsigned char *b = (unsigned char *)pack;
51 unsigned int i,j;
52 FILE *out = fdopen(fd, "w");
53 fprintf(out,"-- begin packet (%u) --\n", len);
54 for (i = 0; i < len; i += 16) {
55 for (j = 0; j < 8; j++)
56 if (i + 2 * j + 1 < len)
57 fprintf(out, "%02x%02x ",
58 (unsigned int) b[i + 2 * j],
59 (unsigned int) b[i + 2 * j + 1]);
60 else if (i + 2 * j < len)
61 fprintf(out, "%02x ", (unsigned int) b[i + 2 * j]);
62 fprintf(out, "\n");
64 fprintf(out, "-- end packet --\n");
65 fflush(out);
67 #endif
69 /*** time_now_usecs ***********************************************************/
70 uint64_t time_now_usecs()
72 struct timeval tv;
73 gettimeofday(&tv, NULL);
74 return (tv.tv_sec * 1000000) + tv.tv_usec;
77 /*** Open IP protocol socket **************************************************/
78 int pptp_gre_bind(struct in_addr inetaddr)
80 struct sockaddr_in src_addr, loc_addr;
81 extern struct in_addr localbind;
82 int s = socket(AF_INET, SOCK_RAW, PPTP_PROTO);
83 if (s < 0) { warn("socket: %s", strerror(errno)); return -1; }
84 if (localbind.s_addr != INADDR_NONE) {
85 bzero(&loc_addr, sizeof(loc_addr));
86 loc_addr.sin_family = AF_INET;
87 loc_addr.sin_addr = localbind;
88 if (bind(s, (struct sockaddr *) &loc_addr, sizeof(loc_addr)) != 0) {
89 warn("bind: %s", strerror(errno)); close(s); return -1;
92 src_addr.sin_family = AF_INET;
93 src_addr.sin_addr = inetaddr;
94 src_addr.sin_port = 0;
95 if (connect(s, (struct sockaddr *) &src_addr, sizeof(src_addr)) < 0) {
96 warn("connect: %s", strerror(errno)); close(s); return -1;
98 return s;
101 /*** pptp_gre_copy ************************************************************/
102 void pptp_gre_copy(u_int16_t call_id, u_int16_t peer_call_id,
103 int pty_fd, int gre_fd)
105 int max_fd;
106 pptp_gre_call_id = call_id;
107 pptp_gre_peer_call_id = peer_call_id;
108 /* Pseudo-terminal already open. */
109 ack_sent = ack_recv = seq_sent = seq_recv = 0;
110 /* weird select semantics */
111 max_fd = gre_fd;
112 if (pty_fd > max_fd) max_fd = pty_fd;
113 /* Dispatch loop */
114 for (;;) { /* until error happens on gre_fd or pty_fd */
115 struct timeval tv = {0, 0};
116 struct timeval *tvp;
117 fd_set rfds;
118 int retval;
119 pqueue_t *head;
120 int block_usecs = -1; /* wait forever */
121 /* watch terminal and socket for input */
122 FD_ZERO(&rfds);
123 FD_SET(gre_fd, &rfds);
124 FD_SET(pty_fd, &rfds);
126 * if there are multiple pending ACKs, then do a minimal timeout;
127 * else if there is a single pending ACK then timeout after 0,5 seconds;
128 * else block until data is available.
130 if (ack_sent != seq_recv) {
131 if (ack_sent + 1 == seq_recv) /* u_int wrap-around safe */
132 block_usecs = 500000;
133 else
134 /* don't use zero, this will force a resceduling */
135 /* when calling select(), giving pppd a chance to */
136 /* run. */
137 block_usecs = 1;
139 /* otherwise block_usecs == -1, which means wait forever */
141 * If there is a packet in the queue, then don't wait longer than
142 * the time remaining until it expires.
144 head = pqueue_head();
145 if (head != NULL) {
146 int expiry_time = pqueue_expiry_time(head);
147 if (block_usecs == -1 || expiry_time < block_usecs)
148 block_usecs = expiry_time;
150 if (block_usecs == -1) {
151 tvp = NULL;
152 } else {
153 tvp = &tv;
154 tv.tv_usec = block_usecs;
155 tv.tv_sec = tv.tv_usec / 1000000;
156 tv.tv_usec %= 1000000;
158 retval = select(max_fd + 1, &rfds, NULL, NULL, tvp);
159 if (FD_ISSET(pty_fd, &rfds)) {
160 if (decaps_hdlc(pty_fd, encaps_gre, gre_fd) < 0)
161 break;
162 } else if (retval == 0 && ack_sent != seq_recv) {
163 /* if outstanding ack */
164 /* send ack with no payload */
165 encaps_gre(gre_fd, NULL, 0);
167 if (FD_ISSET(gre_fd, &rfds)) {
168 if (decaps_gre (gre_fd, encaps_hdlc, pty_fd) < 0)
169 break;
171 if (dequeue_gre (encaps_hdlc, pty_fd) < 0)
172 break;
174 /* Close up when done. */
175 close(gre_fd);
176 close(pty_fd);
179 #define HDLC_FLAG 0x7E
180 #define HDLC_ESCAPE 0x7D
181 #define HDLC_TRANSPARENCY 0x20
183 /* ONE blocking read per call; dispatches all packets possible */
184 /* returns 0 on success, or <0 on read failure */
185 int decaps_hdlc(int fd, int (*cb)(int cl, void *pack, unsigned int len), int cl)
187 unsigned char buffer[PACKET_MAX];
188 unsigned int start = 0;
189 int end;
190 int status;
191 static unsigned int len = 0, escape = 0;
192 static unsigned char copy[PACKET_MAX];
193 static int checkedsync = 0;
194 /* start is start of packet. end is end of buffer data */
195 /* this is the only blocking read we will allow */
196 if ((end = read (fd, buffer, sizeof(buffer))) <= 0) {
197 int saved_errno = errno;
198 warn("short read (%d): %s", end, strerror(saved_errno));
199 switch (saved_errno) {
200 case EMSGSIZE: {
201 int optval, optlen = sizeof(optval);
202 warn("transmitted GRE packet triggered an ICMP destination unreachable, fragmentation needed, or exceeds the MTU of the network interface");
203 #define IP_MTU 14
204 if(getsockopt(fd, IPPROTO_IP, IP_MTU, &optval, &optlen) < 0)
205 warn("getsockopt: %s", strerror(errno));
206 warn("getsockopt: IP_MTU: %d\n", optval);
207 return 0;
209 case EIO:
210 warn("pppd may have shutdown, see pppd log");
211 break;
213 return -1;
215 /* warn if the sync options of ppp and pptp don't match */
216 if( !checkedsync) {
217 checkedsync = 1;
218 if( buffer[0] == HDLC_FLAG){
219 if( syncppp )
220 warn( "pptp --sync option is active, "
221 "yet the ppp mode is asynchronous!\n");
223 else if( !syncppp )
224 warn( "The ppp mode is synchronous, "
225 "yet no pptp --sync option is specified!\n");
227 if ( syncppp ){
228 /* this handling is pretty simple thanks to N_HDLC */
229 if ((status = cb (cl, buffer, end)) < 0)
230 return status; /* error-check */
231 return 0;
233 /* asynchronous mode */
234 while (start < end) {
235 /* Copy to 'copy' and un-escape as we go. */
236 while (buffer[start] != HDLC_FLAG) {
237 if ((escape == 0) && buffer[start] == HDLC_ESCAPE) {
238 escape = HDLC_TRANSPARENCY;
239 } else {
240 if (len < PACKET_MAX)
241 copy [len++] = buffer[start] ^ escape;
242 escape = 0;
244 start++;
245 if (start >= end)
246 return 0; /* No more data, but the frame is not complete yet. */
248 /* found flag. skip past it */
249 start++;
250 /* check for over-short packets and silently discard, as per RFC1662 */
251 if ((len < 4) || (escape != 0)) {
252 len = 0; escape = 0;
253 continue;
255 /* check, then remove the 16-bit FCS checksum field */
256 if (pppfcs16 (PPPINITFCS16, copy, len) != PPPGOODFCS16)
257 warn("Bad Frame Check Sequence during PPP to GRE decapsulation");
258 len -= sizeof(u_int16_t);
259 /* so now we have a packet of length 'len' in 'copy' */
260 if ((status = cb (cl, copy, len)) < 0)
261 return status; /* error-check */
262 /* Great! Let's do more! */
263 len = 0; escape = 0;
265 return 0;
266 /* No more data to process. */
269 /*** Make stripped packet into HDLC packet ************************************/
270 int encaps_hdlc(int fd, void *pack, unsigned int len)
272 unsigned char *source = (unsigned char *)pack;
273 unsigned char dest[2 * PACKET_MAX + 2]; /* largest expansion possible */
274 unsigned int pos = 0, i;
275 u_int16_t fcs;
276 /* in synchronous mode there is little to do */
277 if ( syncppp )
278 return write(fd, source, len);
279 /* asynchronous mode */
280 /* Compute the FCS */
281 fcs = pppfcs16(PPPINITFCS16, source, len) ^ 0xFFFF;
282 /* start character */
283 dest[pos++] = HDLC_FLAG;
284 /* escape the payload */
285 for (i = 0; i < len + 2; i++) {
286 /* wacked out assignment to add FCS to end of source buffer */
287 unsigned char c =
288 (i < len)?source[i]:(i == len)?(fcs & 0xFF):((fcs >> 8) & 0xFF);
289 if (pos >= sizeof(dest)) break; /* truncate on overflow */
290 if ( (c < 0x20) || (c == HDLC_FLAG) || (c == HDLC_ESCAPE) ) {
291 dest[pos++] = HDLC_ESCAPE;
292 if (pos < sizeof(dest))
293 dest[pos++] = c ^ 0x20;
294 } else
295 dest[pos++] = c;
297 /* tack on the end-flag */
298 if (pos < sizeof(dest))
299 dest[pos++] = HDLC_FLAG;
300 /* now write this packet */
301 return write(fd, dest, pos);
304 /*** decaps_gre ***************************************************************/
305 int decaps_gre (int fd, callback_t callback, int cl)
307 unsigned char buffer[PACKET_MAX + 64 /*ip header*/];
308 struct pptp_gre_header *header;
309 int status, ip_len = 0;
310 static int first = 1;
311 unsigned int headersize;
312 unsigned int payload_len;
313 u_int32_t seq;
315 if ((status = read (fd, buffer, sizeof(buffer))) <= 0) {
316 warn("short read (%d): %s", status, strerror(errno));
317 stats.rx_errors++;
318 return -1;
320 /* strip off IP header, if present */
321 if ((buffer[0] & 0xF0) == 0x40)
322 ip_len = (buffer[0] & 0xF) * 4;
323 header = (struct pptp_gre_header *)(buffer + ip_len);
324 /* verify packet (else discard) */
325 if ( /* version should be 1 */
326 ((ntoh8(header->ver) & 0x7F) != PPTP_GRE_VER) ||
327 /* PPTP-GRE protocol for PPTP */
328 (ntoh16(header->protocol) != PPTP_GRE_PROTO)||
329 /* flag C should be clear */
330 PPTP_GRE_IS_C(ntoh8(header->flags)) ||
331 /* flag R should be clear */
332 PPTP_GRE_IS_R(ntoh8(header->flags)) ||
333 /* flag K should be set */
334 (!PPTP_GRE_IS_K(ntoh8(header->flags))) ||
335 /* routing and recursion ctrl = 0 */
336 ((ntoh8(header->flags)&0xF) != 0)) {
337 /* if invalid, discard this packet */
338 warn("Discarding GRE: %X %X %X %X %X %X",
339 ntoh8(header->ver)&0x7F, ntoh16(header->protocol),
340 PPTP_GRE_IS_C(ntoh8(header->flags)),
341 PPTP_GRE_IS_R(ntoh8(header->flags)),
342 PPTP_GRE_IS_K(ntoh8(header->flags)),
343 ntoh8(header->flags) & 0xF);
344 stats.rx_invalid++;
345 return 0;
347 /* silently discard packets not for this call */
348 if (ntoh16(header->call_id) != pptp_gre_call_id) {
349 if (log_level >= 2)
350 log("Discarding for other call : %d %d",
351 ntoh16(header->call_id), pptp_gre_call_id);
352 if (pptp_gre_call_id == 0) {
353 pptp_gre_call_id = ntoh16(header->call_id);
354 } else {
355 return 0;
358 /* test if acknowledgement present */
359 if (PPTP_GRE_IS_A(ntoh8(header->ver))) {
360 u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags)))?
361 header->ack:header->seq; /* ack in different place if S = 0 */
362 ack = ntoh32( ack);
363 if (ack > ack_recv) ack_recv = ack;
364 /* also handle sequence number wrap-around */
365 if (WRAPPED(ack,ack_recv)) ack_recv = ack;
366 if (ack_recv == stats.pt.seq) {
367 int rtt = time_now_usecs() - stats.pt.time;
368 stats.rtt = (stats.rtt + rtt) / 2;
371 /* test if payload present */
372 if (!PPTP_GRE_IS_S(ntoh8(header->flags)))
373 return 0; /* ack, but no payload */
374 headersize = sizeof(*header);
375 payload_len = ntoh16(header->payload_len);
376 seq = ntoh32(header->seq);
377 /* no ack present? */
378 if (!PPTP_GRE_IS_A(ntoh8(header->ver))) headersize -= sizeof(header->ack);
379 /* check for incomplete packet (length smaller than expected) */
380 if (status - headersize < payload_len) {
381 warn("discarding truncated packet (expected %d, got %d bytes)",
382 payload_len, status - headersize);
383 stats.rx_truncated++;
384 return 0;
386 /* check for expected sequence number */
387 if ( first || (seq == seq_recv + 1)) { /* wrap-around safe */
388 if ( log_level >= 2 )
389 log("accepting packet %d", seq);
390 stats.rx_accepted++;
391 first = 0;
392 seq_recv = seq;
393 return callback(cl, buffer + ip_len + headersize, payload_len);
394 /* out of order, check if the number is too low and discard the packet.
395 * (handle sequence number wrap-around, and try to do it right) */
396 } else if ( seq < seq_recv + 1 || WRAPPED(seq_recv, seq) ) {
397 if ( log_level >= 1 )
398 log("discarding duplicate or old packet %d (expecting %d)",
399 seq, seq_recv + 1);
400 stats.rx_underwin++;
401 /* sequence number too high, is it reasonably close? */
402 } else if ( seq < seq_recv + MISSING_WINDOW ||
403 WRAPPED(seq, seq_recv + MISSING_WINDOW) ) {
404 stats.rx_buffered++;
405 if ( log_level >= 1 )
406 log("%s packet %d (expecting %d, lost or reordered)",
407 disable_buffer ? "accepting" : "buffering",
408 seq, seq_recv+1);
409 if ( disable_buffer ) {
410 seq_recv = seq;
411 stats.rx_lost += seq - seq_recv - 1;
412 return callback(cl, buffer + ip_len + headersize, payload_len);
413 } else {
414 pqueue_add(seq, buffer + ip_len + headersize, payload_len);
416 /* no, packet must be discarded */
417 } else {
418 if ( log_level >= 1 )
419 warn("discarding bogus packet %d (expecting %d)",
420 seq, seq_recv + 1);
421 stats.rx_overwin++;
423 return 0;
426 /*** dequeue_gre **************************************************************/
427 int dequeue_gre (callback_t callback, int cl)
429 pqueue_t *head;
430 int status;
431 /* process packets in the queue that either are expected or have
432 * timed out. */
433 head = pqueue_head();
434 while ( head != NULL &&
435 ( (head->seq == seq_recv + 1) || /* wrap-around safe */
436 (pqueue_expiry_time(head) <= 0)
439 /* if it is timed out... */
440 if (head->seq != seq_recv + 1 ) { /* wrap-around safe */
441 stats.rx_lost += head->seq - seq_recv - 1;
442 if (log_level >= 2)
443 log("timeout waiting for %d packets", head->seq - seq_recv - 1);
445 if (log_level >= 2)
446 log("accepting %d from queue", head->seq);
447 seq_recv = head->seq;
448 status = callback(cl, head->packet, head->packlen);
449 pqueue_del(head);
450 if (status < 0)
451 return status;
452 head = pqueue_head();
454 return 0;
457 /*** encaps_gre ***************************************************************/
458 int encaps_gre (int fd, void *pack, unsigned int len)
460 struct pptp_gre_header header;
461 struct iovec iov[2] = { { &header, 0 }, { pack, len } };
462 static u_int32_t seq = 1; /* first sequence number sent must be 1 */
463 unsigned int header_len;
464 int rc;
465 /* package this up in a GRE shell. */
466 header.flags = hton8 (PPTP_GRE_FLAG_K);
467 header.ver = hton8 (PPTP_GRE_VER);
468 header.protocol = hton16(PPTP_GRE_PROTO);
469 header.payload_len = hton16(len);
470 header.call_id = hton16(pptp_gre_peer_call_id);
471 /* special case ACK with no payload */
472 if (pack == NULL) {
473 if (ack_sent != seq_recv) {
474 header.ver |= hton8(PPTP_GRE_FLAG_A);
475 header.payload_len = hton16(0);
476 /* ack is in odd place because S == 0 */
477 header.seq = hton32(seq_recv);
478 ack_sent = seq_recv;
479 rc = write(fd, &header, sizeof(header) - sizeof(header.seq));
480 if (rc < 0) {
481 stats.tx_failed++;
482 } else if (rc < sizeof(header) - sizeof(header.seq)) {
483 stats.tx_short++;
484 } else {
485 stats.tx_acks++;
487 return rc;
488 } else return 0; /* we don't need to send ACK */
489 } /* explicit brace to avoid ambiguous `else' warning */
490 /* send packet with payload */
491 header.flags |= hton8(PPTP_GRE_FLAG_S);
492 header.seq = hton32(seq);
493 if (ack_sent != seq_recv) { /* send ack with this message */
494 header.ver |= hton8(PPTP_GRE_FLAG_A);
495 header.ack = hton32(seq_recv);
496 ack_sent = seq_recv;
497 header_len = sizeof(header);
498 } else { /* don't send ack */
499 header_len = sizeof(header) - sizeof(header.ack);
501 /* save final header length */
502 iov[0].iov_len = header_len;
503 /* record and increment sequence numbers */
504 seq_sent = seq; seq++;
505 /* write this baby out to the net */
506 rc = writev(fd, iov, 2);
507 if (rc < 0) {
508 stats.tx_failed++;
509 } else if (rc < header_len + len) {
510 stats.tx_short++;
511 } else {
512 stats.tx_sent++;
513 stats.pt.seq = seq_sent;
514 stats.pt.time = time_now_usecs();
516 return rc;