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