Dont read/write PCP messages as C struct to remove dependency to the "pack" feature.

structs are left (commented out) in pcp_msg_struct.h for information
This commit is contained in:
Thomas Bernard 2015-09-22 10:22:06 +02:00
parent a6b947e0ca
commit 3d8986b646
2 changed files with 211 additions and 221 deletions

View File

@ -143,6 +143,7 @@ typedef enum pcp_options {
#pragma pack(push, 1)
/* PCP common request header*/
#if 0
typedef struct pcp_request {
uint8_t ver;
uint8_t r_opcode;
@ -152,8 +153,11 @@ typedef struct pcp_request {
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_request_t;
#endif
#define PCP_COMMON_REQUEST_SIZE (24)
/* PCP common response header*/
#if 0
typedef struct pcp_response {
uint8_t ver;
uint8_t r_opcode; /* R indicates Request (0) or Response (1)
@ -166,16 +170,22 @@ typedef struct pcp_response {
uint32_t reserved1[3];/* For requests that were successfully parsed this must be sent as 0 */
uint8_t next_data[0];
} pcp_response_t;
#endif
#define PCP_COMMON_RESPONSE_SIZE (24)
#if 0
typedef struct pcp_options_hdr {
uint8_t code; /* Most significant bit indicates if this option is mandatory (0) or optional (1) */
uint8_t reserved; /* MUST be set to 0 on transmission and MUST be ignored on reception */
uint16_t len; /* indicates the length of the enclosed data in octets (see RFC) */
uint8_t next_data[0]; /* */
} pcp_options_hdr_t;
#endif
#define PCP_OPTION_HDR_SIZE (4)
/* same for both request and response */
#if 0
typedef struct pcp_map_v2 {
uint32_t nonce[3];
uint8_t protocol; /* 6 = TCP, 17 = UDP, 0 = 'all protocols' */
@ -186,7 +196,10 @@ typedef struct pcp_map_v2 {
* ipv4 will be represented by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_map_v2_t;
#endif
#define PCP_MAP_V2_SIZE (36)
#if 0
/* same for both request and response */
typedef struct pcp_map_v1 {
uint8_t protocol;
@ -197,8 +210,11 @@ typedef struct pcp_map_v1 {
by the ipv4 mapped ipv6 */
uint8_t next_data[0];
} pcp_map_v1_t;
#endif
#define PCP_MAP_V1_SIZE (24)
/* same for both request and response */
#if 0
typedef struct pcp_peer_v1 {
uint8_t protocol;
uint8_t reserved[3];
@ -211,8 +227,11 @@ typedef struct pcp_peer_v1 {
struct in6_addr peer_ip;
uint8_t next_data[0];
} pcp_peer_v1_t;
#endif
#define PCP_PEER_V1_SIZE (44)
/* same for both request and response */
#if 0
typedef struct pcp_peer_v2 {
uint32_t nonce[3];
uint8_t protocol;
@ -226,30 +245,41 @@ typedef struct pcp_peer_v2 {
struct in6_addr peer_ip;
uint8_t next_data[0];
} pcp_peer_v2_t;
#endif
#define PCP_PEER_V2_SIZE (56)
#ifdef PCP_SADSCP
#if 0
typedef struct pcp_sadscp_req {
uint32_t nonce[3];
uint8_t tolerance_fields;
uint8_t app_name_length;
char app_name[0];
} pcp_sadscp_req_t;
#endif
#define PCP_SADSCP_REQ_SIZE (14)
#if 0
typedef struct pcp_sadscp_resp {
uint32_t nonce[3];
#define PCP_SADSCP_MASK ((1<<6)-1)
uint8_t a_r_dscp_value;
uint8_t reserved[3];
} pcp_sadscp_resp_t;
#endif
#define PCP_SADSCP_MASK ((1<<6)-1)
#endif /* PCP_SADSCP */
#if 0
typedef struct pcp_prefer_fail_option {
uint8_t option;
uint8_t reserved;
uint16_t len;
uint8_t next_data[0];
} pcp_prefer_fail_option_t;
#endif
#define PCP_PREFER_FAIL_OPTION_SIZE (4)
#if 0
typedef struct pcp_3rd_party_option{
uint8_t option;
uint8_t reserved;
@ -257,22 +287,28 @@ typedef struct pcp_3rd_party_option{
struct in6_addr ip;
uint8_t next_data[0];
} pcp_3rd_party_option_t;
#endif
#define PCP_3RD_PARTY_OPTION_SIZE (20)
#ifdef PCP_FLOWP
#if 0
typedef struct pcp_flow_priority_option{
uint8_t option;
uint8_t reserved;
uint16_t len;
uint8_t dscp_up;
uint8_t dscp_down;
#define PCP_DSCP_MASK ((1<<6)-1)
uint8_t reserved2;
/* most significant bit is used for response */
uint8_t response_bit;
uint8_t next_data[0];
} pcp_flow_priority_option_t;
#endif
#define PCP_DSCP_MASK ((1<<6)-1)
#define PCP_FLOW_PRIORITY_OPTION_SIZE (8)
#endif
#if 0
typedef struct pcp_filter_option {
uint8_t option;
uint8_t reserved1;
@ -282,6 +318,8 @@ typedef struct pcp_filter_option {
uint16_t peer_port;
struct in6_addr peer_ip;
}pcp_filter_option_t;
#endif
#define PCP_FILTER_OPTION_SIZE (24)
#pragma pack(pop)

View File

@ -207,16 +207,16 @@ int get_dscp_value(pcp_info_t *pcp_msg_info) {
* result code is assigned to pcp_msg_info->result_code to indicate
* what kind of error occurred
*/
static int parseCommonRequestHeader(const pcp_request_t *common_req, pcp_info_t *pcp_msg_info)
static int parseCommonRequestHeader(const uint8_t *common_req, pcp_info_t *pcp_msg_info)
{
pcp_msg_info->version = common_req->ver ;
pcp_msg_info->opcode = common_req->r_opcode & 0x7f;
pcp_msg_info->lifetime = ntohl(common_req->req_lifetime);
pcp_msg_info->int_ip = &common_req->ip;
pcp_msg_info->mapped_ip = &common_req->ip;
pcp_msg_info->version = common_req[0] ;
pcp_msg_info->opcode = common_req[1] & 0x7f;
pcp_msg_info->lifetime = READNU32(common_req + 4);
pcp_msg_info->int_ip = (struct in6_addr *)(common_req + 8);
pcp_msg_info->mapped_ip = (struct in6_addr *)(common_req + 8);
if ( (common_req->ver > this_server_info.server_version) ) {
if ( (pcp_msg_info->version > this_server_info.server_version) ) {
pcp_msg_info->result_code = PCP_ERR_UNSUPP_VERSION;
return 1;
}
@ -233,42 +233,42 @@ static int parseCommonRequestHeader(const pcp_request_t *common_req, pcp_info_t
}
#ifdef DEBUG
static void printMAPOpcodeVersion1(const pcp_map_v1_t *map_buf)
static void printMAPOpcodeVersion1(const uint8_t *buf)
{
char map_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP MAP: v1 Opcode specific information. \n");
syslog(LOG_DEBUG, "MAP protocol: \t\t %d\n",map_buf->protocol );
syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", ntohs(map_buf->int_port) );
syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", ntohs(map_buf->ext_port) );
syslog(LOG_DEBUG, "MAP protocol: \t\t %d\n", (int)buf[0] );
syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", (int)READNU16(buf+4));
syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", (int)READNU16(buf+6));
syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6,
&map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN));
buf+8, map_addr, INET6_ADDRSTRLEN));
}
static void printMAPOpcodeVersion2(const pcp_map_v2_t *map_buf)
static void printMAPOpcodeVersion2(const uint8_t *buf)
{
char map_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP MAP: v2 Opcode specific information.");
syslog(LOG_DEBUG, "MAP nonce: \t%08x%08x%08x",
map_buf->nonce[0], map_buf->nonce[1], map_buf->nonce[2]);
syslog(LOG_DEBUG, "MAP protocol:\t%d", map_buf->protocol);
syslog(LOG_DEBUG, "MAP int port:\t%d", ntohs(map_buf->int_port));
syslog(LOG_DEBUG, "MAP ext port:\t%d", ntohs(map_buf->ext_port));
READNU32(buf), READNU32(buf+4), READNU32(buf+8));
syslog(LOG_DEBUG, "MAP protocol:\t%d", (int)buf[12]);
syslog(LOG_DEBUG, "MAP int port:\t%d", (int)READNU16(buf+16));
syslog(LOG_DEBUG, "MAP ext port:\t%d", (int)READNU16(buf+18));
syslog(LOG_DEBUG, "MAP Ext IP: \t%s", inet_ntop(AF_INET6,
&map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN));
buf+20, map_addr, INET6_ADDRSTRLEN));
}
#endif /* DEBUG */
static int parsePCPMAP_version1(const pcp_map_v1_t *map_v1,
static int parsePCPMAP_version1(const uint8_t *map_v1,
pcp_info_t *pcp_msg_info)
{
pcp_msg_info->is_map_op = 1;
pcp_msg_info->protocol = map_v1->protocol;
pcp_msg_info->int_port = ntohs(map_v1->int_port);
pcp_msg_info->ext_port = ntohs(map_v1->ext_port);
pcp_msg_info->protocol = map_v1[0];
pcp_msg_info->int_port = READNU16(map_v1 + 4);
pcp_msg_info->ext_port = READNU16(map_v1 + 6);
pcp_msg_info->ext_ip = &(map_v1->ext_ip);
pcp_msg_info->ext_ip = (struct in6_addr *)(map_v1 + 8);
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port != 0) {
syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value.");
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1;
@ -276,16 +276,16 @@ static int parsePCPMAP_version1(const pcp_map_v1_t *map_v1,
return 0;
}
static int parsePCPMAP_version2(const pcp_map_v2_t *map_v2,
static int parsePCPMAP_version2(const uint8_t *map_v2,
pcp_info_t *pcp_msg_info)
{
pcp_msg_info->is_map_op = 1;
memcpy(pcp_msg_info->nonce, map_v2->nonce, 12);
pcp_msg_info->protocol = map_v2->protocol;
pcp_msg_info->int_port = ntohs(map_v2->int_port);
pcp_msg_info->ext_port = ntohs(map_v2->ext_port);
memcpy(pcp_msg_info->nonce, map_v2, 12);
pcp_msg_info->protocol = map_v2[12];
pcp_msg_info->int_port = READNU16(map_v2 + 16);
pcp_msg_info->ext_port = READNU16(map_v2 + 18);
pcp_msg_info->ext_ip = &(map_v2->ext_ip);
pcp_msg_info->ext_ip = (struct in6_addr *)(map_v2 + 20);
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ) {
syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value.");
@ -298,37 +298,37 @@ static int parsePCPMAP_version2(const pcp_map_v2_t *map_v2,
#ifdef PCP_PEER
#ifdef DEBUG
static void printPEEROpcodeVersion1(pcp_peer_v1_t *peer_buf)
static void printPEEROpcodeVersion1(const uint8_t *buf)
{
char ext_addr[INET6_ADDRSTRLEN];
char peer_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP PEER: v1 Opcode specific information. \n");
syslog(LOG_DEBUG, "Protocol: \t\t %d\n",peer_buf->protocol );
syslog(LOG_DEBUG, "Internal port: \t\t %d\n", ntohs(peer_buf->int_port) );
syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->ext_ip,
syslog(LOG_DEBUG, "Protocol: \t\t %d\n", (int)buf[0]);
syslog(LOG_DEBUG, "Internal port: \t\t %d\n", READNU16(buf + 4));
syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, buf + 8,
ext_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "External port port: \t\t %d\n", ntohs(peer_buf->ext_port) );
syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->peer_ip,
syslog(LOG_DEBUG, "External port port: \t\t %d\n", READNU16(buf + 6));
syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, buf + 28,
peer_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", ntohs(peer_buf->peer_port) );
syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", READNU16(buf + 24));
}
static void printPEEROpcodeVersion2(pcp_peer_v2_t *peer_buf)
static void printPEEROpcodeVersion2(const uint8_t *buf)
{
char ext_addr[INET6_ADDRSTRLEN];
char peer_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP PEER: v2 Opcode specific information.");
syslog(LOG_DEBUG, "nonce: \t%08x%08x%08x",
peer_buf->nonce[0], peer_buf->nonce[1], peer_buf->nonce[2]);
syslog(LOG_DEBUG, "Protocol: \t%d",peer_buf->protocol );
syslog(LOG_DEBUG, "Internal port:\t%d", ntohs(peer_buf->int_port) );
syslog(LOG_DEBUG, "External IP: \t%s", inet_ntop(AF_INET6, &peer_buf->ext_ip,
ext_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "External port:\t%d", ntohs(peer_buf->ext_port) );
syslog(LOG_DEBUG, "PEER IP: \t%s", inet_ntop(AF_INET6, &peer_buf->peer_ip,
peer_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "PEER port: \t%d", ntohs(peer_buf->peer_port) );
READNU32(buf), READNU32(buf+4), READNU32(buf+8));
syslog(LOG_DEBUG, "Protocol: \t%d", buf[12]);
syslog(LOG_DEBUG, "Internal port:\t%d", READNU16(buf + 16));
syslog(LOG_DEBUG, "External IP: \t%s", inet_ntop(AF_INET6, buf + 20,
ext_addr, INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "External port:\t%d", READNU16(buf + 18));
syslog(LOG_DEBUG, "PEER IP: \t%s", inet_ntop(AF_INET6, buf + 40,
peer_addr, INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "PEER port: \t%d", READNU16(buf + 36));
}
#endif /* DEBUG */
@ -336,19 +336,19 @@ static void printPEEROpcodeVersion2(pcp_peer_v2_t *peer_buf)
* Function extracting information from peer_buf to pcp_msg_info
* @return : when no problem occurred 0 is returned, 1 otherwise
*/
static int parsePCPPEER_version1(pcp_peer_v1_t *peer_buf, \
static int parsePCPPEER_version1(const uint8_t *buf,
pcp_info_t *pcp_msg_info)
{
pcp_msg_info->is_peer_op = 1;
pcp_msg_info->protocol = peer_buf->protocol;
pcp_msg_info->int_port = ntohs(peer_buf->int_port);
pcp_msg_info->ext_port = ntohs(peer_buf->ext_port);
pcp_msg_info->peer_port = ntohs(peer_buf->peer_port);
pcp_msg_info->protocol = buf[0];
pcp_msg_info->int_port = READNU16(buf + 4);
pcp_msg_info->ext_port = READNU16(buf + 6);
pcp_msg_info->peer_port = READNU16(buf + 24);
pcp_msg_info->ext_ip = &peer_buf->ext_ip;
pcp_msg_info->peer_ip = &peer_buf->peer_ip;
pcp_msg_info->ext_ip = (struct in6_addr *)(buf + 8);
pcp_msg_info->peer_ip = (struct in6_addr *)(buf + 28);
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0) {
syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value.");
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1;
@ -360,20 +360,19 @@ static int parsePCPPEER_version1(pcp_peer_v1_t *peer_buf, \
* Function extracting information from peer_buf to pcp_msg_info
* @return : when no problem occurred 0 is returned, 1 otherwise
*/
static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \
pcp_info_t *pcp_msg_info)
static int parsePCPPEER_version2(const uint8_t *buf, pcp_info_t *pcp_msg_info)
{
pcp_msg_info->is_peer_op = 1;
memcpy(pcp_msg_info->nonce, peer_buf->nonce, 12);
pcp_msg_info->protocol = peer_buf->protocol;
pcp_msg_info->int_port = ntohs(peer_buf->int_port);
pcp_msg_info->ext_port = ntohs(peer_buf->ext_port);
pcp_msg_info->peer_port = ntohs(peer_buf->peer_port);
memcpy(pcp_msg_info->nonce, buf, 12);
pcp_msg_info->protocol = buf[12];
pcp_msg_info->int_port = READNU16(buf + 16);
pcp_msg_info->ext_port = READNU16(buf + 18);
pcp_msg_info->peer_port = READNU16(buf + 36);
pcp_msg_info->ext_ip = &peer_buf->ext_ip;
pcp_msg_info->peer_ip = &peer_buf->peer_ip;
pcp_msg_info->ext_ip = (struct in6_addr *)(buf + 20);
pcp_msg_info->peer_ip = (struct in6_addr *)(buf + 40);
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){
if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port != 0) {
syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value.");
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1;
@ -384,110 +383,89 @@ static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \
#ifdef PCP_SADSCP
#ifdef DEBUG
static void printSADSCPOpcode(pcp_sadscp_req_t *sadscp) {
static void printSADSCPOpcode(const uint8_t *buf)
{
unsigned char sadscp_tol;
sadscp_tol = sadscp->tolerance_fields;
sadscp_tol = buf[12]; /* tolerance_fields */
syslog(LOG_DEBUG, "PCP SADSCP: Opcode specific information.\n");
syslog(LOG_DEBUG, "Delay tolerance %d \n", (sadscp_tol>>6)&3 );
syslog(LOG_DEBUG, "Delay tolerance %d \n", (sadscp_tol>>6)&3);
syslog(LOG_DEBUG, "Loss tolerance %d \n", (sadscp_tol>>4)&3);
syslog(LOG_DEBUG, "Jitter tolerance %d \n", (sadscp_tol>>2)&3);
syslog(LOG_DEBUG, "RRR %d \n", sadscp_tol&3);
syslog(LOG_DEBUG, "AppName Length %d \n", sadscp->app_name_length);
if (sadscp->app_name) {
syslog(LOG_DEBUG, "Application name %.*s \n", sadscp->app_name_length,
sadscp->app_name);
}
syslog(LOG_DEBUG, "AppName Length %d \n", buf[13]);
syslog(LOG_DEBUG, "Application name %.*s \n", buf[13], buf + 14);
}
#endif //DEBUG
static int parseSADSCP(pcp_sadscp_req_t *sadscp, pcp_info_t *pcp_msg_info) {
static int parseSADSCP(const uint8_t *buf, pcp_info_t *pcp_msg_info)
{
pcp_msg_info->delay_tolerance = (buf[12]>>6)&3;
pcp_msg_info->loss_tolerance = (buf[12]>>4)&3;
pcp_msg_info->jitter_tolerance = (buf[12]>>2)&3;
pcp_msg_info->delay_tolerance = (sadscp->tolerance_fields>>6)&3;
pcp_msg_info->loss_tolerance = (sadscp->tolerance_fields>>4)&3;
pcp_msg_info->jitter_tolerance = (sadscp->tolerance_fields>>2)&3;
if (pcp_msg_info->delay_tolerance == 3 ) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1;
}
if ( pcp_msg_info->loss_tolerance == 3 ) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1;
}
if ( pcp_msg_info->jitter_tolerance == 3 ) {
if (pcp_msg_info->delay_tolerance == 3 ||
pcp_msg_info->loss_tolerance == 3 ||
pcp_msg_info->jitter_tolerance == 3 ) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1;
}
pcp_msg_info->app_name = sadscp->app_name;
pcp_msg_info->app_name_len = sadscp->app_name_length;
pcp_msg_info->app_name = (const char *)(buf + 14);
pcp_msg_info->app_name_len = buf[13];
return 0;
}
#endif
#endif /* PCP_SADSCP */
static int parsePCPOption(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info)
static int parsePCPOption(uint8_t* pcp_buf, int remain, pcp_info_t *pcp_msg_info)
{
#ifdef DEBUG
char third_addr[INET6_ADDRSTRLEN];
#endif
#endif /* DEBUG */
unsigned short option_length;
pcp_3rd_party_option_t* opt_3rd;
#ifdef PCP_FLOWP
pcp_flow_priority_option_t* opt_flp;
#endif
pcp_filter_option_t* opt_filter;
pcp_prefer_fail_option_t* opt_prefail;
pcp_options_hdr_t* opt_hdr;
opt_hdr = (pcp_options_hdr_t*)pcp_buf;
/* Do centralized option sanity checks here. */
if (remain < (int)sizeof(*opt_hdr)) {
if (remain < (int)PCP_OPTION_HDR_SIZE) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0;
}
option_length = ntohs(opt_hdr->len) + 4;
option_length = READNU16(pcp_buf + 2) + 4; /* len */
if (remain < option_length) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0;
}
switch (opt_hdr->code) {
switch (pcp_buf[0]) { /* code */
case PCP_OPTION_3RD_PARTY:
opt_3rd = (pcp_3rd_party_option_t*)pcp_buf;
if ( option_length != sizeof(*opt_3rd) ) {
if (option_length != PCP_3RD_PARTY_OPTION_SIZE) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0;
}
#ifdef DEBUG
syslog(LOG_DEBUG, "PCP OPTION: \t Third party \n");
syslog(LOG_DEBUG, "PCP OPTION: \t Third party\n");
syslog(LOG_DEBUG, "Third PARTY IP: \t %s\n", inet_ntop(AF_INET6,
&(opt_3rd->ip), third_addr, INET6_ADDRSTRLEN));
pcp_buf + 4, third_addr, INET6_ADDRSTRLEN));
#endif
if (pcp_msg_info->thirdp_ip ) {
syslog(LOG_ERR, "PCP: THIRD PARTY OPTION was already present. \n");
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0;
}
else {
pcp_msg_info->thirdp_ip = &opt_3rd->ip;
pcp_msg_info->mapped_ip = &opt_3rd->ip;
} else {
pcp_msg_info->thirdp_ip = (struct in6_addr *)(pcp_buf + 4);
pcp_msg_info->mapped_ip = (struct in6_addr *)(pcp_buf + 4);
}
break;
case PCP_OPTION_PREF_FAIL:
opt_prefail = (pcp_prefer_fail_option_t*)pcp_buf;
if ( option_length != sizeof(*opt_prefail) ) {
if (option_length != PCP_PREFER_FAIL_OPTION_SIZE) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0;
}
@ -499,19 +477,16 @@ static int parsePCPOption(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info)
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
}
if (pcp_msg_info->pfailure_present != 0 ) {
syslog(LOG_DEBUG, "PCP: PREFER FAILURE OPTION was already present. \n");
syslog(LOG_DEBUG, "PCP: PREFER FAILURE OPTION was already present.\n");
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
}
else {
} else {
pcp_msg_info->pfailure_present = 1;
}
break;
case PCP_OPTION_FILTER:
/* TODO fully implement filter */
opt_filter = (pcp_filter_option_t*)pcp_buf;
if ( option_length != sizeof(*opt_filter) ) {
if (option_length != PCP_FILTER_OPTION_SIZE) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0;
}
@ -531,28 +506,26 @@ static int parsePCPOption(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info)
#ifdef DEBUG
syslog(LOG_DEBUG, "PCP OPTION: \t Flow priority\n");
#endif
opt_flp = (pcp_flow_priority_option_t*)pcp_buf;
if ( option_length != sizeof (*opt_flp) ) {
syslog(LOG_ERR, "PCP: Error processing DSCP. sizeof %d and remaining %d . flow len %d \n",
(int)sizeof(pcp_flow_priority_option_t), remain, opt_flp->len);
if (option_length != PCP_FLOW_PRIORITY_OPTION_SIZE) {
syslog(LOG_ERR, "PCP: Error processing DSCP. sizeof %d and remaining %d. flow len %d \n",
PCP_FLOW_PRIORITY_OPTION_SIZE, remain, READNU16(pcp_buf + 2));
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0;
}
#ifdef DEBUG
syslog(LOG_DEBUG, "DSCP UP: \t %d \n", opt_flp->dscp_up);
syslog(LOG_DEBUG, "DSCP DOWN: \t %d \n", opt_flp->dscp_down);
syslog(LOG_DEBUG, "DSCP UP: \t %d\n", pcp_buf[4]);
syslog(LOG_DEBUG, "DSCP DOWN: \t %d\n", pcp_buf[5]);
#endif
pcp_msg_info->dscp_up = opt_flp->dscp_up;
pcp_msg_info->dscp_down = opt_flp->dscp_down;
pcp_msg_info->dscp_up = pcp_buf[4];
pcp_msg_info->dscp_down = pcp_buf[5];
pcp_msg_info->flowp_present = 1;
break;
#endif
default:
if (opt_hdr->code < 128) {
syslog(LOG_ERR, "PCP: Unrecognized mandatory PCP OPTION: %d \n", opt_hdr->code);
if (pcp_buf[0] < 128) {
syslog(LOG_ERR, "PCP: Unrecognized mandatory PCP OPTION: %d \n", (int)pcp_buf[0]);
/* Mandatory to understand */
pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION;
remain = 0;
@ -1224,17 +1197,8 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
{
int remainingSize;
const pcp_map_v1_t* map_v1;
const pcp_map_v2_t* map_v2;
#ifdef PCP_PEER
pcp_peer_v1_t* peer_v1;
pcp_peer_v2_t* peer_v2;
#endif
#ifdef PCP_SADSCP
pcp_sadscp_req_t* sadscp;
#endif
/* start with PCP_SUCCESS as result code, if everything is OK value will be unchanged */
/* start with PCP_SUCCESS as result code,
* if everything is OK value will be unchanged */
pcp_msg_info->result_code = PCP_SUCCESS;
remainingSize = req_size;
@ -1258,33 +1222,32 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
}
/* first parse request header */
if (parseCommonRequestHeader((pcp_request_t*)req, pcp_msg_info) ) {
if (parseCommonRequestHeader(req, pcp_msg_info) ) {
return 1;
}
remainingSize -= sizeof(pcp_request_t);
req += sizeof(pcp_request_t);
remainingSize -= PCP_COMMON_REQUEST_SIZE;
req += PCP_COMMON_REQUEST_SIZE;
if (pcp_msg_info->version == 1) {
/* legacy PCP version 1 support */
switch (pcp_msg_info->opcode) {
case PCP_OPCODE_MAP:
remainingSize -= sizeof(pcp_map_v1_t);
remainingSize -= PCP_MAP_V1_SIZE;
if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code;
}
map_v1 = (pcp_map_v1_t*)req;
#ifdef DEBUG
printMAPOpcodeVersion1(map_v1);
printMAPOpcodeVersion1(req);
#endif /* DEBUG */
if ( parsePCPMAP_version1(map_v1, pcp_msg_info) ) {
if ( parsePCPMAP_version1(req, pcp_msg_info) ) {
return pcp_msg_info->result_code;
}
req += sizeof(pcp_map_v1_t);
req += PCP_MAP_V1_SIZE;
parsePCPOptions(req, remainingSize, pcp_msg_info);
if (ValidatePCPMsg(pcp_msg_info)) {
@ -1303,21 +1266,20 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
#ifdef PCP_PEER
case PCP_OPCODE_PEER:
remainingSize -= sizeof(pcp_peer_v1_t);
remainingSize -= PCP_PEER_V1_SIZE;
if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code;
}
peer_v1 = (pcp_peer_v1_t*)req;
#ifdef DEBUG
printPEEROpcodeVersion1(peer_v1);
printPEEROpcodeVersion1(req);
#endif /* DEBUG */
if ( parsePCPPEER_version1(peer_v1, pcp_msg_info) ) {
if ( parsePCPPEER_version1(req, pcp_msg_info) ) {
return pcp_msg_info->result_code;
}
req += sizeof(pcp_peer_v1_t);
req += PCP_PEER_V1_SIZE;
parsePCPOptions(req, remainingSize, pcp_msg_info);
@ -1349,22 +1311,20 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
break;
case PCP_OPCODE_MAP:
remainingSize -= sizeof(pcp_map_v2_t);
remainingSize -= PCP_MAP_V2_SIZE;
if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code;
}
map_v2 = (pcp_map_v2_t*)req;
#ifdef DEBUG
printMAPOpcodeVersion2(map_v2);
printMAPOpcodeVersion2(req);
#endif /* DEBUG */
if (parsePCPMAP_version2(map_v2, pcp_msg_info) ) {
if (parsePCPMAP_version2(req, pcp_msg_info) ) {
return pcp_msg_info->result_code;
}
req += sizeof(pcp_map_v2_t);
req += PCP_MAP_V2_SIZE;
parsePCPOptions(req, remainingSize, pcp_msg_info);
@ -1384,18 +1344,17 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
#ifdef PCP_PEER
case PCP_OPCODE_PEER:
remainingSize -= sizeof(pcp_peer_v2_t);
remainingSize -= PCP_PEER_V2_SIZE;
if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code;
}
peer_v2 = (pcp_peer_v2_t*)req;
#ifdef DEBUG
printPEEROpcodeVersion2(peer_v2);
printPEEROpcodeVersion2(req);
#endif /* DEBUG */
parsePCPPEER_version2(peer_v2, pcp_msg_info);
req += sizeof(pcp_peer_v2_t);
parsePCPPEER_version2(req, pcp_msg_info);
req += PCP_PEER_V2_SIZE;
if (pcp_msg_info->result_code != 0) {
return pcp_msg_info->result_code;
@ -1418,25 +1377,27 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
#ifdef PCP_SADSCP
case PCP_OPCODE_SADSCP:
remainingSize -= sizeof(pcp_sadscp_req_t);
remainingSize -= PCP_SADSCP_REQ_SIZE;
if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code;
}
sadscp = (pcp_sadscp_req_t*)req;
req += sizeof(pcp_sadscp_req_t);
if (sadscp->app_name_length > remainingSize) {
remainingSize -= ((uint8_t *)req)[13]; /* app_name_length */
if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return pcp_msg_info->result_code;
}
#ifdef DEBUG
printSADSCPOpcode(sadscp);
printSADSCPOpcode(req);
#endif
if (parseSADSCP(sadscp, pcp_msg_info)) {
parseSADSCP(req, pcp_msg_info);
req += PCP_SADSCP_REQ_SIZE;
if (pcp_msg_info->result_code != 0) {
return pcp_msg_info->result_code;
}
req += pcp_msg_info->app_name_len;
get_dscp_value(pcp_msg_info);
@ -1457,22 +1418,18 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
{
pcp_response_t *resp = (pcp_response_t*)response;
resp->reserved = 0;
resp->reserved1[0]=0;
resp->reserved1[1]=0;
resp->reserved1[2]=0;
response[2] = 0; /* reserved */
memset(response + 12, 0, 12); /* reserved */
if (pcp_msg_info->result_code == PCP_ERR_UNSUPP_VERSION ) {
/* highest supported version */
resp->ver = this_server_info.server_version;
response[0] = this_server_info.server_version;
} else {
resp->ver = pcp_msg_info->version;
response[0] = pcp_msg_info->version;
}
resp->r_opcode |= 0x80;
resp->result_code = pcp_msg_info->result_code;
resp->epochtime = htonl(time(NULL) - startup_time);
response[1] |= 0x80; /* r_opcode */
response[3] = pcp_msg_info->result_code;
WRITENU32(response + 8, time(NULL) - startup_time); /* epochtime */
switch (pcp_msg_info->result_code) {
/*long lifetime errors*/
case PCP_ERR_UNSUPP_VERSION:
@ -1485,61 +1442,56 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
case PCP_ERR_ADDRESS_MISMATCH:
case PCP_ERR_CANNOT_PROVIDE_EXTERNAL:
case PCP_ERR_EXCESSIVE_REMOTE_PEERS:
resp->lifetime = 0;
WRITENU32(response + 4, 0); /* lifetime */
break;
case PCP_ERR_NETWORK_FAILURE:
case PCP_ERR_NO_RESOURCES:
case PCP_ERR_USER_EX_QUOTA:
resp->lifetime = htonl(30);
WRITENU32(response + 4, 30); /* lifetime */
break;
case PCP_SUCCESS:
default:
resp->lifetime = htonl(pcp_msg_info->lifetime);
WRITENU32(response + 4, pcp_msg_info->lifetime); /* lifetime */
break;
}
if (resp->r_opcode == 0x81) { /* MAP response */
if (resp->ver == 1 ) {
pcp_map_v1_t *mapr = (pcp_map_v1_t *)resp->next_data;
mapr->ext_ip = *pcp_msg_info->ext_ip;
mapr->ext_port = htons(pcp_msg_info->ext_port);
mapr->int_port = htons(pcp_msg_info->int_port);
if (response[1] == 0x81) { /* MAP response */
if (response[0] == 1) { /* version */
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 4, pcp_msg_info->int_port);
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 6, pcp_msg_info->ext_port);
memcpy(response + PCP_COMMON_RESPONSE_SIZE + 8, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
}
else if (resp->ver == 2 ) {
pcp_map_v2_t *mapr = (pcp_map_v2_t *)resp->next_data;
mapr->ext_ip = *pcp_msg_info->ext_ip;
mapr->ext_port = htons(pcp_msg_info->ext_port);
mapr->int_port = htons(pcp_msg_info->int_port);
else if (response[0] == 2) {
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 16, pcp_msg_info->int_port);
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 18, pcp_msg_info->ext_port);
memcpy(response + PCP_COMMON_RESPONSE_SIZE + 20, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
}
}
#ifdef PCP_PEER
else if (resp->r_opcode == 0x82) { /* PEER response */
if (resp->ver == 1 ){
pcp_peer_v1_t* peer_resp = (pcp_peer_v1_t*)resp->next_data;
peer_resp->ext_port = htons(pcp_msg_info->ext_port);
peer_resp->int_port = htons(pcp_msg_info->int_port);
peer_resp->peer_port = htons(pcp_msg_info->peer_port);
peer_resp->ext_ip = *pcp_msg_info->ext_ip;
else if (response[1] == 0x82) { /* PEER response */
if (response[0] == 1) {
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 4, pcp_msg_info->int_port);
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 6, pcp_msg_info->ext_port);
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 24, pcp_msg_info->peer_port);
memcpy(response + PCP_COMMON_RESPONSE_SIZE + 8, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
}
else if (resp->ver == 2 ){
pcp_peer_v2_t* peer_resp = (pcp_peer_v2_t*)resp->next_data;
peer_resp->ext_port = htons(pcp_msg_info->ext_port);
peer_resp->int_port = htons(pcp_msg_info->int_port);
peer_resp->peer_port = htons(pcp_msg_info->peer_port);
peer_resp->ext_ip = *pcp_msg_info->ext_ip;
else if (response[0] == 2) {
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 16, pcp_msg_info->int_port);
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 18, pcp_msg_info->ext_port);
WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 36, pcp_msg_info->peer_port);
memcpy(response + PCP_COMMON_RESPONSE_SIZE + 20, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
}
}
#endif /* PCP_PEER */
#ifdef PCP_SADSCP
else if (resp->r_opcode == 0x83) { /*SADSCP response*/
pcp_sadscp_resp_t *sadscp_resp = (pcp_sadscp_resp_t*)resp->next_data;
sadscp_resp->a_r_dscp_value = pcp_msg_info->matched_name<<7;
sadscp_resp->a_r_dscp_value &= ~(1<<6);
sadscp_resp->a_r_dscp_value |= (pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK);
memset(sadscp_resp->reserved, 0, sizeof(sadscp_resp->reserved));
else if (response[1] == 0x83) { /*SADSCP response*/
response[PCP_COMMON_RESPONSE_SIZE + 12]
= ((pcp_msg_info->matched_name<<7) & ~(1<<6)) |
(pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK);
memset(response + PCP_COMMON_RESPONSE_SIZE + 13, 0, 3);
}
#endif /* PCP_SADSCP */
}