pcp_errno psd_add_pcp_server(pcp_ctx_t *ctx, struct sockaddr *sa, uint8_t version) { struct in6_addr pcp_ip=IN6ADDR_ANY_INIT; uint16_t pcp_port; uint32_t scope_id=0; pcp_server_t *pcps=NULL; PCP_LOG_BEGIN(PCP_LOGLVL_DEBUG); if (sa->sa_family == AF_INET) { S6_ADDR32(&pcp_ip)[0]=0; S6_ADDR32(&pcp_ip)[1]=0; S6_ADDR32(&pcp_ip)[2]=htonl(0xFFFF); S6_ADDR32(&pcp_ip)[3]=((struct sockaddr_in *)sa)->sin_addr.s_addr; pcp_port=((struct sockaddr_in *)sa)->sin_port; } else { IPV6_ADDR_COPY(&pcp_ip, &((struct sockaddr_in6*)sa)->sin6_addr); pcp_port=((struct sockaddr_in6 *)sa)->sin6_port; scope_id=((struct sockaddr_in6 *)sa)->sin6_scope_id; } if (!pcp_port) { pcp_port=ntohs(PCP_SERVER_PORT); } pcps=get_pcp_server_by_ip(ctx, (struct in6_addr *)&pcp_ip); if (!pcps) { int pcps_indx=pcp_new_server(ctx, &pcp_ip, pcp_port, scope_id); if (pcps_indx >= 0) { pcps=get_pcp_server(ctx, pcps_indx); } if (pcps == NULL) { PCP_LOG(PCP_LOGLVL_ERR, "%s", "Can't add PCP server.\n"); PCP_LOG_END(PCP_LOGLVL_DEBUG); return PCP_ERR_UNKNOWN; } } else { pcps->pcp_port=pcp_port; } pcps->pcp_version=version; pcps->server_state=pss_allocated; if (psd_fill_pcp_server_src(pcps)) { pcps->server_state=pss_unitialized; PCP_LOG(PCP_LOGLVL_INFO, "Failed to add PCP server %s", pcps->pcp_server_paddr); PCP_LOG_END(PCP_LOGLVL_DEBUG); return PCP_ERR_UNKNOWN; } PCP_LOG(PCP_LOGLVL_INFO, "Added PCP server %s", pcps->pcp_server_paddr); PCP_LOG_END(PCP_LOGLVL_DEBUG); return (pcp_errno)pcps->index; }
void psd_add_gws(pcp_ctx_t *ctx) { struct sockaddr_in6 *gws=NULL, *gw; int rcount=getgateways(&gws); gw=gws; for (; rcount > 0; rcount--, gw++) { int pcps_indx; if ((IN6_IS_ADDR_V4MAPPED(&gw->sin6_addr)) && (S6_ADDR32(&gw->sin6_addr)[3] == INADDR_ANY)) continue; if (IN6_IS_ADDR_UNSPECIFIED(&gw->sin6_addr)) continue; if (get_pcp_server_by_ip(ctx, &gw->sin6_addr)) continue; pcps_indx=pcp_new_server(ctx, &gw->sin6_addr, ntohs(PCP_SERVER_PORT), gw->sin6_scope_id); if (pcps_indx >= 0) { pcp_server_t *s=get_pcp_server(ctx, pcps_indx); if (!s) continue; if (psd_fill_pcp_server_src(s)) { PCP_LOG(PCP_LOGLVL_ERR, "Failed to initialize gateway %s as a PCP server.", s?s->pcp_server_paddr:"NULL pointer!!!"); } else { PCP_LOG(PCP_LOGLVL_INFO, "Found gateway %s. " "Added as possible PCP server.", s?s->pcp_server_paddr:"NULL pointer!!!"); } } } free(gws); }
void *build_pcp_msg(pcp_flow_t *flow) { ssize_t ret=-1; pcp_server_t *pcp_server=NULL; pcp_request_t *req; // pointer used for referencing next data structure in linked list void *next_data=NULL; PCP_LOG_BEGIN(PCP_LOGLVL_DEBUG); if (!flow) { return NULL; } pcp_server=get_pcp_server(flow->ctx, flow->pcp_server_indx); if (!pcp_server) { return NULL; } if (!flow->pcp_msg_buffer) { flow->pcp_msg_buffer=(char*)calloc(1, PCP_MAX_LEN); if (flow->pcp_msg_buffer == NULL) { PCP_LOG(PCP_LOGLVL_ERR, "%s", "Malloc can't allocate enough memory for the pcp_flow."); PCP_LOG_END(PCP_LOGLVL_DEBUG); return NULL; } } req=(pcp_request_t *)flow->pcp_msg_buffer; if (pcp_server->pcp_version == 0) { // NATPMP #ifndef PCP_DISABLE_NATPMP ret=build_natpmp_msg(flow); #endif } else { req->ver=pcp_server->pcp_version; req->r_opcode|=(uint8_t)(flow->kd.operation & 0x7f); //set opcode req->req_lifetime=htonl((uint32_t)flow->lifetime); memcpy(&req->ip, &flow->kd.src_ip, 16); // next data in the packet next_data=req->next_data; flow->pcp_msg_len=(uint8_t *)next_data - (uint8_t *)req; switch (flow->kd.operation) { case PCP_OPCODE_PEER: ret=build_pcp_peer(pcp_server, flow, next_data); break; case PCP_OPCODE_MAP: ret=build_pcp_map(pcp_server, flow, next_data); break; #ifdef PCP_SADSCP case PCP_OPCODE_SADSCP: ret=build_pcp_sadscp(pcp_server, flow, next_data); break; #endif case PCP_OPCODE_ANNOUNCE: ret=0; break; } } if (ret < 0) { PCP_LOG(PCP_LOGLVL_ERR, "%s", "Unsupported operation."); free(flow->pcp_msg_buffer); flow->pcp_msg_buffer=NULL; flow->pcp_msg_len=0; req=NULL; } PCP_LOG_END(PCP_LOGLVL_DEBUG); return req; }
int main(void) { pcp_ctx_t * ctx; pcp_log_level = PCP_DEBUG_NONE; PD_SOCKET_STARTUP(); ctx = pcp_init(0, NULL); #ifndef PCP_DISABLE_NATPMP { // TEST NATPMP - parsing nat_pmp_announce_resp_t natpmp_a; nat_pmp_map_resp_t natpmp_mt; nat_pmp_map_resp_t natpmp_mu; pcp_recv_msg_t msg; natpmp_a.ver = 0; natpmp_a.opcode = 0; natpmp_a.result = htons(11); natpmp_a.epoch = htonl(1234); natpmp_a.ext_ip = 0x01020304; natpmp_mt.ver = 0; natpmp_mt.opcode = NATPMP_OPCODE_MAP_TCP; natpmp_mt.result = htons(11); natpmp_mt.epoch = htonl(1234); natpmp_mt.ext_port = htons(1234); natpmp_mt.int_port = htons(3456); natpmp_mt.lifetime = htonl(2233); natpmp_mu.ver = 0; natpmp_mu.opcode = NATPMP_OPCODE_MAP_UDP; natpmp_mu.result = htons(11); natpmp_mu.epoch = htonl(1234); natpmp_mu.ext_port = htons(1234); natpmp_mu.int_port = htons(3456); natpmp_mu.lifetime = htonl(2233); memset(&msg,0,sizeof(msg)); memcpy(&msg.pcp_msg_buffer, &natpmp_a, sizeof(natpmp_a)); msg.pcp_msg_len = sizeof(natpmp_a); TEST(parse_response(&msg)==PCP_ERR_SUCCESS); TEST(msg.recv_version==0); TEST(msg.recv_epoch==1234); TEST(msg.recv_result==11); msg.pcp_msg_len = sizeof(natpmp_a)-1; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); natpmp_a.ver++; memset(&msg,0,sizeof(msg)); memcpy(&msg.pcp_msg_buffer, &natpmp_a, sizeof(natpmp_a)); msg.pcp_msg_len = sizeof(natpmp_a); TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); msg.pcp_msg_len = sizeof(pcp_response_t); TEST(parse_response(&msg)==PCP_ERR_SUCCESS); TEST(msg.recv_version==1); TEST(msg.recv_result==11); natpmp_a.ver++; memset(&msg,0,sizeof(msg)); memcpy(&msg.pcp_msg_buffer, &natpmp_a, sizeof(natpmp_a)); msg.pcp_msg_len = sizeof(natpmp_a); TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); msg.pcp_msg_len = sizeof(pcp_response_t); TEST(parse_response(&msg)==PCP_ERR_SUCCESS); TEST(msg.recv_version==2); TEST(msg.recv_result==11); memset(&msg,0,sizeof(msg)); memcpy(&msg.pcp_msg_buffer, &natpmp_mt, sizeof(natpmp_mt)); msg.pcp_msg_len = sizeof(natpmp_mt); TEST(parse_response(&msg)==PCP_ERR_SUCCESS); TEST(msg.assigned_ext_port==htons(1234)); TEST(msg.kd.map_peer.src_port==htons(3456)); TEST(msg.kd.map_peer.protocol==IPPROTO_TCP); TEST(msg.recv_version==0); TEST(msg.recv_epoch==1234); TEST(msg.recv_lifetime==2233); TEST(msg.recv_result==11); memset(&msg,0,sizeof(msg)); memcpy(&msg.pcp_msg_buffer, &natpmp_mu, sizeof(natpmp_mu)); msg.pcp_msg_len = sizeof(natpmp_mu); TEST(parse_response(&msg)==PCP_ERR_SUCCESS); TEST(msg.assigned_ext_port==htons(1234)); TEST(msg.kd.map_peer.src_port==htons(3456)); TEST(msg.kd.map_peer.protocol==IPPROTO_UDP); TEST(msg.recv_version==0); TEST(msg.recv_epoch==1234); TEST(msg.recv_lifetime==2233); TEST(msg.recv_result==11); msg.pcp_msg_len = sizeof(natpmp_mu)-1; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); natpmp_mu.opcode=3; memset(&msg,0,sizeof(msg)); memcpy(&msg.pcp_msg_buffer, &natpmp_mu, sizeof(natpmp_mu)); msg.pcp_msg_len = sizeof(natpmp_mu); TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); } #endif { // TEST validate MSG pcp_recv_msg_t msg; pcp_response_t* resp = (pcp_response_t*)msg.pcp_msg_buffer; memset(&msg, 0, sizeof(msg)); resp->r_opcode=0x81; resp->ver=1; msg.pcp_msg_len=sizeof(pcp_response_t); TEST(validate_pcp_msg(&msg)); msg.pcp_msg_len=sizeof(pcp_response_t)-1; TEST(!validate_pcp_msg(&msg)); msg.pcp_msg_len=sizeof(pcp_response_t)-4; TEST(validate_pcp_msg(&msg)); msg.pcp_msg_len=1104; TEST(!validate_pcp_msg(&msg)); msg.pcp_msg_len=0; TEST(!validate_pcp_msg(&msg)); msg.pcp_msg_len=sizeof(pcp_response_t); resp->ver=2; TEST(validate_pcp_msg(&msg)); resp->ver=3; TEST(!validate_pcp_msg(&msg)); resp->ver=2; resp->r_opcode=0x1; TEST(!validate_pcp_msg(&msg)); resp->r_opcode=0x7f; TEST(!validate_pcp_msg(&msg)); resp->r_opcode=0x81; msg.pcp_msg_len=sizeof(pcp_response_t)-1; resp->ver=1; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->ver=2; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->r_opcode=0x82; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->ver=1; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->r_opcode=0x83; resp->ver=2; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->r_opcode=0x81; msg.pcp_msg_len=sizeof(pcp_response_t)+1; resp->ver=1; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->ver=2; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->r_opcode=0x82; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->ver=1; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->r_opcode=0x83; resp->ver=2; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); msg.pcp_msg_len=sizeof(pcp_response_t); resp->r_opcode=0x84; resp->ver=2; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->ver=1; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); resp->ver=3; resp->r_opcode=0x82; TEST(parse_response(&msg)!=PCP_ERR_SUCCESS); } { //TEST build msg struct pcp_flow_s fs; pcp_server_t *s; memset(&fs, 0, sizeof(fs)); fs.ctx=ctx; TEST(build_pcp_msg(&fs)==NULL); fs.pcp_server_indx=pcp_add_server(ctx, Sock_pton("127.0.0.1"),1); s=get_pcp_server(ctx, fs.pcp_server_indx); fs.kd.operation = PCP_OPCODE_ANNOUNCE; TEST(build_pcp_msg(&fs)!=NULL); fs.kd.operation = 0x7f; TEST(build_pcp_msg(&fs)==NULL); fs.kd.operation = PCP_OPCODE_SADSCP; TEST(build_pcp_msg(&fs)==NULL); s->pcp_version = 3; TEST(build_pcp_msg(&fs)==NULL); fs.kd.operation = PCP_OPCODE_MAP; TEST(build_pcp_msg(&fs)==NULL); fs.kd.operation = PCP_OPCODE_PEER; TEST(build_pcp_msg(&fs)==NULL); s->pcp_version = 2; #ifdef PCP_EXPERIMENTAL { uint16_t i; pcp_db_add_md(&fs, 0, NULL,sizeof("string")); pcp_db_add_md(&fs, 1, "string", 0); for (i=2; i<256; ++i) { pcp_db_add_md(&fs, i, "string",sizeof("string")); } TEST(build_pcp_msg(&fs)!=NULL); TEST(fs.pcp_msg_len<=PCP_MAX_LEN); } #endif TEST(build_pcp_msg(NULL)==NULL); } PD_SOCKET_CLEANUP(); return 0; }
int main(void) { pcp_flow_t *f1, *f2; pcp_ctx_t *ctx; pcp_log_level = PCP_DEBUG_NONE; PD_SOCKET_STARTUP(); //test pcp_init & terminate ctx = pcp_init(DISABLE_AUTODISCOVERY, NULL); TEST(get_pcp_server(ctx, 0)==NULL); pcp_terminate(ctx, 1); ctx = pcp_init(ENABLE_AUTODISCOVERY, NULL); TEST(get_pcp_server(ctx, 0)!=NULL); pcp_terminate(ctx, 1); TEST(get_pcp_server(ctx, 0)==NULL); ctx = pcp_init(DISABLE_AUTODISCOVERY, NULL); TEST(pcp_add_server(ctx, Sock_pton("127.0.0.1:5351"), 2)==0); #ifdef PCP_USE_IPV6_SOCKET TEST(pcp_add_server(ctx, Sock_pton("[::1]:5351"), 1)==1); #endif pcp_terminate(ctx, 1); #ifdef PCP_SADSCP //TEST learn DSCP { pcp_flow_t* l1; ctx = pcp_init(DISABLE_AUTODISCOVERY, NULL); TEST((l1=pcp_learn_dscp(ctx, 1,1,1,NULL))==NULL); //NO PCP server to send req TEST(pcp_add_server(ctx, Sock_pton("127.0.0.1:5351"), 2)==0); TEST((l1=pcp_learn_dscp(ctx, 1,1,1,NULL))!=NULL); TEST(l1->kd.operation==PCP_OPCODE_SADSCP); TEST(l1->sadscp_app_name==NULL); TEST(l1->sadscp.app_name_length==0); TEST(l1->sadscp.toler_fields==84); pcp_close_flow(l1); pcp_delete_flow(l1); TEST((l1=pcp_learn_dscp(ctx, 2,2,2,"test"))!=NULL); TEST(l1->sadscp.app_name_length==4); TEST(strncmp(l1->sadscp_app_name,"test",l1->sadscp.app_name_length)==0); TEST(l1->sadscp.toler_fields==168); pcp_terminate(ctx, 1); } #endif ctx = pcp_init(DISABLE_AUTODISCOVERY, NULL); TEST(pcp_add_server(ctx, Sock_pton("127.0.0.1:5351"), 2)==0); TEST((pcp_new_flow(ctx, Sock_pton("[::1]:1234"), Sock_pton("[::1]"), NULL, IPPROTO_TCP, 100, NULL))==NULL); pcp_pulse(NULL, NULL); pcp_pulse(ctx, NULL); pcp_flow_get_info(NULL, NULL, NULL); //PCP PEER/MAP tests TEST(pcp_new_flow(NULL, NULL, NULL, NULL, 0, 0, NULL)==NULL); TEST(pcp_new_flow(ctx, NULL, NULL, NULL, 0, 0, NULL)==NULL); TEST((f1=pcp_new_flow(ctx, Sock_pton("127.0.0.1:1234"), Sock_pton("127.0.0.1"), NULL, IPPROTO_TCP, 100, NULL))!=NULL); TEST((f2=pcp_new_flow(ctx, Sock_pton("127.0.0.1:1234"), NULL, NULL, IPPROTO_TCP, 100, NULL))!=NULL); pcp_flow_set_prefer_failure_opt(f2); pcp_flow_set_prefer_failure_opt(f2); pcp_flow_set_lifetime(f1, 1000); TEST((f1->lifetime)>=99); TEST((f1->timeout.tv_sec>0)||(f1->timeout.tv_usec>0)); f1->timeout.tv_sec=0; f1->timeout.tv_usec=0; pcp_flow_set_lifetime(f1, 0); TEST(f1->lifetime==0); TEST((f1->timeout.tv_sec>0)||(f1->timeout.tv_usec>0)); pcp_set_3rd_party_opt(f1,NULL); printf("Tests succeeded.\n\n"); PD_SOCKET_CLEANUP(); return 0; }