summaryrefslogtreecommitdiff
path: root/pptpd-1.3.3/ctrlpacket.c
diff options
context:
space:
mode:
Diffstat (limited to 'pptpd-1.3.3/ctrlpacket.c')
-rw-r--r--pptpd-1.3.3/ctrlpacket.c719
1 files changed, 0 insertions, 719 deletions
diff --git a/pptpd-1.3.3/ctrlpacket.c b/pptpd-1.3.3/ctrlpacket.c
deleted file mode 100644
index b463941..0000000
--- a/pptpd-1.3.3/ctrlpacket.c
+++ /dev/null
@@ -1,719 +0,0 @@
-/*
- * ctrlpacket.c
- *
- * PPTP Control Message packet reading, formatting and writing.
- *
- * $Id: ctrlpacket.c,v 1.6 2005/08/03 09:10:59 quozl Exp $
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#if HAVE_SYSLOG_H
-#include <syslog.h>
-#else
-#include "our_syslog.h"
-#endif
-
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <time.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "pptpdefs.h"
-#include "pptpctrl.h"
-#include "ctrlpacket.h"
-
-#include <net/if.h>
-#include <net/ethernet.h>
-#include "if_pppox.h"
-
-#ifndef HAVE_STRERROR
-#include "compat.h"
-#endif
-
-/* Local function prototypes */
-static ssize_t read_pptp_header(int clientFd, unsigned char *packet, int *ctrl_message_type);
-static void deal_start_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
-static void deal_stop_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
-static void deal_out_call(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
-static void deal_echo(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
-static void deal_call_clr(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size);
-static void deal_set_link_info(unsigned char *packet);
-static u_int16_t getcall();
-static u_int16_t freecall();
-
-#if notyet
-static int make_out_call_rqst(unsigned char *rply_packet, ssize_t * rply_size);
-#endif
-
-/*
- * read_pptp_packet
- *
- * Sees if a packet can be read and if so what type of packet it is. The
- * method then calls the appropriate function to examine the details of the
- * packet and form a suitable reply packet.
- *
- * args: clientFd (IN) - Client socket to read from.
- * packet (OUT) - Packet read from the client.
- * rply_packet (OUT) - Reply packet for the client.
- * rply_size (OUT) - Size of the reply packet.
- *
- * retn: PPTP control message type of the packet on success.
- * -1 on retryable error.
- * 0 on error to abort on.
- */
-int read_pptp_packet(int clientFd, unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
-{
-
- size_t bytes_read;
- int pptp_ctrl_type = 0; /* Control Message Type */
-
- /* read a packet and parse header */
- if ((bytes_read = read_pptp_header(clientFd, packet, &pptp_ctrl_type)) <= 0) {
- /* error reading packet */
- syslog(LOG_ERR, "CTRL: couldn't read packet header (%s)", bytes_read ? "retry" : "exit");
- return bytes_read;
- }
-
- /* launch appropriate method to form suitable reply to the packet */
- switch (pptp_ctrl_type) {
- case START_CTRL_CONN_RQST: /* Start Control Connection Request */
- deal_start_ctrl_conn(packet, rply_packet, rply_size);
- break;
-
- case STOP_CTRL_CONN_RQST:
- deal_stop_ctrl_conn(packet, rply_packet, rply_size);
- break;
-
- case OUT_CALL_RQST: /* Outgoing Call Request */
- deal_out_call(packet, rply_packet, rply_size);
- break;
-
- case ECHO_RQST: /* Echo Request */
- deal_echo(packet, rply_packet, rply_size);
- break;
-
- case CALL_CLR_RQST: /* Call Clear Request (Disconnect Request) */
- deal_call_clr(packet, rply_packet, rply_size);
- break;
-
- case SET_LINK_INFO: /* Set Link Info */
- /* no reply packet but process it */
- deal_set_link_info(packet);
- break;
-
- case ECHO_RPLY: /* Echo Reply */
- case STOP_CTRL_CONN_RPLY: /* Stop Control Connection Reply */
- case CALL_DISCONN_NTFY: /* Call Disconnect Notify */
- /* no reply packet */
- break;
-
- default:
- syslog(LOG_ERR, "CTRL: PPTP Control Message type %d not supported.", pptp_ctrl_type);
- pptp_ctrl_type = -1;
- }
-
- return pptp_ctrl_type;
-}
-
-
-/*
- * send_pptp_packet
- *
- * Sends a PPTP packet to a file descriptor.
- *
- * args: clientFd (IN) - file descriptor to write the packet to.
- * packet (IN) - the packet data to write.
- * packet_size (IN) - the packet size.
- *
- * retn: Number of bytes written on success.
- * -1 on write failure.
- */
-size_t send_pptp_packet(int clientFd, unsigned char *packet, size_t packet_size)
-{
-
- size_t bytes_written;
-
- if ((bytes_written = write(clientFd, packet, packet_size)) == -1) {
- /* write failed */
- syslog(LOG_ERR, "CTRL: Couldn't write packet to client.");
- return -1;
-
- } else {
- /* debugging */
- if (pptpctrl_debug) {
- syslog(LOG_DEBUG, "CTRL: I wrote %i bytes to the client.", (int)packet_size);
- syslog(LOG_DEBUG, "CTRL: Sent packet to client");
- }
- return bytes_written;
- }
-}
-
-/*
- * ignoreErrno
- *
- * Check if an errno represents a read error which should be ignored, and
- * put back to be select()ed on again later.
- *
- * Very similar to the function in Squid by Duane Wessels (under GPL).
- *
- * args: an errno value
- *
- * retn: 1 if the error is unimportant
- * 0 if the error is important
- */
-static int ignoreErrno(int ierrno) {
- switch (ierrno) {
- case EAGAIN: /* nothing to read */
- case EINTR: /* signal received */
-#ifdef ERESTART
-#if ERESTART != EINTR
- case ERESTART: /* signal received, should restart syscall */
-#endif
-#endif
-#if EWOULDBLOCK != EAGAIN
- case EWOULDBLOCK: /* shouldn't get this one but anyway, just in case */
-#endif
- return 1;
- default:
- return 0;
- }
-}
-
-/*
- * read_pptp_header
- *
- * Reads a packet from a file descriptor and determines whether it is a
- * valid PPTP Control Message. If a valid PPTP Control Message is detected
- * it extracts the Control Message type from the packet header.
- *
- * args: clientFd (IN) - Clients file descriptor.
- * packet (OUT) - Packet we read from the client.
- * pptp_ctrl_type (OUT) - PPTP Control Message type of the packet.
- *
- * retn: Number of bytes read on success.
- * -1 on retryable error.
- * 0 on error to exit on.
- */
-ssize_t read_pptp_header(int clientFd, unsigned char *packet, int *pptp_ctrl_type)
-{
-
- ssize_t bytes_ttl, bytes_this; /* quantities read (total and this read) */
- u_int16_t length; /* length of this packet */
- struct pptp_header *header; /* the received header */
-
- static char *buffer = NULL; /* buffer between calls */
- static int buffered = 0; /* size of buffer */
-
- *pptp_ctrl_type = 0; /* initialise return arg */
-
- /* read any previously buffered data */
- if (buffered) {
- memcpy(packet, buffer, buffered);
- free(buffer);
- buffer = NULL;
- bytes_ttl = buffered;
- buffered = 0;
- if (pptpctrl_debug)
- syslog(LOG_DEBUG, "CTRL: Read in previous incomplete ctrl packet");
- } else
- bytes_ttl = 0;
-
- /* try and get the length in */
- if (bytes_ttl < 2) {
- bytes_this = read(clientFd, packet + bytes_ttl, 2 - bytes_ttl);
- switch (bytes_this) {
- case -1:
- if (ignoreErrno(errno)) {
- /* re-tryable error, re-buffer and return */
- if (bytes_ttl) {
- buffered = bytes_ttl;
- buffer = malloc(bytes_ttl);
- if (!buffer)
- return(0);
- memcpy(buffer, packet, bytes_ttl);
- }
- syslog(LOG_ERR, "CTRL: Error reading ctrl packet length (bytes_ttl=%i): %s", (int)bytes_ttl, strerror(errno));
- return -1;
- }
- /* FALLTHRU */
- case 0:
- syslog(LOG_ERR, "CTRL: EOF or bad error reading ctrl packet length.");
- return 0;
- default:
- bytes_ttl += bytes_this;
- /* Not enough data to proceed */
- if (bytes_ttl == 1) {
- buffered = bytes_ttl;
- buffer = malloc(bytes_ttl);
- if (!buffer)
- return(0);
- memcpy(buffer, packet, bytes_ttl);
- if (pptpctrl_debug)
- syslog(LOG_DEBUG, "CTRL: Incomplete ctrl packet length, retry later");
- return -1;
- }
- }
- }
- /* OK, we have (at least) the first 2 bytes, and there is data waiting
- *
- * length includes the header, so a length less than 2 is someone
- * trying to hack into us or a badly corrupted packet.
- * Why not require length to be at least 10? Since we later cast
- * packet to struct pptp_header and use at least the 10 first bytes..
- * Thanks to Timo Sirainen for mentioning this.
- */
- length = htons(*(u_int16_t *) packet);
- if (length <= 10 || length > PPTP_MAX_CTRL_PCKT_SIZE) {
- syslog(LOG_ERR, "CTRL: 11 < Control packet (length=%d) < "
- "PPTP_MAX_CTRL_PCKT_SIZE (%d)",
- length, PPTP_MAX_CTRL_PCKT_SIZE);
- /* we loose sync (unless we malloc something big, which isn't a good
- * idea - potential DoS) so we must close connection (draft states that
- * if you loose sync you must close the control connection immediately)
- */
- return 0;
- }
- /* Now read the actual control packet */
- bytes_this = read(clientFd, packet + bytes_ttl, length - bytes_ttl);
- switch (bytes_this) {
- case -1:
- if(ignoreErrno(errno)) {
- /* re-tryable error, re-buffer and return */
- if (bytes_ttl) {
- buffered = bytes_ttl;
- buffer = malloc(bytes_ttl);
- if (!buffer)
- return(0);
- memcpy(buffer, packet, bytes_ttl);
- }
- syslog(LOG_ERR, "CTRL: Error reading ctrl packet (bytes_ttl=%d,length=%d): %s", (int)bytes_ttl, (int)length, strerror(errno));
- return -1;
- }
- /* FALLTHRU */
- case 0:
- syslog(LOG_ERR, "CTRL: EOF or bad error reading ctrl packet.");
- return 0;
- default:
- bytes_ttl += bytes_this;
- /* not enough data to proceed */
- if (bytes_ttl != length) {
- buffered = bytes_ttl;
- buffer = malloc(bytes_ttl);
- if (!buffer)
- return(0);
- memcpy(buffer, packet, bytes_ttl);
- if (pptpctrl_debug)
- syslog(LOG_DEBUG, "CTRL: Incomplete ctrl packet, retry later");
- return -1;
- }
- }
-
- /* We got one :-) */
-
- /* Cast the packet into the PPTP Control Message format */
- header = (struct pptp_header *) packet;
-
- /* Packet sanity check on magic cookie */
- if (ntohl(header->magic) != PPTP_MAGIC_COOKIE) {
- /* Oops! Not a valid Control Message */
- syslog(LOG_ERR, "CTRL: Bad magic cookie - lost syncronization, closing control connection.");
- /* draft states loss of syncronization must result in
- * immediate closing of the control connection
- */
- return 0;
- }
- /* Woohoo! Looks like we got a valid PPTP packet */
- *pptp_ctrl_type = (int) (ntohs(header->ctrl_type));
- if (pptpctrl_debug)
- syslog(LOG_DEBUG, "CTRL: Received PPTP Control Message (type: %d)", *pptp_ctrl_type);
- return bytes_ttl;
-}
-
-/* Macros to use in making response packets */
-
-#define MAKE_CTRL_HEADER(where, what) \
- where.header.length = htons(sizeof(where)); \
- where.header.pptp_type = htons(PPTP_CTRL_MESSAGE); \
- where.header.magic = htonl(PPTP_MAGIC_COOKIE); \
- where.header.ctrl_type = htons(what); \
- where.header.reserved0 = htons(RESERVED)
-
-#define COPY_CTRL_PACKET(from, to, size) \
- memcpy(to, &from, ((*size) = sizeof(from)))
-
-#define DEBUG_PACKET(what) \
- if(pptpctrl_debug) \
- syslog(LOG_DEBUG, "CTRL: Made a " what " packet")
-
-/*
- * deal_start_ctrl_conn
- *
- * This method 'deals' with a START-CONTROL-CONNECTION-REQUEST. After
- * stripping down the connection request a suitable reply is formed and
- * stored in 'rply_packet' ready for sending.
- *
- * args: packet (IN) - the packet that we have to deal with (should be a
- * START-CONTROL-CONNECTION-REQUEST packet)
- * rply_packet (OUT) - suitable reply to the 'packet' we got.
- * rply_size (OUT) - size of the reply packet
- */
-void deal_start_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
-{
- struct pptp_start_ctrl_conn_rqst *start_ctrl_conn_rqst;
- struct pptp_start_ctrl_conn_rply start_ctrl_conn_rply;
-
- start_ctrl_conn_rqst = (struct pptp_start_ctrl_conn_rqst *) packet;
-
- MAKE_CTRL_HEADER(start_ctrl_conn_rply, START_CTRL_CONN_RPLY);
- start_ctrl_conn_rply.version = htons(PPTP_VERSION);
- start_ctrl_conn_rply.result_code = CONNECTED;
- start_ctrl_conn_rply.error_code = NO_ERROR;
- start_ctrl_conn_rply.framing_cap = htons(OUR_FRAMING);
- start_ctrl_conn_rply.bearer_cap = htons(OUR_BEARER);
- start_ctrl_conn_rply.max_channels = htons(MAX_CHANNELS);
- start_ctrl_conn_rply.firmware_rev = htons(PPTP_FIRMWARE_VERSION);
- bzero(start_ctrl_conn_rply.hostname, MAX_HOSTNAME_SIZE);
- strncpy((char *)start_ctrl_conn_rply.hostname, PPTP_HOSTNAME, MAX_HOSTNAME_SIZE);
- bzero(start_ctrl_conn_rply.vendor, MAX_VENDOR_SIZE);
- strncpy((char *)start_ctrl_conn_rply.vendor, PPTP_VENDOR, MAX_VENDOR_SIZE);
- COPY_CTRL_PACKET(start_ctrl_conn_rply, rply_packet, rply_size);
- DEBUG_PACKET("START CTRL CONN RPLY");
-}
-
-/*
- * deal_stop_ctrl_conn
- *
- * This method response to a STOP-CONTROL-CONNECTION-REQUEST with a
- * STOP-CONTROL-CONNECTION-REPLY.
- */
-void deal_stop_ctrl_conn(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
-{
- struct pptp_stop_ctrl_conn_rply stop_ctrl_conn_rply;
-
- MAKE_CTRL_HEADER(stop_ctrl_conn_rply, STOP_CTRL_CONN_RPLY);
- stop_ctrl_conn_rply.result_code = DISCONNECTED;
- stop_ctrl_conn_rply.error_code = NO_ERROR;
- stop_ctrl_conn_rply.reserved1 = htons(RESERVED);
- COPY_CTRL_PACKET(stop_ctrl_conn_rply, rply_packet, rply_size);
- DEBUG_PACKET("STOP CTRL CONN RPLY");
-}
-
-/*
- * deal_out_call
- *
- * This method 'deals' with a OUT-GOING-CALL-REQUEST. After
- * stripping down the request a suitable reply is formed and stored in
- * 'rply_packet' ready for sending.
- *
- * args: packet (IN) - the packet that we have to deal with (should be a
- * OUT-GOING-CALL-REQUEST packet)
- * rply_packet (OUT) - suitable reply to the 'packet' we got.
- * rply_size (OUT) - size of the reply packet
- *
- */
-void deal_out_call(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
-{
- u_int16_t pac_call_id;
- struct pptp_out_call_rqst *out_call_rqst;
- struct pptp_out_call_rply out_call_rply;
-
- out_call_rqst = (struct pptp_out_call_rqst *) packet;
-
- if ((pac_call_id = getcall()) == htons(-1)) {
- /* XXX should reject call */
- syslog(LOG_ERR, "CTRL: No free Call IDs!");
- pac_call_id = 0;
- }
- MAKE_CTRL_HEADER(out_call_rply, OUT_CALL_RPLY);
- /* call_id is used for ctrl, call_id_peer is used for GRE
- * call_id_peer is what we were sent by the other end in ctrl initilization
- */
- out_call_rply.call_id = pac_call_id;
- out_call_rply.call_id_peer = out_call_rqst->call_id;
- out_call_rply.result_code = CONNECTED;
- out_call_rply.error_code = NO_ERROR;
- out_call_rply.cause_code = NO_ERROR;
- /* maybe limit to pppd speed? but pppd doesn't accept 10Mbps as a speed and yet
- * still performs at over 115200, eg, 60kbyte/sec and higher observed.
- */
- out_call_rply.speed = out_call_rqst->max_bps;
- /* lets match their window size for now... was htons(PCKT_RECV_WINDOW_SIZE)
- */
- out_call_rply.pckt_recv_size = out_call_rqst->pckt_recv_size;
- window=htons(out_call_rply.pckt_recv_size);
- if(pptpctrl_debug)
- syslog(LOG_DEBUG, "CTRL: Set parameters to %d maxbps, %d window size",
- ntohl(out_call_rply.speed), ntohs(out_call_rply.pckt_recv_size));
- out_call_rply.pckt_delay = htons(PCKT_PROCESS_DELAY);
- out_call_rply.channel_id = htonl(CHANNEL_ID);
- COPY_CTRL_PACKET(out_call_rply, rply_packet, rply_size);
- DEBUG_PACKET("OUT CALL RPLY");
-}
-
-
-/*
- * deal_echo
- *
- * This method 'deals' with a ECHO-REQUEST. After stripping down the
- * connection request a suitable reply is formed and stored in
- * 'rply_packet' ready for sending.
- *
- * args: packet (IN) - the packet that we have to deal with (should be a
- * ECHO-REQUEST packet)
- * rply_packet (OUT) - suitable reply to the 'packet' we got.
- * rply_size (OUT) - size of the reply packet
- *
- */
-void deal_echo(unsigned char *packet, unsigned char *rply_packet, ssize_t * rply_size)
-{
- struct pptp_echo_rqst *echo_rqst;
- struct pptp_echo_rply echo_rply;
-
- echo_rqst = (struct pptp_echo_rqst *) packet;
-
- MAKE_CTRL_HEADER(echo_rply, ECHO_RPLY);
- echo_rply.identifier = echo_rqst->identifier;
- echo_rply.result_code = CONNECTED;
- echo_rply.error_code = NO_ERROR;
- echo_rply.reserved1 = htons(RESERVED);
- COPY_CTRL_PACKET(echo_rply, rply_packet, rply_size);
- DEBUG_PACKET("ECHO RPLY");
-}
-
-/*
- * deal_call_clr
- *
- * This method 'deals' with a CALL-CLEAR-REQUEST. After stripping down the
- * connection request a suitable reply is formed and stored in
- * 'rply_packet' ready for sending.
- *
- * args: packet (IN) - the packet that we have to deal with (should be a
- * CALL-CLEAR-REQUEST packet)
- * rply_packet (OUT) - suitable reply to the 'packet' we got.
- * rply_size (OUT) - size of the reply packet
- *
- */
-void deal_call_clr(unsigned char *packet, unsigned char *rply_packet, ssize_t *rply_size)
-{
- struct pptp_call_disconn_ntfy call_disconn_ntfy;
- u_int16_t pac_call_id;
-
- /* Form a reply
- * The reply packet is a CALL-DISCONECT-NOTIFY
- * In single call mode we don't care what peer's call ID is, so don't even bother looking
- */
- if ((pac_call_id = freecall()) == htons(-1)) {
- /* XXX should return an error */
- syslog(LOG_ERR, "CTRL: Could not free Call ID [call clear]!");
- }
- MAKE_CTRL_HEADER(call_disconn_ntfy, CALL_DISCONN_NTFY);
- call_disconn_ntfy.call_id = pac_call_id;
- call_disconn_ntfy.result_code = CALL_CLEAR_REQUEST; /* disconnected by call_clr_rqst */
- call_disconn_ntfy.error_code = NO_ERROR;
- call_disconn_ntfy.cause_code = htons(NO_ERROR);
- call_disconn_ntfy.reserved1 = htons(RESERVED);
- memset(call_disconn_ntfy.call_stats, 0, 128);
- COPY_CTRL_PACKET(call_disconn_ntfy, rply_packet, rply_size);
- DEBUG_PACKET("CALL DISCONNECT RPLY");
-}
-
-/*
- * deal_set_link_info
- *
- * @FIXME This function is *not* completed
- *
- * This method 'deals' with a SET-LINK-INFO. After stripping down the
- * connection request a suitable reply is formed and stored in
- * 'rply_packet' ready for sending.
- *
- * args: packet (IN) - the packet that we have to deal with (should be a
- * SET-LINK-INFO packet)
- * rply_packet (OUT) - suitable reply to the 'packet' we got.
- * rply_size (OUT) - size of the reply packet
- *
- */
-void deal_set_link_info(unsigned char *packet)
-{
- struct pptp_set_link_info *set_link_info;
-
- set_link_info = (struct pptp_set_link_info *) packet;
- if(set_link_info->send_accm != 0xffffffff || set_link_info->recv_accm != 0xffffffff)
- syslog(LOG_ERR, "CTRL: Ignored a SET LINK INFO packet with real ACCMs!");
- else if(pptpctrl_debug)
- syslog(LOG_DEBUG, "CTRL: Got a SET LINK INFO packet with standard ACCMs");
-}
-
-void make_echo_req_packet(unsigned char *rply_packet, ssize_t * rply_size, u_int32_t echo_id)
-{
- struct pptp_echo_rqst echo_packet;
-
- MAKE_CTRL_HEADER(echo_packet, ECHO_RQST);
- echo_packet.identifier = echo_id;
- COPY_CTRL_PACKET(echo_packet, rply_packet, rply_size);
- DEBUG_PACKET("ECHO REQ");
-}
-
-void make_stop_ctrl_req(unsigned char *rply_packet, ssize_t * rply_size)
-{
- struct pptp_stop_ctrl_conn_rqst stop_ctrl;
-
- MAKE_CTRL_HEADER(stop_ctrl, STOP_CTRL_CONN_RQST);
- stop_ctrl.reason = GENERAL_STOP_CTRL;
- stop_ctrl.reserved1 = RESERVED;
- stop_ctrl.reserved2 = htons(RESERVED);
- COPY_CTRL_PACKET(stop_ctrl, rply_packet, rply_size);
- DEBUG_PACKET("STOP CTRL REQ");
-}
-
-void make_call_admin_shutdown(unsigned char *rply_packet, ssize_t * rply_size)
-{
- struct pptp_call_disconn_ntfy call_disconn_ntfy;
- u_int16_t pac_call_id;
-
- /* Form a reply
- * The reply packet is a CALL-DISCONECT-NOTIFY
- * In single call mode we don't care what peer's call ID is, so don't even bother looking
- */
- if ((pac_call_id = freecall()) == htons(-1)) {
- /* XXX should return an error */
- syslog(LOG_ERR, "CTRL: Could not free Call ID [admin shutdown]!");
- }
- MAKE_CTRL_HEADER(call_disconn_ntfy, CALL_DISCONN_NTFY);
- call_disconn_ntfy.call_id = pac_call_id;
- call_disconn_ntfy.result_code = ADMIN_SHUTDOWN; /* disconnected by admin shutdown */
- call_disconn_ntfy.error_code = NO_ERROR;
- call_disconn_ntfy.cause_code = htons(NO_ERROR);
- call_disconn_ntfy.reserved1 = htons(RESERVED);
- memset(call_disconn_ntfy.call_stats, 0, 128);
- COPY_CTRL_PACKET(call_disconn_ntfy, rply_packet, rply_size);
- DEBUG_PACKET("CALL DISCONNECT RPLY");
-}
-
-#if PNS_MODE
-/* out of date. really PNS isn't 'trivially different', it's quite different */
-
-#define C_BITS (sizeof(unsigned int) * 8)
-#define C_SEG(x) (x/C_BITS)
-#define C_BIT(x) ((1U)<<(x%C_BITS))
-static unsigned int activeCalls[(MAX_CALLS / C_BITS) + 1];
-
-/*
- * get_call_id
- *
- * Assigns a call ID and peer call ID to the session.
- *
- * args: call_id (OUT) - the call ID for the session
- * retn: 0 on success, -1 on failure
- */
-int get_call_id(u_int16_t * loc)
-{
- for (i = 0; i < MAX_CALLS; i++) {
- if (!(activeCalls[C_SEG(i)] & C_BIT(i))) {
- activeCalls[C_SEG(i)] |= C_BIT(i);
- *loc = i;
- return 0;
- }
- }
- return -1;
-}
-
-/*
- * free_call_id
- *
- * args: call_id (IN) - the call ID for a terminated session
- * retn: 0 on success, -1 on failure
- */
-int free_call_id(u_int16_t call_id)
-{
- if (!(activeCalls[C_SEG(i)] & C_BIT(i)))
- return -1;
- activeCalls[C_SEG(i)] &= ~C_BIT(i);
- return 0;
-}
-#else
-static int _pac_call_id;
-static u_int16_t _pac_init = 0;
-
-/*
- * getcall
- *
- * Assigns a call ID to the session and stores/returns it
- *
- * we only permit one call at a time, so the chance of wrapping 65k on one
- * control connection is zero to none...
- */
-u_int16_t getcall()
-{
- struct sockaddr_pppox src_addr;
- socklen_t addrlen;
-
- src_addr.sa_family=AF_PPPOX;
- src_addr.sa_protocol=PX_PROTO_PPTP;
- src_addr.sa_addr.pptp.call_id=0;
- src_addr.sa_addr.pptp.sin_addr=inetaddrs[0];
-
- if (pptp_sock!=-1) close(pptp_sock);
-
- pptp_sock=socket(AF_PPPOX,SOCK_STREAM,PX_PROTO_PPTP);
- if (pptp_sock<0)
- {
- syslog(LOG_ERR,"CTRL: failed to create PPTP socket (%s)\n",strerror(errno));
- exit(-1);
- }
- if (bind(pptp_sock,(struct sockaddr*)&src_addr,sizeof(src_addr)))
- {
- syslog(LOG_ERR,"CTRL: failed to bind PPTP socket (%s)\n",strerror(errno));
- close(pptp_sock);
- pptp_sock=-1;
- exit(-1);
- }
- addrlen=sizeof(src_addr);
- getsockname(pptp_sock,(struct sockaddr*)&src_addr,&addrlen);
-
- if(!_pac_init) {
- _pac_call_id = htons(-1);
- _pac_init = 1;
- }
- if(_pac_call_id != htons(-1))
- syslog(LOG_ERR, "CTRL: Asked to allocate call id when call open, not handled well");
-
- _pac_call_id = htons(src_addr.sa_addr.pptp.call_id) ;
- return _pac_call_id;
-}
-
-/*
- * freecall
- *
- * Notes termination of current call
- *
- * retn: -1 on failure, PAC call ID on success
- */
-u_int16_t freecall()
-{
- u_int16_t ret;
-
- if (pptp_sock!=-1){
- close(pptp_sock);
- pptp_sock=-1;
- }
-
- if(!_pac_init) {
- _pac_call_id = htons(-1);
- _pac_init = 1;
- }
- ret = _pac_call_id;
- if(_pac_call_id == htons(-1))
- syslog(LOG_ERR, "CTRL: Asked to free call when no call open, not handled well");
- _pac_call_id = htons(-1);
- return ret;
-}
-#endif