1/* pptp_ctrl.c ... handle PPTP control connection. 2 * C. Scott Ananian <cananian@alumni.princeton.edu> 3 * 4 * $Id: pptp_ctrl.c,v 1.31 2005/03/31 07:42:39 quozl Exp $ 5 */ 6 7#include <errno.h> 8#include <sys/time.h> 9#include <sys/types.h> 10#include <sys/socket.h> 11#include <netinet/in.h> 12#include <unistd.h> 13#include <stdlib.h> 14#include <assert.h> 15#include <signal.h> 16#include <string.h> 17#include <ctype.h> 18#include <fcntl.h> 19#include "pptp_msg.h" 20#include "pptp_ctrl.h" 21#include "pptp_options.h" 22#include "vector.h" 23#include "util.h" 24#include "pptp_quirks.h" 25 26/* BECAUSE OF SIGNAL LIMITATIONS, EACH PROCESS CAN ONLY MANAGE ONE 27 * CONNECTION. SO THIS 'PPTP_CONN' STRUCTURE IS A BIT MISLEADING. 28 * WE'LL KEEP CONNECTION-SPECIFIC INFORMATION IN THERE ANYWAY (AS 29 * OPPOSED TO USING GLOBAL VARIABLES), BUT BEWARE THAT THE ENTIRE 30 * UNIX SIGNAL-HANDLING SEMANTICS WOULD HAVE TO CHANGE (OR THE 31 * TIME-OUT CODE DRASTICALLY REWRITTEN) BEFORE YOU COULD DO A 32 * PPTP_CONN_OPEN MORE THAN ONCE PER PROCESS AND GET AWAY WITH IT. 33 */ 34 35/* This structure contains connection-specific information that the 36 * signal handler needs to see. Thus, it needs to be in a global 37 * variable. If you end up using pthreads or something (why not 38 * just processes?), this would have to be placed in a thread-specific 39 * data area, using pthread_get|set_specific, etc., so I've 40 * conveniently encapsulated it for you. 41 * [linux threads will have to support thread-specific signals 42 * before this would work at all, which, as of this writing 43 * (linux-threads v0.6, linux kernel 2.1.72), it does not.] 44 */ 45 46/* Globals */ 47 48/* control the number of times echo packets will be logged */ 49static int nlogecho = 10; 50 51static struct thread_specific { 52 struct sigaction old_sigaction; /* evil signals */ 53 PPTP_CONN * conn; 54} global; 55 56#define INITIAL_BUFSIZE 512 /* initial i/o buffer size. */ 57 58struct PPTP_CONN { 59 int inet_sock; 60 /* Connection States */ 61 enum { 62 CONN_IDLE, CONN_WAIT_CTL_REPLY, CONN_WAIT_STOP_REPLY, CONN_ESTABLISHED 63 } conn_state; /* on startup: CONN_IDLE */ 64 /* Keep-alive states */ 65 enum { 66 KA_NONE, KA_OUTSTANDING 67 } ka_state; /* on startup: KA_NONE */ 68 /* Keep-alive ID; monotonically increasing (watch wrap-around!) */ 69 u_int32_t ka_id; /* on startup: 1 */ 70 /* Other properties. */ 71 u_int16_t version; 72 u_int16_t firmware_rev; 73 u_int8_t hostname[64], vendor[64]; 74 /* XXX these are only PNS properties, currently XXX */ 75 /* Call assignment information. */ 76 u_int16_t call_serial_number; 77 VECTOR *call; 78 void * closure; 79 pptp_conn_cb callback; 80 /******* IO buffers ******/ 81 char * read_buffer, *write_buffer; 82 size_t read_alloc, write_alloc; 83 size_t read_size, write_size; 84}; 85 86struct PPTP_CALL { 87 /* Call properties */ 88 enum { 89 PPTP_CALL_PAC, PPTP_CALL_PNS 90 } call_type; 91 union { 92 enum pptp_pac_state { 93 PAC_IDLE, PAC_WAIT_REPLY, PAC_ESTABLISHED, PAC_WAIT_CS_ANS 94 } pac; 95 enum pptp_pns_state { 96 PNS_IDLE, PNS_WAIT_REPLY, PNS_ESTABLISHED, PNS_WAIT_DISCONNECT 97 } pns; 98 } state; 99 u_int16_t call_id, peer_call_id; 100 u_int16_t sernum; 101 u_int32_t speed; 102 /* For user data: */ 103 pptp_call_cb callback; 104 void * closure; 105}; 106 107 108/* PPTP error codes: ----------------------------------------------*/ 109 110/* (General Error Codes) */ 111static const struct { 112 const char *name, *desc; 113} pptp_general_errors[] = { 114#define PPTP_GENERAL_ERROR_NONE 0 115 { "(None)", "No general error" }, 116#define PPTP_GENERAL_ERROR_NOT_CONNECTED 1 117 { "(Not-Connected)", "No control connection exists yet for this " 118 "PAC-PNS pair" }, 119#define PPTP_GENERAL_ERROR_BAD_FORMAT 2 120 { "(Bad-Format)", "Length is wrong or Magic Cookie value is incorrect" }, 121#define PPTP_GENERAL_ERROR_BAD_VALUE 3 122 { "(Bad-Value)", "One of the field values was out of range or " 123 "reserved field was non-zero" }, 124#define PPTP_GENERAL_ERROR_NO_RESOURCE 4 125 { "(No-Resource)", "Insufficient resources to handle this command now" }, 126#define PPTP_GENERAL_ERROR_BAD_CALLID 5 127 { "(Bad-Call ID)", "The Call ID is invalid in this context" }, 128#define PPTP_GENERAL_ERROR_PAC_ERROR 6 129 { "(PAC-Error)", "A generic vendor-specific error occured in the PAC" } 130}; 131 132#define MAX_GENERAL_ERROR ( sizeof(pptp_general_errors) / \ 133 sizeof(pptp_general_errors[0]) - 1) 134 135/* Outgoing Call Reply Result Codes */ 136static const char *pptp_out_call_reply_result[] = { 137/* 0 */ "Unknown Result Code", 138/* 1 */ "Connected", 139/* 2 */ "General Error", 140/* 3 */ "No Carrier Detected", 141/* 4 */ "Busy Signal", 142/* 5 */ "No Dial Tone", 143/* 6 */ "Time Out", 144/* 7 */ "Not Accepted, Call is administratively prohibited" }; 145 146#define MAX_OUT_CALL_REPLY_RESULT 7 147 148/* Call Disconnect Notify Result Codes */ 149static const char *pptp_call_disc_ntfy[] = { 150/* 0 */ "Unknown Result Code", 151/* 1 */ "Lost Carrier", 152/* 2 */ "General Error", 153/* 3 */ "Administrative Shutdown", 154/* 4 */ "(your) Request" }; 155 156#define MAX_CALL_DISC_NTFY 4 157 158/* Call Disconnect Notify Result Codes */ 159static const char *pptp_start_ctrl_conn_rply[] = { 160/* 0 */ "Unknown Result Code", 161/* 1 */ "Successful Channel Establishment", 162/* 2 */ "General Error", 163/* 3 */ "Command Channel Already Exists", 164/* 4 */ "Requester is not Authorized" }; 165 166#define MAX_START_CTRL_CONN_REPLY 4 167 168/* timing options */ 169int idle_wait = PPTP_TIMEOUT; 170int max_echo_wait = PPTP_TIMEOUT; 171 172/* Local prototypes */ 173static void pptp_reset_timer(void); 174static void pptp_handle_timer(); 175/* Write/read as much as we can without blocking. */ 176int pptp_write_some(PPTP_CONN * conn); 177int pptp_read_some(PPTP_CONN * conn); 178/* Make valid packets from read_buffer */ 179int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size); 180/* Add packet to write_buffer */ 181int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size); 182/* Dispatch packets (general) */ 183int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size); 184/* Dispatch packets (control messages) */ 185int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size); 186/* Set link info, for pptp servers that need it. 187 this is a noop, unless the user specified a quirk and 188 there's a set_link hook defined in the quirks table 189 for that quirk */ 190void pptp_set_link(PPTP_CONN * conn, int peer_call_id); 191 192/*** log error information in control packets *********************************/ 193static void ctrlp_error( int result, int error, int cause, 194 const char *result_text[], int max_result) 195{ 196 if( cause >= 0) 197 log("Result code is %d '%s'. Error code is %d, Cause code is %d", 198 result, result_text[result <= max_result ? result : 0], error, 199 cause ); 200 else 201 log("Reply result code is %d '%s'. Error code is %d", 202 result, result_text[result <= max_result ? result : 0], error); 203 if ((error > 0) && (error <= MAX_GENERAL_ERROR)){ 204 if( result != PPTP_RESULT_GENERAL_ERROR ) 205 log("Result code is something else then \"general error\", " 206 "so the following error is probably bogus."); 207 log("Error is '%s', Error message: '%s'", 208 pptp_general_errors[error].name, 209 pptp_general_errors[error].desc); 210 } 211} 212 213#ifdef nostrip //Modified by Silver to shrink code //Winster Chan added 05/16/2006 214static const char *ctrl_msg_types[] = { 215 "invalid control message type", 216/* (Control Connection Management) */ 217 "Start-Control-Connection-Request", /* 1 */ 218 "Start-Control-Connection-Reply", /* 2 */ 219 "Stop-Control-Connection-Request", /* 3 */ 220 "Stop-Control-Connection-Reply", /* 4 */ 221 "Echo-Request", /* 5 */ 222 "Echo-Reply", /* 6 */ 223/* (Call Management) */ 224 "Outgoing-Call-Request", /* 7 */ 225 "Outgoing-Call-Reply", /* 8 */ 226 "Incoming-Call-Request", /* 9 */ 227 "Incoming-Call-Reply", /* 10 */ 228 "Incoming-Call-Connected", /* 11 */ 229 "Call-Clear-Request", /* 12 */ 230 "Call-Disconnect-Notify", /* 13 */ 231/* (Error Reporting) */ 232 "WAN-Error-Notify", /* 14 */ 233/* (PPP Session Control) */ 234 "Set-Link-Info" /* 15 */ 235}; 236#define MAX_CTRLMSG_TYPE 15 237#endif //Winster Chan added 05/16/2006 238 239/*** report a sent packet ****************************************************/ 240static void ctrlp_rep( void * buffer, int size, int isbuff) 241{ 242 struct pptp_header *packet = buffer; 243 unsigned int type; 244 if(size < sizeof(struct pptp_header)) return; 245 type = ntoh16(packet->ctrl_type); 246 /* FIXME: do not report sending echo requests as long as they are 247 * sent in a signal handler. This may dead lock as the syslog call 248 * is not reentrant */ 249 if( type == PPTP_ECHO_RQST ) return; 250 /* don't keep reporting sending of echo's */ 251 if( (type == PPTP_ECHO_RQST || type == PPTP_ECHO_RPLY) && nlogecho <= 0 ) return; 252 log("%s control packet type is %d '%s'\n",isbuff ? "Buffered" : "Sent", 253 type, ctrl_msg_types[type <= MAX_CTRLMSG_TYPE ? type : 0]); 254 255} 256 257 258 259/* Open new pptp_connection. Returns NULL on failure. */ 260PPTP_CONN * pptp_conn_open(int inet_sock, int isclient, pptp_conn_cb callback) 261{ 262 PPTP_CONN *conn; 263 /* Allocate structure */ 264 if ((conn = malloc(sizeof(*conn))) == NULL) return NULL; 265 if ((conn->call = vector_create()) == NULL) { free(conn); return NULL; } 266 /* Initialize */ 267 conn->inet_sock = inet_sock; 268 conn->conn_state = CONN_IDLE; 269 conn->ka_state = KA_NONE; 270 conn->ka_id = 1; 271 conn->call_serial_number = 0; 272 conn->callback = callback; 273 /* Create I/O buffers */ 274 conn->read_size = conn->write_size = 0; 275 conn->read_alloc = conn->write_alloc = INITIAL_BUFSIZE; 276 conn->read_buffer = 277 malloc(sizeof(*(conn->read_buffer)) * conn->read_alloc); 278 conn->write_buffer = 279 malloc(sizeof(*(conn->write_buffer)) * conn->write_alloc); 280 if (conn->read_buffer == NULL || conn->write_buffer == NULL) { 281 if (conn->read_buffer != NULL) free(conn->read_buffer); 282 if (conn->write_buffer != NULL) free(conn->write_buffer); 283 vector_destroy(conn->call); free(conn); return NULL; 284 } 285 /* Make this socket non-blocking. */ 286 fcntl(conn->inet_sock, F_SETFL, O_NONBLOCK); 287 /* Request connection from server, if this is a client */ 288 if (isclient) { 289 struct pptp_start_ctrl_conn packet = { 290 PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RQST), 291 hton16(PPTP_VERSION), 0, 0, 292 hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP), 293 hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION), 294 PPTP_HOSTNAME, PPTP_VENDOR 295 }; 296 /* fix this packet, if necessary */ 297 int idx, rc; 298 idx = get_quirk_index(); 299 if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) { 300 if ((rc = pptp_fixups[idx].start_ctrl_conn(&packet))) 301 warn("calling the start_ctrl_conn hook failed (%d)", rc); 302 } 303 if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) 304 conn->conn_state = CONN_WAIT_CTL_REPLY; 305 else 306 return NULL; /* could not send initial start request. */ 307 } 308 /* Set up interval/keep-alive timer */ 309 /* First, register handler for SIGALRM */ 310 sigpipe_create(); 311 sigpipe_assign(SIGALRM); 312 global.conn = conn; 313 /* Reset event timer */ 314 pptp_reset_timer(); 315 /* all done. */ 316 return conn; 317} 318 319int pptp_conn_established(PPTP_CONN *conn) { 320 return (conn->conn_state == CONN_ESTABLISHED); 321} 322 323/* This currently *only* works for client call requests. 324 * We need to do something else to allocate calls for incoming requests. 325 */ 326PPTP_CALL * pptp_call_open(PPTP_CONN * conn, pptp_call_cb callback, 327 char *phonenr) 328{ 329 PPTP_CALL * call; 330 int i; 331 int idx, rc; 332 /* Send off the call request */ 333 struct pptp_out_call_rqst packet = { 334 PPTP_HEADER_CTRL(PPTP_OUT_CALL_RQST), 335 0,0, /*call_id, sernum */ 336 hton32(PPTP_BPS_MIN), hton32(PPTP_BPS_MAX), 337 hton32(PPTP_BEARER_CAP), hton32(PPTP_FRAME_CAP), 338 hton16(PPTP_WINDOW), 0, 0, 0, {0}, {0} 339 }; 340 assert(conn && conn->call); 341 assert(conn->conn_state == CONN_ESTABLISHED); 342 /* Assign call id */ 343 if (!vector_scan(conn->call, 0, PPTP_MAX_CHANNELS - 1, &i)) 344 /* no more calls available! */ 345 return NULL; 346 /* allocate structure. */ 347 if ((call = malloc(sizeof(*call))) == NULL) return NULL; 348 /* Initialize call structure */ 349 call->call_type = PPTP_CALL_PNS; 350 call->state.pns = PNS_IDLE; 351 call->call_id = (u_int16_t) i; 352 call->sernum = conn->call_serial_number++; 353 call->callback = callback; 354 call->closure = NULL; 355 packet.call_id = htons(call->call_id); 356 packet.call_sernum = htons(call->sernum); 357 /* if we have a quirk, build a new packet to fit it */ 358 idx = get_quirk_index(); 359 if (idx != -1 && pptp_fixups[idx].out_call_rqst_hook) { 360 if ((rc = pptp_fixups[idx].out_call_rqst_hook(&packet))) 361 warn("calling the out_call_rqst hook failed (%d)", rc); 362 } 363 /* fill in the phone number if it was specified */ 364 if (phonenr) { 365 strncpy(packet.phone_num, phonenr, sizeof(packet.phone_num)); 366 packet.phone_len = strlen(phonenr); 367 if( packet.phone_len > sizeof(packet.phone_num)) 368 packet.phone_len = sizeof(packet.phone_num); 369 packet.phone_len = hton16 (packet.phone_len); 370 } 371 if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) { 372 pptp_reset_timer(); 373 call->state.pns = PNS_WAIT_REPLY; 374 /* and add it to the call vector */ 375 vector_insert(conn->call, i, call); 376 return call; 377 } else { /* oops, unsuccessful. Deallocate. */ 378 free(call); 379 return NULL; 380 } 381} 382 383/*** pptp_call_close **********************************************************/ 384void pptp_call_close(PPTP_CONN * conn, PPTP_CALL * call) 385{ 386 struct pptp_call_clear_rqst rqst = { 387 PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_RQST), 0, 0 388 }; 389 assert(conn && conn->call); assert(call); 390 assert(vector_contains(conn->call, call->call_id)); 391 /* haven't thought about PAC yet */ 392 assert(call->call_type == PPTP_CALL_PNS); 393 assert(call->state.pns != PNS_IDLE); 394 rqst.call_id = hton16(call->call_id); 395 /* don't check state against WAIT_DISCONNECT... allow multiple disconnect 396 * requests to be made. 397 */ 398 pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst)); 399 pptp_reset_timer(); 400 call->state.pns = PNS_WAIT_DISCONNECT; 401 /* call structure will be freed when we have confirmation of disconnect. */ 402} 403 404/*** hard close ***************************************************************/ 405void pptp_call_destroy(PPTP_CONN *conn, PPTP_CALL *call) 406{ 407 assert(conn && conn->call); assert(call); 408 assert(vector_contains(conn->call, call->call_id)); 409 /* notify */ 410 if (call->callback != NULL) call->callback(conn, call, CALL_CLOSE_DONE); 411 /* deallocate */ 412 vector_remove(conn->call, call->call_id); 413 free(call); 414} 415 416/*** this is a soft close *****************************************************/ 417void pptp_conn_close(PPTP_CONN * conn, u_int8_t close_reason) 418{ 419 struct pptp_stop_ctrl_conn rqst = { 420 PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RQST), 421 hton8(close_reason), 0, 0 422 }; 423 int i; 424 assert(conn && conn->call); 425 /* avoid repeated close attempts */ 426 if (conn->conn_state == CONN_IDLE || conn->conn_state == CONN_WAIT_STOP_REPLY) 427 return; 428 /* close open calls, if any */ 429 for (i = 0; i < vector_size(conn->call); i++) 430 pptp_call_close(conn, vector_get_Nth(conn->call, i)); 431 /* now close connection */ 432 log("Closing PPTP connection"); 433 pptp_send_ctrl_packet(conn, &rqst, sizeof(rqst)); 434 pptp_reset_timer(); /* wait 60 seconds for reply */ 435 conn->conn_state = CONN_WAIT_STOP_REPLY; 436 return; 437} 438 439/*** this is a hard close *****************************************************/ 440void pptp_conn_destroy(PPTP_CONN * conn) 441{ 442 int i; 443 assert(conn != NULL); assert(conn->call != NULL); 444 /* destroy all open calls */ 445 for (i = 0; i < vector_size(conn->call); i++) 446 pptp_call_destroy(conn, vector_get_Nth(conn->call, i)); 447 /* notify */ 448 if (conn->callback != NULL) conn->callback(conn, CONN_CLOSE_DONE); 449 sigpipe_close(); 450 close(conn->inet_sock); 451 /* deallocate */ 452 vector_destroy(conn->call); 453 free(conn); 454} 455 456/*** Deal with messages, in a non-blocking manner 457 * Add file descriptors used by pptp to fd_set. 458 */ 459void pptp_fd_set(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set, 460 int * max_fd) 461{ 462 assert(conn && conn->call); 463 /* Add fd to write_set if there are outstanding writes. */ 464 if (conn->write_size > 0) 465 FD_SET(conn->inet_sock, write_set); 466 /* Always add fd to read_set. (always want something to read) */ 467 FD_SET(conn->inet_sock, read_set); 468 if (*max_fd < conn->inet_sock) *max_fd = conn->inet_sock; 469 /* Add signal pipe file descriptor to set */ 470 int sig_fd = sigpipe_fd(); 471 FD_SET(sig_fd, read_set); 472 if (*max_fd < sig_fd) *max_fd = sig_fd; 473} 474 475/*** handle any pptp file descriptors set in fd_set, and clear them ***********/ 476int pptp_dispatch(PPTP_CONN * conn, fd_set * read_set, fd_set * write_set) 477{ 478 int r = 0; 479 assert(conn && conn->call); 480 /* Check for signals */ 481 if (FD_ISSET(sigpipe_fd(), read_set)) { 482 if (sigpipe_read() == SIGALRM) pptp_handle_timer(); 483 FD_CLR(sigpipe_fd(), read_set); 484 } 485 /* Check write_set could be set. */ 486 if (FD_ISSET(conn->inet_sock, write_set)) { 487 FD_CLR(conn->inet_sock, write_set); 488 if (conn->write_size > 0) 489 r = pptp_write_some(conn);/* write as much as we can without blocking */ 490 } 491 /* Check read_set */ 492 if (r >= 0 && FD_ISSET(conn->inet_sock, read_set)) { 493 void *buffer; size_t size; 494 FD_CLR(conn->inet_sock, read_set); 495 r = pptp_read_some(conn); /* read as much as we can without blocking */ 496 if (r < 0) 497 return r; 498 /* make packets of the buffer, while we can. */ 499 while (r >= 0 && pptp_make_packet(conn, &buffer, &size)) { 500 r = pptp_dispatch_packet(conn, buffer, size); 501 free(buffer); 502 } 503 } 504 /* That's all, folks. Simple, eh? */ 505 return r; 506} 507 508/*** Non-blocking write *******************************************************/ 509int pptp_write_some(PPTP_CONN * conn) { 510 ssize_t retval; 511 assert(conn && conn->call); 512 retval = write(conn->inet_sock, conn->write_buffer, conn->write_size); 513 if (retval < 0) { /* error. */ 514 if (errno == EAGAIN || errno == EINTR) { 515 return 0; 516 } else { /* a real error */ 517 log("write error: %s", strerror(errno)); 518 return -1; 519 } 520 } 521 assert(retval <= conn->write_size); 522 conn->write_size -= retval; 523 memmove(conn->write_buffer, conn->write_buffer + retval, conn->write_size); 524 ctrlp_rep(conn->write_buffer, retval, 0); 525 return 0; 526} 527 528/*** Non-blocking read ********************************************************/ 529int pptp_read_some(PPTP_CONN * conn) 530{ 531 ssize_t retval; 532 assert(conn && conn->call); 533 if (conn->read_size == conn->read_alloc) { /* need to alloc more memory */ 534 char *new_buffer = realloc(conn->read_buffer, 535 sizeof(*(conn->read_buffer)) * conn->read_alloc * 2); 536 if (new_buffer == NULL) { 537 log("Out of memory"); return -1; 538 } 539 conn->read_alloc *= 2; 540 conn->read_buffer = new_buffer; 541 } 542 retval = read(conn->inet_sock, conn->read_buffer + conn->read_size, 543 conn->read_alloc - conn->read_size); 544 if (retval == 0) { 545 log("read returned zero, peer has closed"); 546 return -1; 547 } 548 if (retval < 0) { 549 if (errno == EINTR || errno == EAGAIN) 550 return 0; 551 else { /* a real error */ 552 log("read error: %s", strerror(errno)); 553 return -1; 554 } 555 } 556 conn->read_size += retval; 557 assert(conn->read_size <= conn->read_alloc); 558 return 0; 559} 560 561/*** Packet formation *********************************************************/ 562int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size) 563{ 564 struct pptp_header *header; 565 size_t bad_bytes = 0; 566 assert(conn && conn->call); assert(buf != NULL); assert(size != NULL); 567 /* Give up unless there are at least sizeof(pptp_header) bytes */ 568 while ((conn->read_size-bad_bytes) >= sizeof(struct pptp_header)) { 569 /* Throw out bytes until we have a valid header. */ 570 header = (struct pptp_header *) (conn->read_buffer + bad_bytes); 571 if (ntoh32(header->magic) != PPTP_MAGIC) goto throwitout; 572 if (ntoh16(header->reserved0) != 0) 573 log("reserved0 field is not zero! (0x%x) Cisco feature? \n", 574 ntoh16(header->reserved0)); 575 if (ntoh16(header->length) < sizeof(struct pptp_header)) goto throwitout; 576 if (ntoh16(header->length) > PPTP_CTRL_SIZE_MAX) goto throwitout; 577 /* well. I guess it's good. Let's see if we've got it all. */ 578 if (ntoh16(header->length) > (conn->read_size-bad_bytes)) 579 /* nope. Let's wait until we've got it, then. */ 580 goto flushbadbytes; 581 /* One last check: */ 582 if ((ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL) && 583 (ntoh16(header->length) != 584 PPTP_CTRL_SIZE(ntoh16(header->ctrl_type)))) 585 goto throwitout; 586 /* well, I guess we've got it. */ 587 *size = ntoh16(header->length); 588 *buf = malloc(*size); 589 if (*buf == NULL) { log("Out of memory."); return 0; /* ack! */ } 590 memcpy(*buf, conn->read_buffer + bad_bytes, *size); 591 /* Delete this packet from the read_buffer. */ 592 conn->read_size -= (bad_bytes + *size); 593 memmove(conn->read_buffer, conn->read_buffer + bad_bytes + *size, 594 conn->read_size); 595 if (bad_bytes > 0) 596 log("%lu bad bytes thrown away.", (unsigned long) bad_bytes); 597 return 1; 598throwitout: 599 bad_bytes++; 600 } 601flushbadbytes: 602 /* no more packets. Let's get rid of those bad bytes */ 603 conn->read_size -= bad_bytes; 604 memmove(conn->read_buffer, conn->read_buffer + bad_bytes, conn->read_size); 605 if (bad_bytes > 0) 606 log("%lu bad bytes thrown away.", (unsigned long) bad_bytes); 607 return 0; 608} 609 610/*** pptp_send_ctrl_packet ****************************************************/ 611int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size) 612{ 613 assert(conn && conn->call); assert(buffer); 614 if( conn->write_size > 0) pptp_write_some( conn); 615 if( conn->write_size == 0) { 616 ssize_t retval; 617 retval = write(conn->inet_sock, buffer, size); 618 if (retval < 0) { /* error. */ 619 if (errno == EAGAIN || errno == EINTR) { 620 /* ignore */; 621 retval = 0; 622 } else { /* a real error */ 623 log("write error: %s", strerror(errno)); 624 pptp_conn_destroy(conn); /* shut down fast. */ 625 return 0; 626 } 627 } 628 ctrlp_rep( buffer, retval, 0); 629 size -= retval; 630 if( size <= 0) return 1; 631 } 632 /* Shove anything not written into the write buffer */ 633 if (conn->write_size + size > conn->write_alloc) { /* need more memory */ 634 char *new_buffer = realloc(conn->write_buffer, 635 sizeof(*(conn->write_buffer)) * conn->write_alloc * 2); 636 if (new_buffer == NULL) { 637 log("Out of memory"); return 0; 638 } 639 conn->write_alloc *= 2; 640 conn->write_buffer = new_buffer; 641 } 642 memcpy(conn->write_buffer + conn->write_size, buffer, size); 643 conn->write_size += size; 644 ctrlp_rep( buffer,size,1); 645 return 1; 646} 647 648/*** Packet Dispatch **********************************************************/ 649int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size) 650{ 651 int r = 0; 652 struct pptp_header *header = (struct pptp_header *)buffer; 653 assert(conn && conn->call); assert(buffer); 654 assert(ntoh32(header->magic) == PPTP_MAGIC); 655 assert(ntoh16(header->length) == size); 656 switch (ntoh16(header->pptp_type)) { 657 case PPTP_MESSAGE_CONTROL: 658 r = ctrlp_disp(conn, buffer, size); 659 break; 660 case PPTP_MESSAGE_MANAGE: 661 /* MANAGEMENT messages aren't even part of the spec right now. */ 662 log("PPTP management message received, but not understood."); 663 break; 664 default: 665 log("Unknown PPTP control message type received: %u", 666 (unsigned int) ntoh16(header->pptp_type)); 667 break; 668 } 669 return r; 670} 671 672/*** log echo request/replies *************************************************/ 673static void logecho( int type) 674{ 675 /* hack to stop flooding the log files (the most interesting part is right 676 * after the connection built-up) */ 677 if( nlogecho > 0) { 678 log( "Echo Re%s received.", type == PPTP_ECHO_RQST ? "quest" :"ply"); 679 if( --nlogecho == 0) 680 log("no more Echo Reply/Request packets will be reported."); 681 } 682} 683 684/*** pptp_dispatch_ctrl_packet ************************************************/ 685int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size) 686{ 687 struct pptp_header *header = (struct pptp_header *)buffer; 688 u_int8_t close_reason = PPTP_STOP_NONE; 689 assert(conn && conn->call); assert(buffer); 690 assert(ntoh32(header->magic) == PPTP_MAGIC); 691 assert(ntoh16(header->length) == size); 692 assert(ntoh16(header->pptp_type) == PPTP_MESSAGE_CONTROL); 693 if (size < PPTP_CTRL_SIZE(ntoh16(header->ctrl_type))) { 694 log("Invalid packet received [type: %d; length: %d].", 695 (int) ntoh16(header->ctrl_type), (int) size); 696 return 0; 697 } 698 switch (ntoh16(header->ctrl_type)) { 699 /* ----------- STANDARD Start-Session MESSAGES ------------ */ 700 case PPTP_START_CTRL_CONN_RQST: 701 { 702 struct pptp_start_ctrl_conn *packet = 703 (struct pptp_start_ctrl_conn *) buffer; 704 struct pptp_start_ctrl_conn reply = { 705 PPTP_HEADER_CTRL(PPTP_START_CTRL_CONN_RPLY), 706 hton16(PPTP_VERSION), 0, 0, 707 hton32(PPTP_FRAME_CAP), hton32(PPTP_BEARER_CAP), 708 hton16(PPTP_MAX_CHANNELS), hton16(PPTP_FIRMWARE_VERSION), 709 PPTP_HOSTNAME, PPTP_VENDOR }; 710 int idx, rc; 711 log("Received Start Control Connection Request"); 712 /* fix this packet, if necessary */ 713 idx = get_quirk_index(); 714 if (idx != -1 && pptp_fixups[idx].start_ctrl_conn) { 715 if ((rc = pptp_fixups[idx].start_ctrl_conn(&reply))) 716 warn("calling the start_ctrl_conn hook failed (%d)", rc); 717 } 718 if (conn->conn_state == CONN_IDLE) { 719 if (ntoh16(packet->version) < PPTP_VERSION) { 720 /* Can't support this (earlier) PPTP_VERSION */ 721 reply.version = packet->version; 722 /* protocol version not supported */ 723 reply.result_code = hton8(5); 724 pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); 725 pptp_reset_timer(); /* give sender a chance for a retry */ 726 } else { /* same or greater version */ 727 if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) { 728 conn->conn_state = CONN_ESTABLISHED; 729 log("server connection ESTABLISHED."); 730 pptp_reset_timer(); 731 } 732 } 733 } 734 break; 735 } 736 case PPTP_START_CTRL_CONN_RPLY: 737 { 738 struct pptp_start_ctrl_conn *packet = 739 (struct pptp_start_ctrl_conn *) buffer; 740 log("Received Start Control Connection Reply"); 741 if (conn->conn_state == CONN_WAIT_CTL_REPLY) { 742 /* XXX handle collision XXX [see rfc] */ 743 if (ntoh16(packet->version) != PPTP_VERSION) { 744 if (conn->callback != NULL) 745 conn->callback(conn, CONN_OPEN_FAIL); 746 close_reason = PPTP_STOP_PROTOCOL; 747 goto pptp_conn_close; 748 } 749 if (ntoh8(packet->result_code) != 1 && 750 /* J'ai change le if () afin que la connection ne se ferme 751 * pas pour un "rien" :p adel@cybercable.fr - 752 * 753 * Don't close the connection if the result code is zero 754 * (feature found in certain ADSL modems) 755 */ 756 ntoh8(packet->result_code) != 0) { 757 log("Negative reply received to our Start Control " 758 "Connection Request"); 759 ctrlp_error(packet->result_code, packet->error_code, 760 -1, pptp_start_ctrl_conn_rply, 761 MAX_START_CTRL_CONN_REPLY); 762 if (conn->callback != NULL) 763 conn->callback(conn, CONN_OPEN_FAIL); 764 close_reason = PPTP_STOP_PROTOCOL; 765 goto pptp_conn_close; 766 } 767 conn->conn_state = CONN_ESTABLISHED; 768 /* log session properties */ 769 conn->version = ntoh16(packet->version); 770 conn->firmware_rev = ntoh16(packet->firmware_rev); 771 memcpy(conn->hostname, packet->hostname, sizeof(conn->hostname)); 772 memcpy(conn->vendor, packet->vendor, sizeof(conn->vendor)); 773 pptp_reset_timer(); /* 60 seconds until keep-alive */ 774 log("Client connection established."); 775 if (conn->callback != NULL) 776 conn->callback(conn, CONN_OPEN_DONE); 777 } /* else goto pptp_conn_close; */ 778 break; 779 } 780 /* ----------- STANDARD Stop-Session MESSAGES ------------ */ 781 case PPTP_STOP_CTRL_CONN_RQST: 782 { 783 /* conn_state should be CONN_ESTABLISHED, but it could be 784 * something else */ 785 struct pptp_stop_ctrl_conn reply = { 786 PPTP_HEADER_CTRL(PPTP_STOP_CTRL_CONN_RPLY), 787 hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0 788 }; 789 log("Received Stop Control Connection Request."); 790 if (conn->conn_state == CONN_IDLE) break; 791 if (pptp_send_ctrl_packet(conn, &reply, sizeof(reply))) { 792 if (conn->callback != NULL) 793 conn->callback(conn, CONN_CLOSE_RQST); 794 conn->conn_state = CONN_IDLE; 795 return -1; 796 } 797 break; 798 } 799 case PPTP_STOP_CTRL_CONN_RPLY: 800 { 801 log("Received Stop Control Connection Reply."); 802 /* conn_state should be CONN_WAIT_STOP_REPLY, but it 803 * could be something else */ 804 if (conn->conn_state == CONN_IDLE) break; 805 conn->conn_state = CONN_IDLE; 806 return -1; 807 } 808 /* ----------- STANDARD Echo/Keepalive MESSAGES ------------ */ 809 case PPTP_ECHO_RPLY: 810 { 811 struct pptp_echo_rply *packet = 812 (struct pptp_echo_rply *) buffer; 813 logecho( PPTP_ECHO_RPLY); 814 if ((conn->ka_state == KA_OUTSTANDING) && 815 (ntoh32(packet->identifier) == conn->ka_id)) { 816 conn->ka_id++; 817 conn->ka_state = KA_NONE; 818 pptp_reset_timer(); 819 } 820 break; 821 } 822 case PPTP_ECHO_RQST: 823 { 824 struct pptp_echo_rqst *packet = 825 (struct pptp_echo_rqst *) buffer; 826 struct pptp_echo_rply reply = { 827 PPTP_HEADER_CTRL(PPTP_ECHO_RPLY), 828 packet->identifier, /* skip hton32(ntoh32(id)) */ 829 hton8(1), hton8(PPTP_GENERAL_ERROR_NONE), 0 830 }; 831 logecho( PPTP_ECHO_RQST); 832 pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); 833 pptp_reset_timer(); 834 break; 835 } 836 /* ----------- OUTGOING CALL MESSAGES ------------ */ 837 case PPTP_OUT_CALL_RQST: 838 { 839 struct pptp_out_call_rqst *packet = 840 (struct pptp_out_call_rqst *)buffer; 841 struct pptp_out_call_rply reply = { 842 PPTP_HEADER_CTRL(PPTP_OUT_CALL_RPLY), 843 0 /* callid */, packet->call_id, 1, PPTP_GENERAL_ERROR_NONE, 0, 844 hton32(PPTP_CONNECT_SPEED), 845 hton16(PPTP_WINDOW), hton16(PPTP_DELAY), 0 846 }; 847 log("Received Outgoing Call Request."); 848 /* XXX PAC: eventually this should make an outgoing call. XXX */ 849 reply.result_code = hton8(7); /* outgoing calls verboten */ 850 pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); 851 break; 852 } 853 case PPTP_OUT_CALL_RPLY: 854 { 855 struct pptp_out_call_rply *packet = 856 (struct pptp_out_call_rply *)buffer; 857 PPTP_CALL * call; 858 u_int16_t callid = ntoh16(packet->call_id_peer); 859 log("Received Outgoing Call Reply."); 860 if (!vector_search(conn->call, (int) callid, &call)) { 861 log("PPTP_OUT_CALL_RPLY received for non-existant call: " 862 "peer call ID (us) %d call ID (them) %d.", 863 callid, ntoh16(packet->call_id)); 864 break; 865 } 866 if (call->call_type != PPTP_CALL_PNS) { 867 log("Ack! How did this call_type get here?"); /* XXX? */ 868 break; 869 } 870 if (call->state.pns != PNS_WAIT_REPLY) { 871 warn("Unexpected(?) Outgoing Call Reply will be ignored."); 872 break; 873 } 874 /* check for errors */ 875 if (packet->result_code != 1) { 876 /* An error. Log it verbosely. */ 877 log("Our outgoing call request [callid %d] has not been " 878 "accepted.", (int) callid); 879 ctrlp_error(packet->result_code, packet->error_code, 880 packet->cause_code, pptp_out_call_reply_result, 881 MAX_OUT_CALL_REPLY_RESULT); 882 call->state.pns = PNS_IDLE; 883 if (call->callback != NULL) 884 call->callback(conn, call, CALL_OPEN_FAIL); 885 pptp_call_destroy(conn, call); 886 } else { 887 /* connection established */ 888 call->state.pns = PNS_ESTABLISHED; 889 call->peer_call_id = ntoh16(packet->call_id); 890 call->speed = ntoh32(packet->speed); 891 pptp_reset_timer(); 892 /* call pptp_set_link. unless the user specified a quirk 893 and this quirk has a set_link hook, this is a noop */ 894 pptp_set_link(conn, call->peer_call_id); 895 if (call->callback != NULL) 896 call->callback(conn, call, CALL_OPEN_DONE); 897 log("Outgoing call established (call ID %u, peer's " 898 "call ID %u).\n", call->call_id, call->peer_call_id); 899 } 900 break; 901 } 902 /* ----------- INCOMING CALL MESSAGES ------------ */ 903 /* XXX write me XXX */ 904 /* ----------- CALL CONTROL MESSAGES ------------ */ 905 case PPTP_CALL_CLEAR_RQST: 906 { 907 struct pptp_call_clear_rqst *packet = 908 (struct pptp_call_clear_rqst *)buffer; 909 struct pptp_call_clear_ntfy reply = { 910 PPTP_HEADER_CTRL(PPTP_CALL_CLEAR_NTFY), packet->call_id, 911 1, PPTP_GENERAL_ERROR_NONE, 0, 0, {0} 912 }; 913 log("Received Call Clear Request."); 914 if (vector_contains(conn->call, ntoh16(packet->call_id))) { 915 PPTP_CALL * call; 916 vector_search(conn->call, ntoh16(packet->call_id), &call); 917 if (call->callback != NULL) 918 call->callback(conn, call, CALL_CLOSE_RQST); 919 pptp_send_ctrl_packet(conn, &reply, sizeof(reply)); 920 pptp_call_destroy(conn, call); 921 log("Call closed (RQST) (call id %d)", (int) call->call_id); 922 } 923 break; 924 } 925 case PPTP_CALL_CLEAR_NTFY: 926 { 927 struct pptp_call_clear_ntfy *packet = 928 (struct pptp_call_clear_ntfy *)buffer; 929 log("Call disconnect notification received (call id %d)", 930 ntoh16(packet->call_id)); 931 if (vector_contains(conn->call, ntoh16(packet->call_id))) { 932 PPTP_CALL * call; 933 ctrlp_error(packet->result_code, packet->error_code, 934 packet->cause_code, pptp_call_disc_ntfy, 935 MAX_CALL_DISC_NTFY); 936 vector_search(conn->call, ntoh16(packet->call_id), &call); 937 pptp_call_destroy(conn, call); 938 } 939 /* XXX we could log call stats here XXX */ 940 /* XXX not all servers send this XXX */ 941 break; 942 } 943 case PPTP_SET_LINK_INFO: 944 { 945 /* I HAVE NO CLUE WHAT TO DO IF send_accm IS NOT 0! */ 946 /* this is really dealt with in the HDLC deencapsulation, anyway. */ 947 struct pptp_set_link_info *packet = 948 (struct pptp_set_link_info *)buffer; 949 /* log it. */ 950 log("PPTP_SET_LINK_INFO received from peer_callid %u", 951 (unsigned int) ntoh16(packet->call_id_peer)); 952 log(" send_accm is %08lX, recv_accm is %08lX", 953 (unsigned long) ntoh32(packet->send_accm), 954 (unsigned long) ntoh32(packet->recv_accm)); 955 if (!(ntoh32(packet->send_accm) == 0 && 956 ntoh32(packet->recv_accm) == 0)) 957 warn("Non-zero Async Control Character Maps are not supported!"); 958 break; 959 } 960 default: 961 log("Unrecognized Packet %d received.", 962 (int) ntoh16(((struct pptp_header *)buffer)->ctrl_type)); 963 /* goto pptp_conn_close; */ 964 break; 965 } 966 return 0; 967pptp_conn_close: 968 warn("pptp_conn_close(%d)", (int) close_reason); 969 pptp_conn_close(conn, close_reason); 970 return 0; 971} 972 973/*** pptp_set_link **************************************************************/ 974void pptp_set_link(PPTP_CONN* conn, int peer_call_id) 975{ 976 int idx, rc; 977 /* if we need to send a set_link packet because of buggy 978 hardware or pptp server, do it now */ 979 if ((idx = get_quirk_index()) != -1 && pptp_fixups[idx].set_link_hook) { 980 struct pptp_set_link_info packet; 981 if ((rc = pptp_fixups[idx].set_link_hook(&packet, peer_call_id))) 982 warn("calling the set_link hook failed (%d)", rc); 983 if (pptp_send_ctrl_packet(conn, &packet, sizeof(packet))) { 984 pptp_reset_timer(); 985 } 986 } 987} 988 989/*** Get info from call structure *********************************************/ 990/* NOTE: The peer_call_id is undefined until we get a server response. */ 991void pptp_call_get_ids(PPTP_CONN * conn, PPTP_CALL * call, 992 u_int16_t * call_id, u_int16_t * peer_call_id) 993{ 994 assert(conn != NULL); assert(call != NULL); 995 *call_id = call->call_id; 996 *peer_call_id = call->peer_call_id; 997} 998 999/*** pptp_call_closure_put ****************************************************/ 1000void pptp_call_closure_put(PPTP_CONN * conn, PPTP_CALL * call, void *cl) 1001{ 1002 assert(conn != NULL); assert(call != NULL); 1003 call->closure = cl; 1004} 1005 1006/*** pptp_call_closure_get ****************************************************/ 1007void * pptp_call_closure_get(PPTP_CONN * conn, PPTP_CALL * call) 1008{ 1009 assert(conn != NULL); assert(call != NULL); 1010 return call->closure; 1011} 1012 1013/*** pptp_conn_closure_put ****************************************************/ 1014void pptp_conn_closure_put(PPTP_CONN * conn, void *cl) 1015{ 1016 assert(conn != NULL); 1017 conn->closure = cl; 1018} 1019 1020/*** pptp_conn_closure_get ****************************************************/ 1021void * pptp_conn_closure_get(PPTP_CONN * conn) 1022{ 1023 assert(conn != NULL); 1024 return conn->closure; 1025} 1026 1027/*** Reset keep-alive timer ***************************************************/ 1028static void pptp_reset_timer(void) 1029{ 1030 const struct itimerval tv = { { 0, 0 }, /* stop on time-out */ 1031 { idle_wait, 0 } }; 1032 if (idle_wait) setitimer(ITIMER_REAL, &tv, NULL); 1033} 1034 1035 1036/*** Handle keep-alive timer **************************************************/ 1037static void pptp_handle_timer() 1038{ 1039 int i; 1040 /* "Keep Alives and Timers, 1": check connection state */ 1041 if (global.conn->conn_state != CONN_ESTABLISHED) { 1042 if (global.conn->conn_state == CONN_WAIT_STOP_REPLY) 1043 /* hard close. */ 1044 pptp_conn_destroy(global.conn); 1045 else /* soft close */ 1046 pptp_conn_close(global.conn, PPTP_STOP_NONE); 1047 } 1048 /* "Keep Alives and Timers, 2": check echo status */ 1049 if (global.conn->ka_state == KA_OUTSTANDING) { 1050 /* no response to keep-alive */ 1051 log ("closing control connection due to missing echo reply"); 1052 pptp_conn_close(global.conn, PPTP_STOP_NONE); 1053 } else { /* ka_state == NONE */ /* send keep-alive */ 1054 struct pptp_echo_rqst rqst = { 1055 PPTP_HEADER_CTRL(PPTP_ECHO_RQST), hton32(global.conn->ka_id) }; 1056 pptp_send_ctrl_packet(global.conn, &rqst, sizeof(rqst)); 1057 global.conn->ka_state = KA_OUTSTANDING; 1058 } 1059 /* check incoming/outgoing call states for !IDLE && !ESTABLISHED */ 1060 for (i = 0; i < vector_size(global.conn->call); i++) { 1061 PPTP_CALL * call = vector_get_Nth(global.conn->call, i); 1062 if (call->call_type == PPTP_CALL_PNS) { 1063 if (call->state.pns == PNS_WAIT_REPLY) { 1064 /* send close request */ 1065 pptp_call_close(global.conn, call); 1066 assert(call->state.pns == PNS_WAIT_DISCONNECT); 1067 } else if (call->state.pns == PNS_WAIT_DISCONNECT) { 1068 /* hard-close the call */ 1069 pptp_call_destroy(global.conn, call); 1070 } 1071 } else if (call->call_type == PPTP_CALL_PAC) { 1072 if (call->state.pac == PAC_WAIT_REPLY) { 1073 /* XXX FIXME -- drop the PAC connection XXX */ 1074 } else if (call->state.pac == PAC_WAIT_CS_ANS) { 1075 /* XXX FIXME -- drop the PAC connection XXX */ 1076 } 1077 } 1078 } 1079 pptp_reset_timer(); 1080} 1081