/* pptp_ctrl.c ... handle PPTP control connection.
* C. Scott Ananian <[email protected]>
*
* $Id: pptp_ctrl.c,v 1.40 2011/12/19 07:15:03 quozl Exp $
*/
#include <errno.h>
#if defined (__SVR4) && defined (__sun) /* Solaris */
#define _XPG4_2
#define __EXTENSIONS__
#endif /* Solaris */
#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 <time.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_DEAD
} 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 occurred 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(void);
/* 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, u_int8_t 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",

qq_37032926
- 粉丝: 1
最新资源
- 单片机的液位监测系统的设计方案(完美版).doc
- 多桥隧高铁移动通信网配套传输网设计方案.doc
- 浙江中医药大学软件工程复习整理.doc
- 以问题为导向的高中信息技术深度学习教学探究.docx
- 浅析GIS技术工程测量中数字化应用方法.docx
- 计算机应用基础第五版习题答案教材课后题.doc
- 金融监管信息化推动我国银行业稳健运行及发展.docx
- 简述5G移动网络新技术及核心网架构.docx
- 计算机信息系统安全及防范策略.docx
- 【精选ppt】大数据科技风通用模板PPT模板ppt课件.pptx
- AMD概述-VT概述-虚拟化.docx
- iPhone项目管理开发需求.doc
- 在水利工程管理中数据挖掘技术的应用探析.docx
- 水箱液位控制系统wincc与matlabopc通讯系统设计方案.doc
- 《C语言程序设计》期末考试模拟试卷及参考答案.doc
- 单片机课程八路抢答器研究设计.doc
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈


