asuswrt-merlin.ng/release/src-rt-5.02axhnd/userspace/public/include/pcp.h
2020-08-28 22:07:59 -04:00

328 lines
11 KiB
C

/*
* Copyright (C) 2010-2011 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: pcp.h 1253 2011-07-04 14:54:05Z fdupont $ */
/*
* PCP (port-control-protocol) client library include
*
* Francis_Dupont@isc.org, December 2010
*
* a la miniUPnP libnatpmp
*
* types: pcp_t, pcp_request_t, pcp_response_t
*/
/* API version */
#define __PCP_API_VERSION__ 0
#include <sys/time.h>
/* Types */
#ifndef PCP_MAX_OPTIONS
#define PCP_MAX_OPTIONS 4
#endif
#define PCP_VECOPT_SIZE (PCP_MAX_OPTIONS + 1)
typedef struct { /* PCP handler (opaque) */
int s; /* server socket */
uint8_t usable; /* better than s < 0 */
uint8_t tries; /* retry counter */
uint8_t reset; /* reset flag */
struct timeval retry; /* next retry date */
uint16_t reqlen; /* current request length */
uint16_t resplen; /* current response length */
uint8_t *request; /* current request */
#define PCP_RESPLENGTH 512
uint8_t *response; /* current response */
} pcp_t;
typedef struct { /* PCP option */
uint8_t code; /* option code */
uint8_t res; /* reserved field */
uint16_t length; /* option data length (per 32 bits) */
uint8_t *data; /* option data */
} pcp_option_t;
typedef struct { /* PCP element of request */
uint8_t ver; /* version */
uint8_t opcode; /* opcode */
uint16_t res; /* reserved field */
uint32_t lifetime; /* lifetime */
uint8_t iaddr[16]; /* internal address */
/* fields below are for MAP/PEER opcode specific */
uint16_t iport; /* internal port */
uint16_t eport; /* external port */
uint8_t eaddr[16]; /* external address */
uint8_t raddr[16]; /* remote address */
uint16_t rport; /* remote peer's port */
uint8_t protocol; /* protocol */
} pcp_request_t;
/*
* PCP response Packet Format:
*
* 0 1 2 3
* Version Opcode Reserved Result
* Lifetime
* Epoch Time
* Reserved
* Reserved
* Reserved
* Opcode specific response data
* Options
*/
typedef struct { /* PCP response */
uint8_t ver; /* version */
uint8_t opcode; /* opcode */
uint8_t res; /* reserved field */
uint8_t result; /* result-code */
uint32_t lifetime; /* lifetime */
uint32_t epochtime; /* second since start of epoch */
uint8_t optcnt; /* option count */
pcp_request_t assigned; /* assigned request */
pcp_option_t options[PCP_VECOPT_SIZE]; /* returned options */
unsigned int optoffs[PCP_VECOPT_SIZE]; /* options offsets */
} pcp_response_t;
typedef struct { /* PCP MAP specific info */
uint8_t proto; /* protocol */
uint8_t res[3]; /* reserved field */
uint16_t iport; /* internal port */
uint16_t eport; /* external port */
uint8_t eaddr[16]; /* external address */
} pcp_map_t;
typedef struct { /* PCP PEER specific info */
uint8_t proto; /* protocol */
uint8_t res1[3]; /* reserved field */
uint16_t iport; /* internal port */
uint16_t eport; /* external port */
uint8_t eaddr[16]; /* external address */
uint16_t rport; /* remote peer's port */
uint16_t res2; /* reserved field */
uint8_t raddr[16]; /* remote peer's address */
} pcp_peer_t;
#if 0
typedef struct { /* PCP third_party option */
uint8_t code; /* 1 */
uint8_t res; /* 0 */
uint16_t length; /* 16 */
uint8_t iaddr[16]; /* LAN device's address */
} pcp_option_thirdparty_t;
typedef struct { /* PCP prefer_failure option */
uint8_t code; /* 2 */
uint8_t res; /* 0 */
uint16_t length; /* 0 */
} pcp_option_preferfailure_t;
typedef struct { /* PCP filter option */
uint8_t code; /* 3 */
uint8_t res1; /* 0 */
uint16_t length; /* 20 */
uint8_t res2; /* 0 */
uint8_t plen; /* prefix length */
uint16_t rport; /* remote peer's port */
uint8_t raddr[16]; /* remote peer's address */
} pcp_option_filter_t;
#endif
/* Routines */
extern int pcp_init(struct sockaddr *server,
struct sockaddr *source,
pcp_t *pcp, int isRenew);
extern int pcp_close(pcp_t *pcp, int isRenew);
extern int pcp_getsocket(pcp_t *pcp, int *sock);
extern int pcp_gettries(pcp_t *pcp, int *tries);
extern int pcp_gettimeout(pcp_t *pcp, struct timeval *timeout, int relative);
extern int pcp_setreset(pcp_t *pcp, int reset, int *old);
extern int pcp_third_party(pcp_option_t ***options, const uint8_t *addr);
extern int pcp_prefer_failure(pcp_option_t ***options);
extern int pcp_filter4(pcp_option_t ***options, uint32_t addr, uint16_t port);
extern int pcp_filter6(pcp_option_t ***options, uint8_t *addr, uint16_t port);
extern int pcp_makerequest(pcp_t *pcp,
pcp_request_t *request,
pcp_option_t **options);
extern int pcp_sendrequest(pcp_t *pcp);
extern int pcp_recvresponse(pcp_t *pcp, pcp_response_t *response);
extern const char *pcp_strerror(int error);
extern int pcp_fillintaddr(pcp_t *pcp, pcp_request_t *request);
extern int pcp_getmapping(pcp_t *pcp,
pcp_request_t *request,
pcp_option_t **options,
pcp_response_t *response);
extern int pcp_renewmapping(pcp_t *pcp, pcp_response_t *response);
extern int pcp_delmapping(pcp_t *pcp, pcp_response_t *response);
extern int _pcp_setrequest(pcp_t *pcp, uint8_t *request, uint16_t reqlen);
extern int _pcp_getrequest(pcp_t *pcp, uint8_t **request, uint16_t *reqlen);
extern int _pcp_setresponse(pcp_t *pcp, uint8_t *response, uint16_t resplen);
extern int _pcp_getresponse(pcp_t *pcp, uint8_t **response, uint16_t *resplen);
/* Support PCP version */
#define PCP_VERSION_IMPL 1
/* UDP port number */
#define PCP_LISTEN_PORT1 5350
#define PCP_LISTEN_PORT2 5351
#define PCP_RELINQUISH_PORT 44323
/* opcode values */
#define PCP_OPCODE_ANNOUNCE 0
#define PCP_OPCODE_MAP 1
#define PCP_OPCODE_PEER 2
#define PCP_OPCODE_RESPONSE 128 /* response bit */
/* offsets in the common header */
#define PCP_OPCODE_HDR 24
/* offsets in the MAP header */
#define PCP_MAP_PROTOCOL (PCP_OPCODE_HDR + 0)
#define PCP_MAP_INTERNAL_PORT (PCP_OPCODE_HDR + 4)
#define PCP_MAP_EXTERNAL_PORT (PCP_OPCODE_HDR + 6)
#define PCP_MAP_EXTERNAL_ADDR (PCP_OPCODE_HDR + 8)
/* offsets in the PEER header */
#define PCP_PEER_PROTOCOL (PCP_OPCODE_HDR + 0)
#define PCP_PEER_INTERNAL_PORT (PCP_OPCODE_HDR + 4)
#define PCP_PEER_EXTERNAL_PORT (PCP_OPCODE_HDR + 6)
#define PCP_PEER_EXTERNAL_ADDR (PCP_OPCODE_HDR + 8)
#define PCP_PEER_REMOTE_PORT (PCP_OPCODE_HDR + 24)
#define PCP_PEER_REMOTE_ADDR (PCP_OPCODE_HDR + 28)
/* lengths */
#define PCP_LEN_MAP 48
#define PCP_LEN_PEER 68
#define PCP_LEN_THIRDPARTY_OPTION 16
#define PCP_LEN_FILTER_OPTION 20
/* PCP Result Code */
#define PCP_OK (0) /* SUCCESS */
#define PCP_UNSUPP_VERSION (1) /* Unsupported protocol version */
#define PCP_NOT_AUTHORIZED (2) /* Unauthorized req */
#define PCP_MALFORMED_REQ (3) /* Request cannot be parsed */
#define PCP_UNSUPP_OPCODE (4) /* Unsupported opcode */
#define PCP_UNSUPP_OPTION (5) /* Unsupported option */
#define PCP_MALFORMED_OPT (6) /* Malformed option */
#define PCP_NETWORK_FAIL (7) /* Network failure */
#define PCP_NO_RESOURCE (8) /* NO_RESOURCE */
#define PCP_UNSUPP_PROTO (9) /* Unsupported proto */
#define PCP_EX_QUOTA (10)/* Exceed user's port quota */
#define PCP_NO_EXTERNAL (11)/* Cannot provide external */
#define PCP_ADDR_MISMATCH (12)/* Address mismatch */
/* Errors */
/* bad API use */
#define PCP_ERR_INVAL (-1) /* invalid arguments */
/* OS errors */
#define PCP_ERR_NOMEM (-10) /* malloc() failed */
#define PCP_ERR_SOCKET (-11) /* socket() syscall failed */
#define PCP_ERR_BIND (-12) /* bind() syscall failed */
#define PCP_ERR_CONNECT (-13) /* connect() syscall failed */
#define PCP_ERR_SEND (-14) /* send() syscall failed */
#define PCP_ERR_RECV (-15) /* recv() syscall failed */
#define PCP_ERR_SYSCALL (-16) /* miscellaneous syscall failed */
/* routine errors */
#define PCP_ERR_NOREQUEST (-20) /* no current request */
#define PCP_ERR_RECVBAD (-21) /* received a bad response */
#define PCP_ERR_TOOMANYOPTS (-22) /* too many options */
/* *mapping failure */
#define PCP_ERR_FAILURE (-30) /* *mapping() internal failure */
/* user application */
#define PCP_ERR_APP0 (-50) /* user application error 0 */
#define PCP_ERR_APP1 (-51) /* user application error 1 */
#define PCP_ERR_APP2 (-52) /* user application error 2 */
/* protocol errors */
#define PCP_ERR_PROTOBASE (-100) /* base for protocol errors */
#define PCP_ERR_UNSUPVERSION (-101) /* unsupported version */
#define PCP_ERR_BADREQUEST (-102) /* malformed request */
#define PCP_ERR_UNSUPOPCODE (-103) /* unsupported opcode */
#define PCP_ERR_UNSUPOPTION (-104) /* unsupported option */
#define PCP_ERR_BADOPTION (-105) /* malformed option */
#define PCP_ERR_PROCERROR (-106) /* processing error */
#define PCP_ERR_SRVOVERLOAD (-107) /* overloaded server */
#define PCP_ERR_NETFAILURE (-120) /* network failure */
#define PCP_ERR_NORESOURCES (-121) /* out of resources */
#define PCP_ERR_UNSUPPROTO (-122) /* unsupported protocol */
#define PCP_ERR_NOTAUTH (-123) /* not authorized */
#define PCP_ERR_EXQUOTA (-124) /* user exceeded quota */
#define PCP_ERR_CANTPROVIDE (-125) /* cannot provide external port */
#define PCP_ERR_TOOMANYPEER (-126) /* excessive number of remote peers */
#define PCP_ERR_UNAUTH3PTY (-151) /* unauthorized third party */
#define PCP_ERR_IMPLICITMAP (-228) /* collides with implicit mapping */
/* Options */
#define PCP_OPTION_THIRD_PARTY 1 /* third-party */
#define PCP_OPTION_PREF_FAIL 2 /* prefer failure */
#define PCP_OPTION_FILTER 3 /* remote peer filter */
#define PCP_OPTION_OPTIONAL 128 /* flag bit */
/* Others */
/* Default port of PCP service */
#define PCP_PORT 5351
/* Default retry timer (in seconds) */
#define PCP_RETRY_TIMER 2
/* Maximum number of tries */
#define PCP_MAX_TRIES 4
/* Default reset threshold (in seconds) */
#ifndef PCP_RESET_THRESHOLD
#define PCP_RESET_THRESHOLD 60
#endif
/* Tunables & co */
/* weak definition so you can overwrite them */
extern void *pcp_malloc(size_t size);
extern void pcp_free(void *ptr);
/* inline utility to free allocated options */
static inline void pcp_freeoptions(pcp_option_t **options) {
if (options != NULL) {
unsigned int i;
for (i = 0; options[i] != NULL; i++)
pcp_free(options[i]);
pcp_free(options);
options = NULL;
}
}
extern const char *err_app0_msg;
extern const char *err_app1_msg;
extern const char *err_app2_msg;
/* for bad response debugging */
#define LIBSPEC
// LIBSPEC int pcp_debug_offset;
// LIBSPEC int pcp_debug_line;