/* pptp_ctrl.c ... handle PPTP control connection.
* C. Scott Ananian <cananian@alumni.princeton.edu>
*
* $Id: pptp_ctrl.c,v 1.33 2007/11/21 03:36:47 quozl Exp $
*/
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <signal.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include "pptp_msg.h"
#include "pptp_ctrl.h"
#include "pptp_options.h"
#include "vector.h"
#include "util.h"
#include "pptp_quirks.h"
/* BECAUSE OF SIGNAL LIMITATIONS, EACH PROCESS CAN ONLY MANAGE ONE
* CONNECTION. SO THIS 'PPTP_CONN' STRUCTURE IS A BIT MISLEADING.
* WE'LL KEEP CONNECTION-SPECIFIC INFORMATION IN THERE ANYWAY (AS
* OPPOSED TO USING GLOBAL VARIABLES), BUT BEWARE THAT THE ENTIRE
* UNIX SIGNAL-HANDLING SEMANTICS WOULD HAVE TO CHANGE (OR THE
* TIME-OUT CODE DRASTICALLY REWRITTEN) BEFORE YOU COULD DO A
* PPTP_CONN_OPEN MORE THAN ONCE PER PROCESS AND GET AWAY WITH IT.
*/
/* This structure contains connection-specific information that the
* signal handler needs to see. Thus, it needs to be in a global
* variable. If you end up using pthreads or something (why not
* just processes?), this would have to be placed in a thread-specific
* data area, using pthread_get|set_specific, etc., so I've
* conveniently encapsulated it for you.
* [linux threads will have to support thread-specific signals
* before this would work at all, which, as of this writing
* (linux-threads v0.6, linux kernel 2.1.72), it does not.]
*/
/* Globals */
/* control the number of times echo packets will be logged */
static int nlogecho = 10;
static struct thread_specific {
struct sigaction old_sigaction; /* evil signals */
PPTP_CONN * conn;
} global;
#define INITIAL_BUFSIZE 512 /* initial i/o buffer size. */
struct PPTP_CONN {
int inet_sock;
/* Connection States */
enum {
CONN_IDLE, CONN_WAIT_CTL_REPLY, CONN_WAIT_STOP_REPLY, CONN_ESTABLISHED
} conn_state; /* on startup: CONN_IDLE */
/* Keep-alive states */
enum {
KA_NONE, KA_OUTSTANDING
} ka_state; /* on startup: KA_NONE */
/* Keep-alive ID; monotonically increasing (watch wrap-around!) */
u_int32_t ka_id; /* on startup: 1 */
/* Other properties. */
u_int16_t version;
u_int16_t firmware_rev;
u_int8_t hostname[64], vendor[64];
/* XXX these are only PNS properties, currently XXX */
/* Call assignment information. */
u_int16_t call_serial_number;
VECTOR *call;
void * closure;
pptp_conn_cb callback;
/******* IO buffers ******/
char * read_buffer, *write_buffer;
size_t read_alloc, write_alloc;
size_t read_size, write_size;
};
struct PPTP_CALL {
/* Call properties */
enum {
PPTP_CALL_PAC, PPTP_CALL_PNS
} call_type;
union {
enum pptp_pac_state {
PAC_IDLE, PAC_WAIT_REPLY, PAC_ESTABLISHED, PAC_WAIT_CS_ANS
} pac;
enum pptp_pns_state {
PNS_IDLE, PNS_WAIT_REPLY, PNS_ESTABLISHED, PNS_WAIT_DISCONNECT
} pns;
} state;
u_int16_t call_id, peer_call_id;
u_int16_t sernum;
u_int32_t speed;
/* For user data: */
pptp_call_cb callback;
void * closure;
};
/* PPTP error codes: ----------------------------------------------*/
/* (General Error Codes) */
static const struct {
const char *name, *desc;
} pptp_general_errors[] = {
#define PPTP_GENERAL_ERROR_NONE 0
{ "(None)", "No general error" },
#define PPTP_GENERAL_ERROR_NOT_CONNECTED 1
{ "(Not-Connected)", "No control connection exists yet for this "
"PAC-PNS pair" },
#define PPTP_GENERAL_ERROR_BAD_FORMAT 2
{ "(Bad-Format)", "Length is wrong or Magic Cookie value is incorrect" },
#define PPTP_GENERAL_ERROR_BAD_VALUE 3
{ "(Bad-Value)", "One of the field values was out of range or "
"reserved field was non-zero" },
#define PPTP_GENERAL_ERROR_NO_RESOURCE 4
{ "(No-Resource)", "Insufficient resources to handle this command now" },
#define PPTP_GENERAL_ERROR_BAD_CALLID 5
{ "(Bad-Call ID)", "The Call ID is invalid in this context" },
#define PPTP_GENERAL_ERROR_PAC_ERROR 6
{ "(PAC-Error)", "A generic vendor-specific error occured in the PAC" }
};
#define MAX_GENERAL_ERROR ( sizeof(pptp_general_errors) / \
sizeof(pptp_general_errors[0]) - 1)
/* Outgoing Call Reply Result Codes */
static const char *pptp_out_call_reply_result[] = {
/* 0 */ "Unknown Result Code",
/* 1 */ "Connected",
/* 2 */ "General Error",
/* 3 */ "No Carrier Detected",
/* 4 */ "Busy Signal",
/* 5 */ "No Dial Tone",
/* 6 */ "Time Out",
/* 7 */ "Not Accepted, Call is administratively prohibited" };
#define MAX_OUT_CALL_REPLY_RESULT 7
/* Call Disconnect Notify Result Codes */
static const char *pptp_call_disc_ntfy[] = {
/* 0 */ "Unknown Result Code",
/* 1 */ "Lost Carrier",
/* 2 */ "General Error",
/* 3 */ "Administrative Shutdown",
/* 4 */ "(your) Request" };
#define MAX_CALL_DISC_NTFY 4
/* Call Disconnect Notify Result Codes */
static const char *pptp_start_ctrl_conn_rply[] = {
/* 0 */ "Unknown Result Code",
/* 1 */ "Successful Channel Establishment",
/* 2 */ "General Error",
/* 3 */ "Command Channel Already Exists",
/* 4 */ "Requester is not Authorized" };
#define MAX_START_CTRL_CONN_REPLY 4
/* timing options */
int idle_wait = PPTP_TIMEOUT;
int max_echo_wait = PPTP_TIMEOUT;
/* Local prototypes */
static void pptp_reset_timer(void);
static void pptp_handle_timer();
/* Write/read as much as we can without blocking. */
int pptp_write_some(PPTP_CONN * conn);
int pptp_read_some(PPTP_CONN * conn);
/* Make valid packets from read_buffer */
int pptp_make_packet(PPTP_CONN * conn, void **buf, size_t *size);
/* Add packet to write_buffer */
int pptp_send_ctrl_packet(PPTP_CONN * conn, void * buffer, size_t size);
/* Dispatch packets (general) */
int pptp_dispatch_packet(PPTP_CONN * conn, void * buffer, size_t size);
/* Dispatch packets (control messages) */
int ctrlp_disp(PPTP_CONN * conn, void * buffer, size_t size);
/* Set link info, for pptp servers that need it.
this is a noop, unless the user specified a quirk and
there's a set_link hook defined in the quirks table
for that quirk */
void pptp_set_link(PPTP_CONN * conn, int peer_call_id);
/*** log error information in control packets *********************************/
static void ctrlp_error( int result, int error, int cause,
const char *result_text[], int max_result)
{
if( cause >= 0)
log("Result code is %d '%s'. Error code is %d, Cause code is %d",
result, result_text[result <= max_result ? result : 0], error,
cause );
else
log("Reply result code is %d '%s'. Error code is %d",
result, result_text[result <= max_result ? result : 0], error);
if ((error > 0) && (error <= MAX_GENERAL_ERROR)){
if( result != PPTP_RESULT_GENERAL_ERROR )
log("Result code is something else then \"general error\", "
"so the following error is probably bogus.");
log("Error is '%s', Error message: '%s'",
pptp_general_errors[error].name,
pptp_general_errors[error].desc);
}
}
static const char *ctrl_msg_types[] = {
"invalid control message type",
/* (Control Connection Management) */
"Start-Control-Connection-Request", /* 1 */
"Start-Control-Connection-Reply", /* 2 */
"Stop-Control-Connection-Request", /* 3 */
"Stop-Control-Connection-Reply", /* 4 */
"Echo-Request", /* 5 */
"Echo-Reply", /* 6 */
/* (Call Management) */
"Outgoing-Call-Request", /* 7 */
"Outgoing-Call-Reply",
PPTP源码(Linux and FreeBSD)
5星 · 超过95%的资源 需积分: 16 123 浏览量
2010-08-18
08:45:54
上传
评论
收藏 79KB GZ 举报
yangcock
- 粉丝: 13
- 资源: 59
最新资源
- TestBrightness2.zip
- 用DAC0832产生锯齿波电压_单片机C语言实例(纯C语言源代码).zip
- [其他类别]SimpleID 0.6.5_simpleid-codepub.rar
- [图片动画]Singapore v0.10.0_singapore-0.10.0.rar
- NiceChord 好和弦:Wiwi寫給想做音樂的你,厲害的人都在用!超過80個寫歌、編曲創作原理.pdf
- IMG_20240420_234000.jpg
- [其他类别]PHP Web admin System v1.0_webadmin_php.rar
- 实用密码锁_单片机C语言实例(纯C语言源代码).zip
- 女孩写字.zip
- 请问更好发挥和规范化风格化发货
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
- 1
- 2
- 3
前往页