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) #pragma pack(push, 1)
/* PCP common request header*/ /* PCP common request header*/
#if 0
typedef struct pcp_request { typedef struct pcp_request {
uint8_t ver; uint8_t ver;
uint8_t r_opcode; uint8_t r_opcode;
@ -152,8 +153,11 @@ typedef struct pcp_request {
by the ipv4 mapped ipv6 */ by the ipv4 mapped ipv6 */
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_request_t; } pcp_request_t;
#endif
#define PCP_COMMON_REQUEST_SIZE (24)
/* PCP common response header*/ /* PCP common response header*/
#if 0
typedef struct pcp_response { typedef struct pcp_response {
uint8_t ver; uint8_t ver;
uint8_t r_opcode; /* R indicates Request (0) or Response (1) 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 */ uint32_t reserved1[3];/* For requests that were successfully parsed this must be sent as 0 */
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_response_t; } pcp_response_t;
#endif
#define PCP_COMMON_RESPONSE_SIZE (24)
#if 0
typedef struct pcp_options_hdr { typedef struct pcp_options_hdr {
uint8_t code; /* Most significant bit indicates if this option is mandatory (0) or optional (1) */ 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 */ 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) */ uint16_t len; /* indicates the length of the enclosed data in octets (see RFC) */
uint8_t next_data[0]; /* */ uint8_t next_data[0]; /* */
} pcp_options_hdr_t; } pcp_options_hdr_t;
#endif
#define PCP_OPTION_HDR_SIZE (4)
/* same for both request and response */ /* same for both request and response */
#if 0
typedef struct pcp_map_v2 { typedef struct pcp_map_v2 {
uint32_t nonce[3]; uint32_t nonce[3];
uint8_t protocol; /* 6 = TCP, 17 = UDP, 0 = 'all protocols' */ 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 */ * ipv4 will be represented by the ipv4 mapped ipv6 */
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_map_v2_t; } pcp_map_v2_t;
#endif
#define PCP_MAP_V2_SIZE (36)
#if 0
/* same for both request and response */ /* same for both request and response */
typedef struct pcp_map_v1 { typedef struct pcp_map_v1 {
uint8_t protocol; uint8_t protocol;
@ -197,8 +210,11 @@ typedef struct pcp_map_v1 {
by the ipv4 mapped ipv6 */ by the ipv4 mapped ipv6 */
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_map_v1_t; } pcp_map_v1_t;
#endif
#define PCP_MAP_V1_SIZE (24)
/* same for both request and response */ /* same for both request and response */
#if 0
typedef struct pcp_peer_v1 { typedef struct pcp_peer_v1 {
uint8_t protocol; uint8_t protocol;
uint8_t reserved[3]; uint8_t reserved[3];
@ -211,8 +227,11 @@ typedef struct pcp_peer_v1 {
struct in6_addr peer_ip; struct in6_addr peer_ip;
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_peer_v1_t; } pcp_peer_v1_t;
#endif
#define PCP_PEER_V1_SIZE (44)
/* same for both request and response */ /* same for both request and response */
#if 0
typedef struct pcp_peer_v2 { typedef struct pcp_peer_v2 {
uint32_t nonce[3]; uint32_t nonce[3];
uint8_t protocol; uint8_t protocol;
@ -226,30 +245,41 @@ typedef struct pcp_peer_v2 {
struct in6_addr peer_ip; struct in6_addr peer_ip;
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_peer_v2_t; } pcp_peer_v2_t;
#endif
#define PCP_PEER_V2_SIZE (56)
#ifdef PCP_SADSCP #ifdef PCP_SADSCP
#if 0
typedef struct pcp_sadscp_req { typedef struct pcp_sadscp_req {
uint32_t nonce[3]; uint32_t nonce[3];
uint8_t tolerance_fields; uint8_t tolerance_fields;
uint8_t app_name_length; uint8_t app_name_length;
char app_name[0]; char app_name[0];
} pcp_sadscp_req_t; } pcp_sadscp_req_t;
#endif
#define PCP_SADSCP_REQ_SIZE (14)
#if 0
typedef struct pcp_sadscp_resp { typedef struct pcp_sadscp_resp {
uint32_t nonce[3]; uint32_t nonce[3];
#define PCP_SADSCP_MASK ((1<<6)-1)
uint8_t a_r_dscp_value; uint8_t a_r_dscp_value;
uint8_t reserved[3]; uint8_t reserved[3];
} pcp_sadscp_resp_t; } pcp_sadscp_resp_t;
#endif #endif
#define PCP_SADSCP_MASK ((1<<6)-1)
#endif /* PCP_SADSCP */
#if 0
typedef struct pcp_prefer_fail_option { typedef struct pcp_prefer_fail_option {
uint8_t option; uint8_t option;
uint8_t reserved; uint8_t reserved;
uint16_t len; uint16_t len;
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_prefer_fail_option_t; } pcp_prefer_fail_option_t;
#endif
#define PCP_PREFER_FAIL_OPTION_SIZE (4)
#if 0
typedef struct pcp_3rd_party_option{ typedef struct pcp_3rd_party_option{
uint8_t option; uint8_t option;
uint8_t reserved; uint8_t reserved;
@ -257,22 +287,28 @@ typedef struct pcp_3rd_party_option{
struct in6_addr ip; struct in6_addr ip;
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_3rd_party_option_t; } pcp_3rd_party_option_t;
#endif
#define PCP_3RD_PARTY_OPTION_SIZE (20)
#ifdef PCP_FLOWP #ifdef PCP_FLOWP
#if 0
typedef struct pcp_flow_priority_option{ typedef struct pcp_flow_priority_option{
uint8_t option; uint8_t option;
uint8_t reserved; uint8_t reserved;
uint16_t len; uint16_t len;
uint8_t dscp_up; uint8_t dscp_up;
uint8_t dscp_down; uint8_t dscp_down;
#define PCP_DSCP_MASK ((1<<6)-1)
uint8_t reserved2; uint8_t reserved2;
/* most significant bit is used for response */ /* most significant bit is used for response */
uint8_t response_bit; uint8_t response_bit;
uint8_t next_data[0]; uint8_t next_data[0];
} pcp_flow_priority_option_t; } pcp_flow_priority_option_t;
#endif #endif
#define PCP_DSCP_MASK ((1<<6)-1)
#define PCP_FLOW_PRIORITY_OPTION_SIZE (8)
#endif
#if 0
typedef struct pcp_filter_option { typedef struct pcp_filter_option {
uint8_t option; uint8_t option;
uint8_t reserved1; uint8_t reserved1;
@ -282,6 +318,8 @@ typedef struct pcp_filter_option {
uint16_t peer_port; uint16_t peer_port;
struct in6_addr peer_ip; struct in6_addr peer_ip;
}pcp_filter_option_t; }pcp_filter_option_t;
#endif
#define PCP_FILTER_OPTION_SIZE (24)
#pragma pack(pop) #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 * result code is assigned to pcp_msg_info->result_code to indicate
* what kind of error occurred * 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->version = common_req[0] ;
pcp_msg_info->opcode = common_req->r_opcode & 0x7f; pcp_msg_info->opcode = common_req[1] & 0x7f;
pcp_msg_info->lifetime = ntohl(common_req->req_lifetime); pcp_msg_info->lifetime = READNU32(common_req + 4);
pcp_msg_info->int_ip = &common_req->ip; pcp_msg_info->int_ip = (struct in6_addr *)(common_req + 8);
pcp_msg_info->mapped_ip = &common_req->ip; 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; pcp_msg_info->result_code = PCP_ERR_UNSUPP_VERSION;
return 1; return 1;
} }
@ -233,40 +233,40 @@ static int parseCommonRequestHeader(const pcp_request_t *common_req, pcp_info_t
} }
#ifdef DEBUG #ifdef DEBUG
static void printMAPOpcodeVersion1(const pcp_map_v1_t *map_buf) static void printMAPOpcodeVersion1(const uint8_t *buf)
{ {
char map_addr[INET6_ADDRSTRLEN]; char map_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP MAP: v1 Opcode specific information. \n"); 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 protocol: \t\t %d\n", (int)buf[0] );
syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", ntohs(map_buf->int_port) ); syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", (int)READNU16(buf+4));
syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", ntohs(map_buf->ext_port) ); 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, 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]; char map_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP MAP: v2 Opcode specific information."); syslog(LOG_DEBUG, "PCP MAP: v2 Opcode specific information.");
syslog(LOG_DEBUG, "MAP nonce: \t%08x%08x%08x", syslog(LOG_DEBUG, "MAP nonce: \t%08x%08x%08x",
map_buf->nonce[0], map_buf->nonce[1], map_buf->nonce[2]); READNU32(buf), READNU32(buf+4), READNU32(buf+8));
syslog(LOG_DEBUG, "MAP protocol:\t%d", map_buf->protocol); syslog(LOG_DEBUG, "MAP protocol:\t%d", (int)buf[12]);
syslog(LOG_DEBUG, "MAP int port:\t%d", ntohs(map_buf->int_port)); syslog(LOG_DEBUG, "MAP int port:\t%d", (int)READNU16(buf+16));
syslog(LOG_DEBUG, "MAP ext port:\t%d", ntohs(map_buf->ext_port)); syslog(LOG_DEBUG, "MAP ext port:\t%d", (int)READNU16(buf+18));
syslog(LOG_DEBUG, "MAP Ext IP: \t%s", inet_ntop(AF_INET6, 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 */ #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_info_t *pcp_msg_info)
{ {
pcp_msg_info->is_map_op = 1; pcp_msg_info->is_map_op = 1;
pcp_msg_info->protocol = map_v1->protocol; pcp_msg_info->protocol = map_v1[0];
pcp_msg_info->int_port = ntohs(map_v1->int_port); pcp_msg_info->int_port = READNU16(map_v1 + 4);
pcp_msg_info->ext_port = ntohs(map_v1->ext_port); 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."); syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value.");
@ -276,16 +276,16 @@ static int parsePCPMAP_version1(const pcp_map_v1_t *map_v1,
return 0; 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_info_t *pcp_msg_info)
{ {
pcp_msg_info->is_map_op = 1; pcp_msg_info->is_map_op = 1;
memcpy(pcp_msg_info->nonce, map_v2->nonce, 12); memcpy(pcp_msg_info->nonce, map_v2, 12);
pcp_msg_info->protocol = map_v2->protocol; pcp_msg_info->protocol = map_v2[12];
pcp_msg_info->int_port = ntohs(map_v2->int_port); pcp_msg_info->int_port = READNU16(map_v2 + 16);
pcp_msg_info->ext_port = ntohs(map_v2->ext_port); 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 ) { 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."); 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 PCP_PEER
#ifdef DEBUG #ifdef DEBUG
static void printPEEROpcodeVersion1(pcp_peer_v1_t *peer_buf) static void printPEEROpcodeVersion1(const uint8_t *buf)
{ {
char ext_addr[INET6_ADDRSTRLEN]; char ext_addr[INET6_ADDRSTRLEN];
char peer_addr[INET6_ADDRSTRLEN]; char peer_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP PEER: v1 Opcode specific information. \n"); syslog(LOG_DEBUG, "PCP PEER: v1 Opcode specific information. \n");
syslog(LOG_DEBUG, "Protocol: \t\t %d\n",peer_buf->protocol ); syslog(LOG_DEBUG, "Protocol: \t\t %d\n", (int)buf[0]);
syslog(LOG_DEBUG, "Internal port: \t\t %d\n", ntohs(peer_buf->int_port) ); 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, &peer_buf->ext_ip, syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, buf + 8,
ext_addr,INET6_ADDRSTRLEN)); ext_addr,INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "External port port: \t\t %d\n", ntohs(peer_buf->ext_port) ); 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, &peer_buf->peer_ip, syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, buf + 28,
peer_addr,INET6_ADDRSTRLEN)); 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 ext_addr[INET6_ADDRSTRLEN];
char peer_addr[INET6_ADDRSTRLEN]; char peer_addr[INET6_ADDRSTRLEN];
syslog(LOG_DEBUG, "PCP PEER: v2 Opcode specific information."); syslog(LOG_DEBUG, "PCP PEER: v2 Opcode specific information.");
syslog(LOG_DEBUG, "nonce: \t%08x%08x%08x", syslog(LOG_DEBUG, "nonce: \t%08x%08x%08x",
peer_buf->nonce[0], peer_buf->nonce[1], peer_buf->nonce[2]); READNU32(buf), READNU32(buf+4), READNU32(buf+8));
syslog(LOG_DEBUG, "Protocol: \t%d",peer_buf->protocol ); syslog(LOG_DEBUG, "Protocol: \t%d", buf[12]);
syslog(LOG_DEBUG, "Internal port:\t%d", ntohs(peer_buf->int_port) ); syslog(LOG_DEBUG, "Internal port:\t%d", READNU16(buf + 16));
syslog(LOG_DEBUG, "External IP: \t%s", inet_ntop(AF_INET6, &peer_buf->ext_ip, syslog(LOG_DEBUG, "External IP: \t%s", inet_ntop(AF_INET6, buf + 20,
ext_addr, INET6_ADDRSTRLEN)); ext_addr, INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "External port:\t%d", ntohs(peer_buf->ext_port) ); syslog(LOG_DEBUG, "External port:\t%d", READNU16(buf + 18));
syslog(LOG_DEBUG, "PEER IP: \t%s", inet_ntop(AF_INET6, &peer_buf->peer_ip, syslog(LOG_DEBUG, "PEER IP: \t%s", inet_ntop(AF_INET6, buf + 40,
peer_addr, INET6_ADDRSTRLEN)); peer_addr, INET6_ADDRSTRLEN));
syslog(LOG_DEBUG, "PEER port: \t%d", ntohs(peer_buf->peer_port) ); syslog(LOG_DEBUG, "PEER port: \t%d", READNU16(buf + 36));
} }
#endif /* DEBUG */ #endif /* DEBUG */
@ -336,17 +336,17 @@ static void printPEEROpcodeVersion2(pcp_peer_v2_t *peer_buf)
* Function extracting information from peer_buf to pcp_msg_info * Function extracting information from peer_buf to pcp_msg_info
* @return : when no problem occurred 0 is returned, 1 otherwise * @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_info_t *pcp_msg_info)
{ {
pcp_msg_info->is_peer_op = 1; pcp_msg_info->is_peer_op = 1;
pcp_msg_info->protocol = peer_buf->protocol; pcp_msg_info->protocol = buf[0];
pcp_msg_info->int_port = ntohs(peer_buf->int_port); pcp_msg_info->int_port = READNU16(buf + 4);
pcp_msg_info->ext_port = ntohs(peer_buf->ext_port); pcp_msg_info->ext_port = READNU16(buf + 6);
pcp_msg_info->peer_port = ntohs(peer_buf->peer_port); pcp_msg_info->peer_port = READNU16(buf + 24);
pcp_msg_info->ext_ip = &peer_buf->ext_ip; pcp_msg_info->ext_ip = (struct in6_addr *)(buf + 8);
pcp_msg_info->peer_ip = &peer_buf->peer_ip; 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."); syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value.");
@ -360,18 +360,17 @@ static int parsePCPPEER_version1(pcp_peer_v1_t *peer_buf, \
* Function extracting information from peer_buf to pcp_msg_info * Function extracting information from peer_buf to pcp_msg_info
* @return : when no problem occurred 0 is returned, 1 otherwise * @return : when no problem occurred 0 is returned, 1 otherwise
*/ */
static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \ static int parsePCPPEER_version2(const uint8_t *buf, pcp_info_t *pcp_msg_info)
pcp_info_t *pcp_msg_info)
{ {
pcp_msg_info->is_peer_op = 1; pcp_msg_info->is_peer_op = 1;
memcpy(pcp_msg_info->nonce, peer_buf->nonce, 12); memcpy(pcp_msg_info->nonce, buf, 12);
pcp_msg_info->protocol = peer_buf->protocol; pcp_msg_info->protocol = buf[12];
pcp_msg_info->int_port = ntohs(peer_buf->int_port); pcp_msg_info->int_port = READNU16(buf + 16);
pcp_msg_info->ext_port = ntohs(peer_buf->ext_port); pcp_msg_info->ext_port = READNU16(buf + 18);
pcp_msg_info->peer_port = ntohs(peer_buf->peer_port); pcp_msg_info->peer_port = READNU16(buf + 36);
pcp_msg_info->ext_ip = &peer_buf->ext_ip; pcp_msg_info->ext_ip = (struct in6_addr *)(buf + 20);
pcp_msg_info->peer_ip = &peer_buf->peer_ip; 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."); syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value.");
@ -384,110 +383,89 @@ static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \
#ifdef PCP_SADSCP #ifdef PCP_SADSCP
#ifdef DEBUG #ifdef DEBUG
static void printSADSCPOpcode(pcp_sadscp_req_t *sadscp) { static void printSADSCPOpcode(const uint8_t *buf)
{
unsigned char sadscp_tol; 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, "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, "Loss tolerance %d \n", (sadscp_tol>>4)&3);
syslog(LOG_DEBUG, "Jitter tolerance %d \n", (sadscp_tol>>2)&3); syslog(LOG_DEBUG, "Jitter tolerance %d \n", (sadscp_tol>>2)&3);
syslog(LOG_DEBUG, "RRR %d \n", sadscp_tol&3); syslog(LOG_DEBUG, "RRR %d \n", sadscp_tol&3);
syslog(LOG_DEBUG, "AppName Length %d \n", sadscp->app_name_length); syslog(LOG_DEBUG, "AppName Length %d \n", buf[13]);
if (sadscp->app_name) { syslog(LOG_DEBUG, "Application name %.*s \n", buf[13], buf + 14);
syslog(LOG_DEBUG, "Application name %.*s \n", sadscp->app_name_length,
sadscp->app_name);
}
} }
#endif //DEBUG #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; if (pcp_msg_info->delay_tolerance == 3 ||
pcp_msg_info->loss_tolerance = (sadscp->tolerance_fields>>4)&3; pcp_msg_info->loss_tolerance == 3 ||
pcp_msg_info->jitter_tolerance = (sadscp->tolerance_fields>>2)&3; pcp_msg_info->jitter_tolerance == 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 ) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return 1; return 1;
} }
pcp_msg_info->app_name = sadscp->app_name; pcp_msg_info->app_name = (const char *)(buf + 14);
pcp_msg_info->app_name_len = sadscp->app_name_length; pcp_msg_info->app_name_len = buf[13];
return 0; 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 #ifdef DEBUG
char third_addr[INET6_ADDRSTRLEN]; char third_addr[INET6_ADDRSTRLEN];
#endif #endif /* DEBUG */
unsigned short option_length; 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. */ /* 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; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0; return 0;
} }
option_length = ntohs(opt_hdr->len) + 4; option_length = READNU16(pcp_buf + 2) + 4; /* len */
if (remain < option_length) { if (remain < option_length) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0; return 0;
} }
switch (opt_hdr->code) { switch (pcp_buf[0]) { /* code */
case PCP_OPTION_3RD_PARTY: case PCP_OPTION_3RD_PARTY:
opt_3rd = (pcp_3rd_party_option_t*)pcp_buf; if (option_length != PCP_3RD_PARTY_OPTION_SIZE) {
if ( option_length != sizeof(*opt_3rd) ) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0; return 0;
} }
#ifdef DEBUG #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, 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 #endif
if (pcp_msg_info->thirdp_ip ) { if (pcp_msg_info->thirdp_ip ) {
syslog(LOG_ERR, "PCP: THIRD PARTY OPTION was already present. \n"); syslog(LOG_ERR, "PCP: THIRD PARTY OPTION was already present. \n");
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0; return 0;
} } else {
else { pcp_msg_info->thirdp_ip = (struct in6_addr *)(pcp_buf + 4);
pcp_msg_info->thirdp_ip = &opt_3rd->ip; pcp_msg_info->mapped_ip = (struct in6_addr *)(pcp_buf + 4);
pcp_msg_info->mapped_ip = &opt_3rd->ip;
} }
break; break;
case PCP_OPTION_PREF_FAIL: case PCP_OPTION_PREF_FAIL:
opt_prefail = (pcp_prefer_fail_option_t*)pcp_buf; if (option_length != PCP_PREFER_FAIL_OPTION_SIZE) {
if ( option_length != sizeof(*opt_prefail) ) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0; return 0;
} }
@ -501,17 +479,14 @@ static int parsePCPOption(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info)
if (pcp_msg_info->pfailure_present != 0 ) { 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; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
} } else {
else {
pcp_msg_info->pfailure_present = 1; pcp_msg_info->pfailure_present = 1;
} }
break; break;
case PCP_OPTION_FILTER: case PCP_OPTION_FILTER:
/* TODO fully implement filter */ /* TODO fully implement filter */
opt_filter = (pcp_filter_option_t*)pcp_buf; if (option_length != PCP_FILTER_OPTION_SIZE) {
if ( option_length != sizeof(*opt_filter) ) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0; return 0;
} }
@ -531,28 +506,26 @@ static int parsePCPOption(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info)
#ifdef DEBUG #ifdef DEBUG
syslog(LOG_DEBUG, "PCP OPTION: \t Flow priority\n"); syslog(LOG_DEBUG, "PCP OPTION: \t Flow priority\n");
#endif #endif
opt_flp = (pcp_flow_priority_option_t*)pcp_buf; if (option_length != PCP_FLOW_PRIORITY_OPTION_SIZE) {
if ( option_length != sizeof (*opt_flp) ) {
syslog(LOG_ERR, "PCP: Error processing DSCP. sizeof %d and remaining %d. flow len %d \n", 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); PCP_FLOW_PRIORITY_OPTION_SIZE, remain, READNU16(pcp_buf + 2));
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return 0; return 0;
} }
#ifdef DEBUG #ifdef DEBUG
syslog(LOG_DEBUG, "DSCP UP: \t %d \n", opt_flp->dscp_up); syslog(LOG_DEBUG, "DSCP UP: \t %d\n", pcp_buf[4]);
syslog(LOG_DEBUG, "DSCP DOWN: \t %d \n", opt_flp->dscp_down); syslog(LOG_DEBUG, "DSCP DOWN: \t %d\n", pcp_buf[5]);
#endif #endif
pcp_msg_info->dscp_up = opt_flp->dscp_up; pcp_msg_info->dscp_up = pcp_buf[4];
pcp_msg_info->dscp_down = opt_flp->dscp_down; pcp_msg_info->dscp_down = pcp_buf[5];
pcp_msg_info->flowp_present = 1; pcp_msg_info->flowp_present = 1;
break; break;
#endif #endif
default: default:
if (opt_hdr->code < 128) { if (pcp_buf[0] < 128) {
syslog(LOG_ERR, "PCP: Unrecognized mandatory PCP OPTION: %d \n", opt_hdr->code); syslog(LOG_ERR, "PCP: Unrecognized mandatory PCP OPTION: %d \n", (int)pcp_buf[0]);
/* Mandatory to understand */ /* Mandatory to understand */
pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION; pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION;
remain = 0; remain = 0;
@ -1224,17 +1197,8 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info)
{ {
int remainingSize; int remainingSize;
const pcp_map_v1_t* map_v1; /* start with PCP_SUCCESS as result code,
const pcp_map_v2_t* map_v2; * if everything is OK value will be unchanged */
#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 */
pcp_msg_info->result_code = PCP_SUCCESS; pcp_msg_info->result_code = PCP_SUCCESS;
remainingSize = req_size; 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 */ /* first parse request header */
if (parseCommonRequestHeader((pcp_request_t*)req, pcp_msg_info) ) { if (parseCommonRequestHeader(req, pcp_msg_info) ) {
return 1; return 1;
} }
remainingSize -= sizeof(pcp_request_t); remainingSize -= PCP_COMMON_REQUEST_SIZE;
req += sizeof(pcp_request_t); req += PCP_COMMON_REQUEST_SIZE;
if (pcp_msg_info->version == 1) { if (pcp_msg_info->version == 1) {
/* legacy PCP version 1 support */ /* legacy PCP version 1 support */
switch (pcp_msg_info->opcode) { switch (pcp_msg_info->opcode) {
case PCP_OPCODE_MAP: case PCP_OPCODE_MAP:
remainingSize -= sizeof(pcp_map_v1_t); remainingSize -= PCP_MAP_V1_SIZE;
if (remainingSize < 0) { if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
map_v1 = (pcp_map_v1_t*)req;
#ifdef DEBUG #ifdef DEBUG
printMAPOpcodeVersion1(map_v1); printMAPOpcodeVersion1(req);
#endif /* DEBUG */ #endif /* DEBUG */
if ( parsePCPMAP_version1(map_v1, pcp_msg_info) ) { if ( parsePCPMAP_version1(req, pcp_msg_info) ) {
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
req += sizeof(pcp_map_v1_t); req += PCP_MAP_V1_SIZE;
parsePCPOptions(req, remainingSize, pcp_msg_info); parsePCPOptions(req, remainingSize, pcp_msg_info);
if (ValidatePCPMsg(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 #ifdef PCP_PEER
case PCP_OPCODE_PEER: case PCP_OPCODE_PEER:
remainingSize -= sizeof(pcp_peer_v1_t); remainingSize -= PCP_PEER_V1_SIZE;
if (remainingSize < 0) { if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
peer_v1 = (pcp_peer_v1_t*)req;
#ifdef DEBUG #ifdef DEBUG
printPEEROpcodeVersion1(peer_v1); printPEEROpcodeVersion1(req);
#endif /* DEBUG */ #endif /* DEBUG */
if ( parsePCPPEER_version1(peer_v1, pcp_msg_info) ) { if ( parsePCPPEER_version1(req, pcp_msg_info) ) {
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
req += sizeof(pcp_peer_v1_t); req += PCP_PEER_V1_SIZE;
parsePCPOptions(req, remainingSize, pcp_msg_info); 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; break;
case PCP_OPCODE_MAP: case PCP_OPCODE_MAP:
remainingSize -= sizeof(pcp_map_v2_t); remainingSize -= PCP_MAP_V2_SIZE;
if (remainingSize < 0) { if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
map_v2 = (pcp_map_v2_t*)req;
#ifdef DEBUG #ifdef DEBUG
printMAPOpcodeVersion2(map_v2); printMAPOpcodeVersion2(req);
#endif /* DEBUG */ #endif /* DEBUG */
if (parsePCPMAP_version2(map_v2, pcp_msg_info) ) { if (parsePCPMAP_version2(req, pcp_msg_info) ) {
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
req += sizeof(pcp_map_v2_t); req += PCP_MAP_V2_SIZE;
parsePCPOptions(req, remainingSize, pcp_msg_info); 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 #ifdef PCP_PEER
case PCP_OPCODE_PEER: case PCP_OPCODE_PEER:
remainingSize -= sizeof(pcp_peer_v2_t); remainingSize -= PCP_PEER_V2_SIZE;
if (remainingSize < 0) { if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
peer_v2 = (pcp_peer_v2_t*)req;
#ifdef DEBUG #ifdef DEBUG
printPEEROpcodeVersion2(peer_v2); printPEEROpcodeVersion2(req);
#endif /* DEBUG */ #endif /* DEBUG */
parsePCPPEER_version2(peer_v2, pcp_msg_info); parsePCPPEER_version2(req, pcp_msg_info);
req += sizeof(pcp_peer_v2_t); req += PCP_PEER_V2_SIZE;
if (pcp_msg_info->result_code != 0) { if (pcp_msg_info->result_code != 0) {
return pcp_msg_info->result_code; 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 #ifdef PCP_SADSCP
case PCP_OPCODE_SADSCP: case PCP_OPCODE_SADSCP:
remainingSize -= sizeof(pcp_sadscp_req_t); remainingSize -= PCP_SADSCP_REQ_SIZE;
if (remainingSize < 0) { if (remainingSize < 0) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST;
return pcp_msg_info->result_code; return pcp_msg_info->result_code;
} }
sadscp = (pcp_sadscp_req_t*)req; remainingSize -= ((uint8_t *)req)[13]; /* app_name_length */
req += sizeof(pcp_sadscp_req_t); if (remainingSize < 0) {
if (sadscp->app_name_length > remainingSize) {
pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION;
return pcp_msg_info->result_code;
} }
#ifdef DEBUG #ifdef DEBUG
printSADSCPOpcode(sadscp); printSADSCPOpcode(req);
#endif #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; return pcp_msg_info->result_code;
} }
req += pcp_msg_info->app_name_len;
get_dscp_value(pcp_msg_info); 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) static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
{ {
pcp_response_t *resp = (pcp_response_t*)response; response[2] = 0; /* reserved */
memset(response + 12, 0, 12); /* reserved */
resp->reserved = 0;
resp->reserved1[0]=0;
resp->reserved1[1]=0;
resp->reserved1[2]=0;
if (pcp_msg_info->result_code == PCP_ERR_UNSUPP_VERSION ) { if (pcp_msg_info->result_code == PCP_ERR_UNSUPP_VERSION ) {
/* highest supported version */ /* highest supported version */
resp->ver = this_server_info.server_version; response[0] = this_server_info.server_version;
} else { } else {
resp->ver = pcp_msg_info->version; response[0] = pcp_msg_info->version;
} }
resp->r_opcode |= 0x80; response[1] |= 0x80; /* r_opcode */
resp->result_code = pcp_msg_info->result_code; response[3] = pcp_msg_info->result_code;
resp->epochtime = htonl(time(NULL) - startup_time); WRITENU32(response + 8, time(NULL) - startup_time); /* epochtime */
switch (pcp_msg_info->result_code) { switch (pcp_msg_info->result_code) {
/*long lifetime errors*/ /*long lifetime errors*/
case PCP_ERR_UNSUPP_VERSION: 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_ADDRESS_MISMATCH:
case PCP_ERR_CANNOT_PROVIDE_EXTERNAL: case PCP_ERR_CANNOT_PROVIDE_EXTERNAL:
case PCP_ERR_EXCESSIVE_REMOTE_PEERS: case PCP_ERR_EXCESSIVE_REMOTE_PEERS:
resp->lifetime = 0; WRITENU32(response + 4, 0); /* lifetime */
break; break;
case PCP_ERR_NETWORK_FAILURE: case PCP_ERR_NETWORK_FAILURE:
case PCP_ERR_NO_RESOURCES: case PCP_ERR_NO_RESOURCES:
case PCP_ERR_USER_EX_QUOTA: case PCP_ERR_USER_EX_QUOTA:
resp->lifetime = htonl(30); WRITENU32(response + 4, 30); /* lifetime */
break; break;
case PCP_SUCCESS: case PCP_SUCCESS:
default: default:
resp->lifetime = htonl(pcp_msg_info->lifetime); WRITENU32(response + 4, pcp_msg_info->lifetime); /* lifetime */
break; break;
} }
if (resp->r_opcode == 0x81) { /* MAP response */ if (response[1] == 0x81) { /* MAP response */
if (resp->ver == 1 ) { if (response[0] == 1) { /* version */
pcp_map_v1_t *mapr = (pcp_map_v1_t *)resp->next_data; WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 4, pcp_msg_info->int_port);
mapr->ext_ip = *pcp_msg_info->ext_ip; WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 6, pcp_msg_info->ext_port);
mapr->ext_port = htons(pcp_msg_info->ext_port); memcpy(response + PCP_COMMON_RESPONSE_SIZE + 8, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
mapr->int_port = htons(pcp_msg_info->int_port);
} }
else if (resp->ver == 2 ) { else if (response[0] == 2) {
pcp_map_v2_t *mapr = (pcp_map_v2_t *)resp->next_data; WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 16, pcp_msg_info->int_port);
mapr->ext_ip = *pcp_msg_info->ext_ip; WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 18, pcp_msg_info->ext_port);
mapr->ext_port = htons(pcp_msg_info->ext_port); memcpy(response + PCP_COMMON_RESPONSE_SIZE + 20, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
mapr->int_port = htons(pcp_msg_info->int_port);
} }
} }
#ifdef PCP_PEER #ifdef PCP_PEER
else if (resp->r_opcode == 0x82) { /* PEER response */ else if (response[1] == 0x82) { /* PEER response */
if (resp->ver == 1 ){ if (response[0] == 1) {
pcp_peer_v1_t* peer_resp = (pcp_peer_v1_t*)resp->next_data; WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 4, pcp_msg_info->int_port);
peer_resp->ext_port = htons(pcp_msg_info->ext_port); WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 6, pcp_msg_info->ext_port);
peer_resp->int_port = htons(pcp_msg_info->int_port); WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 24, pcp_msg_info->peer_port);
peer_resp->peer_port = htons(pcp_msg_info->peer_port); memcpy(response + PCP_COMMON_RESPONSE_SIZE + 8, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
peer_resp->ext_ip = *pcp_msg_info->ext_ip;
} }
else if (resp->ver == 2 ){ else if (response[0] == 2) {
pcp_peer_v2_t* peer_resp = (pcp_peer_v2_t*)resp->next_data; WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 16, pcp_msg_info->int_port);
peer_resp->ext_port = htons(pcp_msg_info->ext_port); WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 18, pcp_msg_info->ext_port);
peer_resp->int_port = htons(pcp_msg_info->int_port); WRITENU16(response + PCP_COMMON_RESPONSE_SIZE + 36, pcp_msg_info->peer_port);
peer_resp->peer_port = htons(pcp_msg_info->peer_port); memcpy(response + PCP_COMMON_RESPONSE_SIZE + 20, pcp_msg_info->ext_ip, sizeof(struct in6_addr));
peer_resp->ext_ip = *pcp_msg_info->ext_ip;
} }
} }
#endif /* PCP_PEER */ #endif /* PCP_PEER */
#ifdef PCP_SADSCP #ifdef PCP_SADSCP
else if (resp->r_opcode == 0x83) { /*SADSCP response*/ else if (response[1] == 0x83) { /*SADSCP response*/
pcp_sadscp_resp_t *sadscp_resp = (pcp_sadscp_resp_t*)resp->next_data; response[PCP_COMMON_RESPONSE_SIZE + 12]
sadscp_resp->a_r_dscp_value = pcp_msg_info->matched_name<<7; = ((pcp_msg_info->matched_name<<7) & ~(1<<6)) |
sadscp_resp->a_r_dscp_value &= ~(1<<6); (pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK);
sadscp_resp->a_r_dscp_value |= (pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK); memset(response + PCP_COMMON_RESPONSE_SIZE + 13, 0, 3);
memset(sadscp_resp->reserved, 0, sizeof(sadscp_resp->reserved));
} }
#endif /* PCP_SADSCP */ #endif /* PCP_SADSCP */
} }