33#define _CRT_SECURE_NO_WARNINGS 1
49#include <sys/select.h>
53#include <netinet/in.h>
113#ifdef PCP_USE_IPV6_SOCKET
122 "Error occurred while creating a PCP socket.");
140 int fpresent_no_exit_state=0;
146 for (fiter=flow; fiter != NULL; fiter=fiter->
next_child) {
147 switch (fiter->
state) {
160 fpresent_no_exit_state=1;
166 if (fpresent_no_exit_state) {
175 }
else if (ffailed) {
189#ifdef PCP_SOCKET_IS_VOIDPTR
195 struct timeval tout_end;
196 struct timeval tout_select;
218 tout_end.tv_usec+=(timeout * 1000) % 1000000;
219 tout_end.tv_sec+=tout_end.tv_usec / 1000000;
220 tout_end.tv_usec=tout_end.tv_usec % 1000000;
221 tout_end.tv_sec+=timeout / 1000;
224 "Initialized wait for result of flow: %d, wait timeout %d ms",
241 if ((timeval_subtract(&tout_select, &tout_end, &ctv))
242 || ((tout_select.tv_sec == 0) && (tout_select.tv_usec == 0))
243 || (tout_select.tv_sec < 0)) {
253 if ((exit_on_partial_res)
261 FD_SET(fd, &read_fds);
264 "Executing select with fdmax=%d, timeout = %ld s; %ld us",
265 fdmax, tout_select.tv_sec, (
long int)tout_select.tv_usec);
267 ret_count=select(fdmax, &read_fds, NULL, NULL, &tout_select);
271 if (ret_count == -1) {
275 "select failed: %s", error);
276 }
else if (ret_count == 0) {
281 "select returned %d i/o events.", ret_count);
290 struct sockaddr *ext_addr)
294 struct timeval curtime;
339static int chain_and_assign_src_ip(
pcp_server_t *s,
void *data)
350 if ((IN6_IS_ADDR_UNSPECIFIED(
d->src_ip))
351 || (IN6_ARE_ADDR_EQUAL(
d->src_ip, (
struct in6_addr *) s->
src_ip))) {
354 memcpy(&
d->kd->src_ip, s->
src_ip,
sizeof(
d->kd->src_ip));
355 memcpy(&
d->kd->pcp_server_ip, s->
pcp_ip,
sizeof(
d->kd->pcp_server_ip));
356 memcpy(&
d->kd->nonce, &s->
nonce,
sizeof(
d->kd->nonce));
365 f->sadscp.toler_fields =
d->toler_fields;
367 f->sadscp.app_name_length = strlen(
d->app_name);
368 f->sadscp_app_name =
strdup(
d->app_name);
370 f->sadscp.app_name_length = 0;
371 f->sadscp_app_name = NULL;
375 init_flow(f, s,
d->lifetime,
d->ext_addr);
378 d->fprev->next_child=f;
390 struct sockaddr *dst_addr,
struct sockaddr *
ext_addr,
uint8_t protocol,
395 struct in6_addr src_ip;
396 struct sockaddr_storage tmp_ext_addr;
400 memset(&kd, 0,
sizeof(kd));
402 if ((!src_addr) || (!ctx)) {
410 switch (dst_addr->sa_family) {
412 if (((
struct sockaddr_in*)(dst_addr))->sin_addr.s_addr
418 if (IN6_IS_ADDR_UNSPECIFIED(
419 &((
struct sockaddr_in6 *)(dst_addr))->sin6_addr)) {
432 if (src_addr->sa_family == AF_INET) {
433 if (
S6_ADDR32(&src_ip)[3] == INADDR_ANY) {
434 findsaddr((
struct sockaddr_in*)dst_addr, &src_ip);
436 }
else if (IN6_IS_ADDR_UNSPECIFIED(&src_ip)) {
437 findsaddr6((
struct sockaddr_in6*)dst_addr, &src_ip);
438 }
else if (dst_addr->sa_family != src_addr->sa_family) {
440 "Socket family mismatch.");
450 struct sockaddr_in *te4=(
struct sockaddr_in *)&tmp_ext_addr;
451 struct sockaddr_in6 *te6=(
struct sockaddr_in6 *)&tmp_ext_addr;
452 tmp_ext_addr.ss_family=src_addr->sa_family;
453 switch (tmp_ext_addr.ss_family) {
455 memset(&te4->sin_addr, 0,
sizeof(te4->sin_addr));
459 memset(&te6->sin6_addr, 0,
sizeof(te6->sin6_addr));
464 "Unsupported address family.");
467 ext_addr=(
struct sockaddr *)&tmp_ext_addr;
493 for (fiter=f; fiter != NULL; fiter=fiter->
next_child) {
504 for (fiter=f; fiter != NULL; fiter=fiter->
next_child) {
516 for (fiter=f; fiter != NULL; fiter=fiter->
next_child) {
530 for (fiter=f; fiter != NULL; fiter=fiter->
next_child) {
537#ifdef PCP_EXPERIMENTAL
538int pcp_flow_set_userid(
pcp_flow_t *f, pcp_userid_option_p user)
542 for (fiter=f; fiter; fiter=fiter->
next_child) {
543 memcpy(&(fiter->f_userid.userid[0]), &(user->userid[0]),
MAX_USER_ID);
549int pcp_flow_set_location(
pcp_flow_t *f, pcp_location_option_p loc)
553 for (fiter=f; fiter; fiter=fiter->
next_child) {
554 memcpy(&(fiter->f_location.location[0]), &(
loc->location[0]),
MAX_GEO_STR);
561int pcp_flow_set_deviceid(
pcp_flow_t *f, pcp_deviceid_option_p dev)
565 for (fiter=f; fiter; fiter=fiter->
next_child) {
566 memcpy(&(fiter->f_deviceid.deviceid[0]), &(dev->deviceid[0]),
MAX_DEVICE_ID);
577 for (fiter=f; fiter!=NULL; fiter=fiter->
next_child) {
578 pcp_db_add_md(fiter, md_id, value, val_len);
584#ifdef PCP_FLOW_PRIORITY
589 for (fiter=f; fiter; fiter=fiter->
next_child) {
590 uint8_t fpresent = (dscp_up!=0)||(dscp_down!=0);
591 if (fiter->flowp_option_present != fpresent) {
592 fiter->flowp_option_present=fpresent;
595 fiter->flowp_dscp_up=dscp_up;
596 fiter->flowp_dscp_down=dscp_down;
603static inline void pcp_close_flow_intern(
pcp_flow_t *f)
630 for (fiter=f; fiter; fiter=fiter->
next_child) {
631 pcp_close_flow_intern(fiter);
651static int delete_flow_iter(
pcp_flow_t *f,
void *data)
654 pcp_close_flow_intern(f);
680 for (fiter=f; fiter; fiter=fiter->
next_child) {
690 for (fiter=f, info_iter=info_buf; fiter != NULL;
693 switch (fiter->
state) {
711 memcpy(&info_iter->
int_ip, &fiter->
kd.
src_ip,
sizeof(
struct in6_addr));
717 sizeof(info_iter->
dst_ip));
719 sizeof(info_iter->
ext_ip));
752 uint8_t jitter_tol,
char *app_name)
756 struct in6_addr src_ip=IN6ADDR_ANY_INIT;
758 memset(&data, 0 ,
sizeof(data));
759 memset(&kd, 0 ,
sizeof(kd));
769 data.toler_fields=(delay_tol&3)<<6 | ((loss_tol&3)<<4)
770 | ((jitter_tol&3)<<2);
771 data.app_name=app_name;
#define assert(condition)
#define PCP_MAX_SUPPORTED_VERSION
const char * findsaddr6(const struct sockaddr_in6 *to, struct in6_addr *from)
const char * findsaddr(const struct sockaddr_in *to, struct in6_addr *from)
@ pcp_state_short_lifetime_error
@ pcp_state_partial_result
int pcp_pulse(pcp_ctx_t *ctx, struct timeval *next_timeout)
int pcp_add_server(pcp_ctx_t *ctx, struct sockaddr *pcp_server, uint8_t pcp_version)
int pcp_eval_flow_state(pcp_flow_t *flow, pcp_fstate_e *fstate)
void pcp_flow_set_filter_opt(pcp_flow_t *f, struct sockaddr *filter_ip, uint8_t filter_prefix)
pcp_ctx_t * pcp_init(uint8_t autodiscovery, pcp_socket_vt_t *socket_vt)
void * pcp_flow_get_user_data(pcp_flow_t *f)
void pcp_flow_set_user_data(pcp_flow_t *f, void *userdata)
pcp_fstate_e pcp_wait(pcp_flow_t *flow, int timeout, int exit_on_partial_res)
void pcp_delete_flow(pcp_flow_t *f)
void pcp_close_flow(pcp_flow_t *f)
void pcp_flow_set_3rd_party_opt(pcp_flow_t *f, struct sockaddr *thirdp_addr)
pcp_flow_t * pcp_new_flow(pcp_ctx_t *ctx, struct sockaddr *src_addr, struct sockaddr *dst_addr, struct sockaddr *ext_addr, uint8_t protocol, uint32_t lifetime, void *userdata)
void pcp_flow_set_prefer_failure_opt(pcp_flow_t *f)
PCP_SOCKET pcp_get_socket(pcp_ctx_t *ctx)
void pcp_flow_set_lifetime(pcp_flow_t *f, uint32_t lifetime)
pcp_flow_info_t * pcp_flow_get_info(pcp_flow_t *f, size_t *info_count)
void pcp_terminate(pcp_ctx_t *ctx, int close_flows)
pcp_errno pcp_db_foreach_flow(pcp_ctx_t *ctx, pcp_db_flow_iterate f, void *data)
pcp_errno pcp_db_add_flow(pcp_flow_t *f)
pcp_errno pcp_db_foreach_server(pcp_ctx_t *ctx, pcp_db_server_iterate f, void *data)
pcp_flow_t * pcp_create_flow(pcp_server_t *s, struct flow_key_data *fkd)
void pcp_db_free_pcp_servers(pcp_ctx_t *ctx)
pcp_errno pcp_delete_flow_intern(pcp_flow_t *f)
void pcp_flow_updated(pcp_flow_t *f)
@ pfs_wait_for_lifetime_renew
@ pfs_wait_after_short_life_error
@ pfs_wait_for_server_init
int gettimeofday(struct timeval *tv, struct timezone *tz)
void pcp_strerror(int errnum, char *buf, size_t buflen)
void pcp_logger_init(void)
#define PCP_LOG_END(level)
#define PCP_LOG_BEGIN(level)
#define PCP_LOG_FLOW(f, msg)
#define PCP_LOG(level, fmt,...)
#define PCP_OPCODE_SADSCP
pcp_errno psd_add_pcp_server(pcp_ctx_t *ctx, struct sockaddr *sa, uint8_t version)
void psd_add_gws(pcp_ctx_t *ctx)
void pcp_fill_in6_addr(struct in6_addr *dst_ip6, uint16_t *dst_port, struct sockaddr *src)
int pcp_socket_close(struct pcp_ctx_s *ctx)
pcp_socket_vt_t default_socket_vt
PCP_SOCKET pcp_socket_create(struct pcp_ctx_s *ctx, int domain, int type, int protocol)
#define PCP_INVALID_SOCKET
struct flow_key_data * kd
struct sockaddr * ext_addr
struct flow_key_data::mp_keydata map_peer
struct in6_addr pcp_server_ip
pcp_socket_vt_t * virt_socket_tb
struct in6_addr pcp_server_ip
uint8_t third_party_option_present
uint8_t filter_option_present
struct pcp_flow_s * next_child
struct in6_addr third_party_ip
struct in6_addr filter_ip
struct pcp_flow_s::@6::@8 map_peer
uint8_t pfailure_option_present
struct timeval next_timeout
pcp_server_state_e server_state