Project Alice
Loading...
Searching...
No Matches
pcp_api.c
Go to the documentation of this file.
1/*
2 Copyright (c) 2014 by Cisco Systems, Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 1. Redistributions of source code must retain the above copyright notice, this
9 list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#else
29#include "default_config.h"
30#endif
31
32#ifdef _MSC_VER
33#define _CRT_SECURE_NO_WARNINGS 1
34#endif
35
36#include <assert.h>
37#include <stddef.h>
38#include <stdint.h>
39#include <stdlib.h>
40#include <string.h>
41#include <stdio.h>
42#include <errno.h>
43
44#ifdef WIN32
45#include <winsock2.h>
48#else
49#include <sys/select.h>
50#include <time.h>
51#include <sys/types.h>
52#include <unistd.h>
53#include <netinet/in.h>
54#include <netdb.h>
55#include <arpa/inet.h>
56#endif
57#include "pcp.h"
58#include "net/pcp_socket.h"
59#include "pcp_client_db.h"
60#include "pcp_logger.h"
61#include "pcp_event_handler.h"
62#include "pcp_utils.h"
64#include "net/findsaddr.h"
65
67{
68
69 return ctx ? ctx->socket : PCP_INVALID_SOCKET;
70}
71
72int pcp_add_server(pcp_ctx_t *ctx, struct sockaddr *pcp_server,
73 uint8_t pcp_version)
74{
75 int res;
76
78
79 if (!ctx) {
80 return PCP_ERR_BAD_ARGS;
81 }
82 if (pcp_version > PCP_MAX_SUPPORTED_VERSION) {
85 }
86
87 res=psd_add_pcp_server(ctx, pcp_server, pcp_version);
88
90 return res;
91}
92
93pcp_ctx_t *pcp_init(uint8_t autodiscovery, pcp_socket_vt_t *socket_vt)
94{
95 pcp_ctx_t *ctx=(pcp_ctx_t *)calloc(1, sizeof(pcp_ctx_t));
96
98
100
101 if (!ctx) {
103 return NULL;
104 }
105
106 if (socket_vt) {
107 ctx->virt_socket_tb=socket_vt;
108 } else {
110 }
111
112 ctx->socket=pcp_socket_create(ctx,
113#ifdef PCP_USE_IPV6_SOCKET
114 AF_INET6,
115#else
116 AF_INET,
117#endif
118 SOCK_DGRAM, 0);
119
120 if (ctx->socket == PCP_INVALID_SOCKET) {
122 "Error occurred while creating a PCP socket.");
123
125 return NULL;
126 }
127 PCP_LOG(PCP_LOGLVL_DEBUG, "%s", "Created a new PCP socket.");
128
129 if (autodiscovery)
130 psd_add_gws(ctx);
131
133 return ctx;
134}
135
137{
138 pcp_flow_t *fiter;
139 int nexit_states=0;
140 int fpresent_no_exit_state=0;
141 int fsuccess=0;
142 int ffailed=0;
143
145
146 for (fiter=flow; fiter != NULL; fiter=fiter->next_child) {
147 switch (fiter->state) {
149 fsuccess=1;
150 ++nexit_states;
151 break;
152 case pfs_failed:
153 ffailed=1;
154 ++nexit_states;
155 break;
157 ++nexit_states;
158 break;
159 default:
160 fpresent_no_exit_state=1;
161 break;
162 }
163 }
164
165 if (fstate) {
166 if (fpresent_no_exit_state) {
167 if (fsuccess) {
169 } else {
170 *fstate=pcp_state_processing;
171 }
172 } else {
173 if (fsuccess) {
174 *fstate=pcp_state_succeeded;
175 } else if (ffailed) {
176 *fstate=pcp_state_failed;
177 } else {
179 }
180 }
181 }
182
184 return nexit_states;
185}
186
187pcp_fstate_e pcp_wait(pcp_flow_t *flow, int timeout, int exit_on_partial_res)
188{
189#ifdef PCP_SOCKET_IS_VOIDPTR
190 return pcp_state_failed;
191#else
192 fd_set read_fds;
193 int fdmax;
194 PCP_SOCKET fd;
195 struct timeval tout_end;
196 struct timeval tout_select;
197 pcp_fstate_e fstate;
198 int nflow_exit_states=pcp_eval_flow_state(flow, &fstate);
199
201
202 if (!flow) {
203 PCP_LOG(PCP_LOGLVL_PERR, "Flow argument of %s function set to NULL!",
204 __FUNCTION__);
205 return pcp_state_failed;
206 }
207
208 switch (fstate) {
211 break;
212 default:
213 nflow_exit_states=0;
214 break;
215 }
216
217 gettimeofday(&tout_end, NULL);
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;
222
224 "Initialized wait for result of flow: %d, wait timeout %d ms",
225 flow->key_bucket, timeout);
226
227 FD_ZERO(&read_fds);
228
229 fd=pcp_get_socket(flow->ctx);
230 fdmax= (int)fd + 1;
231
232 // main loop
233 for (;;) {
234 int ret_count;
235 pcp_fstate_e ret_state;
236 struct timeval ctv;
237
238 OSDEP(ret_count);
239 // check expiration of wait timeout
240 gettimeofday(&ctv, NULL);
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)) {
245 }
246
247 //process all events and get timeout value for next select
248 pcp_pulse(flow->ctx, &tout_select);
249
250 // check flow for reaching one of exit from wait states
251 // (also handles case when flow is MAP for 0.0.0.0)
252 if (pcp_eval_flow_state(flow, &ret_state) > nflow_exit_states) {
253 if ((exit_on_partial_res)
254 || (ret_state != pcp_state_partial_result)) {
256 return ret_state;
257 }
258 }
259
260 FD_ZERO(&read_fds);
261 FD_SET(fd, &read_fds);
262
264 "Executing select with fdmax=%d, timeout = %ld s; %ld us",
265 fdmax, tout_select.tv_sec, (long int)tout_select.tv_usec);
266
267 ret_count=select(fdmax, &read_fds, NULL, NULL, &tout_select);
268
269 // check of select result // only for debug purposes
270#ifdef DEBUG
271 if (ret_count == -1) {
272 char error[ERR_BUF_LEN];
273 pcp_strerror(errno, error, sizeof(error));
275 "select failed: %s", error);
276 } else if (ret_count == 0) {
278 "select timed out");
279 } else {
281 "select returned %d i/o events.", ret_count);
282 }
283#endif
285 //return pcp_state_succeeded;
286#endif //PCP_SOCKET_IS_VOIDPTR
287}
288
289static inline void init_flow(pcp_flow_t *f, pcp_server_t *s, int lifetime,
290 struct sockaddr *ext_addr)
291{
293 if (f && s) {
294 struct timeval curtime;
295 f->ctx=s->ctx;
296
297 switch (f->kd.operation) {
298 case PCP_OPCODE_MAP:
299 case PCP_OPCODE_PEER:
301 ext_addr);
302 break;
303 default:
304 assert(!ext_addr);
305 break;
306 }
307
308 gettimeofday(&curtime, NULL);
309 f->lifetime=lifetime;
310 f->timeout=curtime;
311
312 if (s->server_state == pss_wait_io) {
313 f->state=pfs_send;
314 } else {
316 }
317
318 s->next_timeout=curtime;
319 f->user_data=NULL;
320
322 PCP_LOG_FLOW(f, "Added new flow");
323 }
325}
326
332 struct sockaddr *ext_addr;
333 struct in6_addr *src_ip;
335 char *app_name;
336 void *userdata;
337};
338
339static int chain_and_assign_src_ip(pcp_server_t *s, void *data)
340{
341 struct caasi_data *d=(struct caasi_data *)data;
342
344
345 if (s->server_state == pss_not_working) {
347 return 0;
348 }
349
350 if ((IN6_IS_ADDR_UNSPECIFIED(d->src_ip))
351 || (IN6_ARE_ADDR_EQUAL(d->src_ip, (struct in6_addr *) s->src_ip))) {
352 pcp_flow_t *f=NULL;
353
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));
357
358 f=pcp_create_flow(s, d->kd);
359 if (!f) {
361 return 1;
362 }
363#ifdef PCP_SADSCP
364 if (d->kd->operation == PCP_OPCODE_SADSCP) {
365 f->sadscp.toler_fields = d->toler_fields;
366 if (d->app_name) {
367 f->sadscp.app_name_length = strlen(d->app_name);
368 f->sadscp_app_name = strdup(d->app_name);
369 } else {
370 f->sadscp.app_name_length = 0;
371 f->sadscp_app_name = NULL;
372 }
373 }
374#endif
375 init_flow(f, s, d->lifetime, d->ext_addr);
376 f->user_data=d->userdata;
377 if (d->fprev) {
378 d->fprev->next_child=f;
379 } else {
380 d->ffirst=f;
381 }
382 d->fprev=f;
383 }
384
386 return 0;
387}
388
389pcp_flow_t *pcp_new_flow(pcp_ctx_t *ctx, struct sockaddr *src_addr,
390 struct sockaddr *dst_addr, struct sockaddr *ext_addr, uint8_t protocol,
392{
393 struct flow_key_data kd;
394 struct caasi_data data;
395 struct in6_addr src_ip;
396 struct sockaddr_storage tmp_ext_addr;
397
399
400 memset(&kd, 0, sizeof(kd));
401
402 if ((!src_addr) || (!ctx)) {
403 return NULL;
404 }
405 pcp_fill_in6_addr(&src_ip, &kd.map_peer.src_port, src_addr);
406
407 kd.map_peer.protocol=protocol;
408
409 if (dst_addr) {
410 switch (dst_addr->sa_family) {
411 case AF_INET:
412 if (((struct sockaddr_in*)(dst_addr))->sin_addr.s_addr
413 == INADDR_ANY) {
414 dst_addr=NULL;
415 }
416 break;
417 case AF_INET6:
418 if (IN6_IS_ADDR_UNSPECIFIED(
419 &((struct sockaddr_in6 *)(dst_addr))->sin6_addr)) {
420 dst_addr=NULL;
421 }
422 break;
423 default:
424 dst_addr=NULL;
425 break;
426 }
427 }
428
429 if (dst_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);
435 }
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.");
441
443 return NULL;
444 }
445 } else {
447 }
448
449 if (!ext_addr) {
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) {
454 case AF_INET:
455 memset(&te4->sin_addr, 0, sizeof(te4->sin_addr));
456 te4->sin_port=0;
457 break;
458 case AF_INET6:
459 memset(&te6->sin6_addr, 0, sizeof(te6->sin6_addr));
460 te6->sin6_port=0;
461 break;
462 default:
464 "Unsupported address family.");
465 return NULL;
466 }
467 ext_addr=(struct sockaddr *)&tmp_ext_addr;
468 }
469
470 data.fprev=NULL;
471 data.lifetime=lifetime;
472 data.ext_addr=ext_addr;
473 data.src_ip=&src_ip;
474 data.kd=&kd;
475 data.ffirst=NULL;
476 data.userdata=userdata;
477
478 if (pcp_db_foreach_server(ctx, chain_and_assign_src_ip, &data)
479 != PCP_ERR_MAX_SIZE) { // didn't iterate through each server => error happened
482 return NULL;
483 }
484
486 return data.ffirst;
487}
488
490{
491 pcp_flow_t *fiter;
492
493 for (fiter=f; fiter != NULL; fiter=fiter->next_child) {
494 fiter->lifetime=lifetime;
495
496 pcp_flow_updated(fiter);
497 }
498}
499
500void pcp_flow_set_3rd_party_opt(pcp_flow_t *f, struct sockaddr *thirdp_addr)
501{
502 pcp_flow_t *fiter;
503
504 for (fiter=f; fiter != NULL; fiter=fiter->next_child) {
506 pcp_fill_in6_addr(&fiter->third_party_ip, NULL, thirdp_addr);
507 pcp_flow_updated(fiter);
508 }
509}
510
511void pcp_flow_set_filter_opt(pcp_flow_t *f, struct sockaddr *filter_ip,
512 uint8_t filter_prefix)
513{
514 pcp_flow_t *fiter;
515
516 for (fiter=f; fiter != NULL; fiter=fiter->next_child) {
517 if (!fiter->filter_option_present) {
518 fiter->filter_option_present=1;
519 }
520 pcp_fill_in6_addr(&fiter->filter_ip, &fiter->filter_port, filter_ip);
521 fiter->filter_prefix=filter_prefix;
522 pcp_flow_updated(fiter);
523 }
524}
525
527{
528 pcp_flow_t *fiter;
529
530 for (fiter=f; fiter != NULL; fiter=fiter->next_child) {
531 if (!fiter->pfailure_option_present) {
533 pcp_flow_updated(fiter);
534 }
535 }
536}
537#ifdef PCP_EXPERIMENTAL
538int pcp_flow_set_userid(pcp_flow_t *f, pcp_userid_option_p user)
539{
540 pcp_flow_t *fiter;
541
542 for (fiter=f; fiter; fiter=fiter->next_child) {
543 memcpy(&(fiter->f_userid.userid[0]), &(user->userid[0]), MAX_USER_ID);
544 pcp_flow_updated(fiter);
545 }
546 return 0;
547}
548
549int pcp_flow_set_location(pcp_flow_t *f, pcp_location_option_p loc)
550{
551 pcp_flow_t *fiter;
552
553 for (fiter=f; fiter; fiter=fiter->next_child) {
554 memcpy(&(fiter->f_location.location[0]), &(loc->location[0]), MAX_GEO_STR);
555 pcp_flow_updated(fiter);
556 }
557
558 return 0;
559}
560
561int pcp_flow_set_deviceid(pcp_flow_t *f, pcp_deviceid_option_p dev)
562{
563 pcp_flow_t *fiter;
564
565 for (fiter=f; fiter; fiter=fiter->next_child) {
566 memcpy(&(fiter->f_deviceid.deviceid[0]), &(dev->deviceid[0]), MAX_DEVICE_ID);
567 pcp_flow_updated(fiter);
568 }
569 return 0;
570}
571
572void
573pcp_flow_add_md (pcp_flow_t *f, uint32_t md_id, void *value, size_t val_len)
574{
575 pcp_flow_t *fiter;
576
577 for (fiter=f; fiter!=NULL; fiter=fiter->next_child) {
578 pcp_db_add_md(fiter, md_id, value, val_len);
579 pcp_flow_updated(fiter);
580 }
581}
582#endif
583
584#ifdef PCP_FLOW_PRIORITY
585void pcp_flow_set_flowp(pcp_flow_t *f, uint8_t dscp_up, uint8_t dscp_down)
586{
587 pcp_flow_t *fiter;
588
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;
593 }
594 if (fpresent) {
595 fiter->flowp_dscp_up=dscp_up;
596 fiter->flowp_dscp_down=dscp_down;
597 }
598 pcp_flow_updated(fiter);
599 }
600}
601#endif
602
603static inline void pcp_close_flow_intern(pcp_flow_t *f)
604{
605 switch (f->state) {
607 case pfs_idle:
608 case pfs_failed:
609 f->state=pfs_failed;
610 break;
611 default:
612 f->lifetime=0;
614 break;
615 }
616 if ((f->state != pfs_wait_for_server_init) && (f->state != pfs_idle)
617 && (f->state != pfs_failed)) {
618 PCP_LOG_FLOW(f, "Flow closed");
619 f->lifetime=0;
621 } else {
622 f->state=pfs_failed;
623 }
624}
625
627{
628 pcp_flow_t *fiter;
629
630 for (fiter=f; fiter; fiter=fiter->next_child) {
631 pcp_close_flow_intern(fiter);
632 }
633
634 if (f) {
635 pcp_pulse(f->ctx, NULL);
636 }
637}
638
640{
641 pcp_flow_t *fiter=f;
642 pcp_flow_t *fnext=NULL;
643
644 while (fiter) {
645 fnext=fiter->next_child;
647 fiter=fnext;
648 }
649}
650
651static int delete_flow_iter(pcp_flow_t *f, void *data)
652{
653 if (data) {
654 pcp_close_flow_intern(f);
655 pcp_pulse(f->ctx, NULL);
656 }
658
659 return 0;
660}
661
662void pcp_terminate(pcp_ctx_t *ctx, int close_flows)
663{
664 pcp_db_foreach_flow(ctx, delete_flow_iter, close_flows ? (void *)1 : NULL);
666 pcp_socket_close(ctx);
667}
668
670{
671 pcp_flow_t *fiter;
672 pcp_flow_info_t *info_buf;
673 pcp_flow_info_t *info_iter;
674 uint32_t cnt=0;
675
676 if (!info_count) {
677 return NULL;
678 }
679
680 for (fiter=f; fiter; fiter=fiter->next_child) {
681 ++cnt;
682 }
683
684 info_buf=(pcp_flow_info_t *)calloc(cnt, sizeof(pcp_flow_info_t));
685 if (!info_buf) {
686 PCP_LOG(PCP_LOGLVL_DEBUG, "%s", "Error allocating memory");
687 return NULL;
688 }
689
690 for (fiter=f, info_iter=info_buf; fiter != NULL;
691 fiter=fiter->next_child, ++info_iter) {
692
693 switch (fiter->state) {
696 break;
698 info_iter->result=pcp_state_succeeded;
699 break;
700 case pfs_failed:
701 info_iter->result=pcp_state_failed;
702 break;
703 default:
704 info_iter->result=pcp_state_processing;
705 break;
706 }
707
708 info_iter->recv_lifetime_end=fiter->recv_lifetime;
709 info_iter->lifetime_renew_s=fiter->lifetime;
710 info_iter->pcp_result_code=(uint8_t)(fiter->recv_result);
711 memcpy(&info_iter->int_ip, &fiter->kd.src_ip, sizeof(struct in6_addr));
712 memcpy(&info_iter->pcp_server_ip, &fiter->kd.pcp_server_ip,
713 sizeof(info_iter->pcp_server_ip));
714 if ((fiter->kd.operation == PCP_OPCODE_MAP)
715 || (fiter->kd.operation == PCP_OPCODE_PEER)) {
716 memcpy(&info_iter->dst_ip, &fiter->kd.map_peer.dst_ip,
717 sizeof(info_iter->dst_ip));
718 memcpy(&info_iter->ext_ip, &fiter->map_peer.ext_ip,
719 sizeof(info_iter->ext_ip));
720 info_iter->int_port=fiter->kd.map_peer.src_port;
721 info_iter->dst_port=fiter->kd.map_peer.dst_port;
722 info_iter->ext_port=fiter->map_peer.ext_port;
723 info_iter->protocol=fiter->kd.map_peer.protocol;
724#ifdef PCP_SADSCP
725 } else if (fiter->kd.operation == PCP_OPCODE_SADSCP) {
726 info_iter->learned_dscp=fiter->sadscp.learned_dscp;
727#endif
728 }
729 }
730 *info_count=cnt;
731
732 return info_buf;
733}
734
735void pcp_flow_set_user_data(pcp_flow_t *f, void *userdata)
736{
737 pcp_flow_t *fiter=f;
738
739 while (fiter) {
740 fiter->user_data=userdata;
741 fiter=fiter->next_child;
742 }
743}
744
746{
747 return (f ? f->user_data : NULL);
748}
749
750#ifdef PCP_SADSCP
751pcp_flow_t *pcp_learn_dscp(pcp_ctx_t *ctx, uint8_t delay_tol, uint8_t loss_tol,
752 uint8_t jitter_tol, char *app_name)
753{
754 struct flow_key_data kd;
755 struct caasi_data data;
756 struct in6_addr src_ip=IN6ADDR_ANY_INIT;
757
758 memset(&data, 0 ,sizeof(data));
759 memset(&kd, 0 ,sizeof(kd));
760
761 kd.operation=PCP_OPCODE_SADSCP;
762
763 data.fprev=NULL;
764 data.src_ip=&src_ip;
765 data.kd=&kd;
766 data.ffirst=NULL;
767 data.lifetime=0;
768 data.ext_addr=NULL;
769 data.toler_fields=(delay_tol&3)<<6 | ((loss_tol&3)<<4)
770 | ((jitter_tol&3)<<2);
771 data.app_name=app_name;
772
773 pcp_db_foreach_server(ctx, chain_and_assign_src_ip, &data);
774
775 return data.ffirst;
776}
777#endif
#define assert(condition)
Definition: debug.h:74
#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)
Definition: findsaddr-udp.c:71
uint uint32_t
uchar uint8_t
@ PCP_LOGLVL_DEBUG
Definition: pcp.h:90
@ PCP_LOGLVL_INFO
Definition: pcp.h:88
@ PCP_LOGLVL_PERR
Definition: pcp.h:89
@ PCP_LOGLVL_WARN
Definition: pcp.h:87
#define PCP_SOCKET
Definition: pcp.h:55
pcp_fstate_e
Definition: pcp.h:231
@ pcp_state_short_lifetime_error
Definition: pcp.h:235
@ pcp_state_partial_result
Definition: pcp.h:234
@ pcp_state_failed
Definition: pcp.h:236
@ pcp_state_succeeded
Definition: pcp.h:233
@ pcp_state_processing
Definition: pcp.h:232
int pcp_pulse(pcp_ctx_t *ctx, struct timeval *next_timeout)
@ PCP_ERR_BAD_ARGS
Definition: pcp.h:74
@ PCP_ERR_UNSUP_VERSION
Definition: pcp.h:72
@ PCP_ERR_MAX_SIZE
Definition: pcp.h:67
int pcp_add_server(pcp_ctx_t *ctx, struct sockaddr *pcp_server, uint8_t pcp_version)
Definition: pcp_api.c:72
int pcp_eval_flow_state(pcp_flow_t *flow, pcp_fstate_e *fstate)
Definition: pcp_api.c:136
void pcp_flow_set_filter_opt(pcp_flow_t *f, struct sockaddr *filter_ip, uint8_t filter_prefix)
Definition: pcp_api.c:511
pcp_ctx_t * pcp_init(uint8_t autodiscovery, pcp_socket_vt_t *socket_vt)
Definition: pcp_api.c:93
void * pcp_flow_get_user_data(pcp_flow_t *f)
Definition: pcp_api.c:745
void pcp_flow_set_user_data(pcp_flow_t *f, void *userdata)
Definition: pcp_api.c:735
pcp_fstate_e pcp_wait(pcp_flow_t *flow, int timeout, int exit_on_partial_res)
Definition: pcp_api.c:187
void pcp_delete_flow(pcp_flow_t *f)
Definition: pcp_api.c:639
void pcp_close_flow(pcp_flow_t *f)
Definition: pcp_api.c:626
void pcp_flow_set_3rd_party_opt(pcp_flow_t *f, struct sockaddr *thirdp_addr)
Definition: pcp_api.c:500
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)
Definition: pcp_api.c:389
void pcp_flow_set_prefer_failure_opt(pcp_flow_t *f)
Definition: pcp_api.c:526
PCP_SOCKET pcp_get_socket(pcp_ctx_t *ctx)
Definition: pcp_api.c:66
void pcp_flow_set_lifetime(pcp_flow_t *f, uint32_t lifetime)
Definition: pcp_api.c:489
pcp_flow_info_t * pcp_flow_get_info(pcp_flow_t *f, size_t *info_count)
Definition: pcp_api.c:669
void pcp_terminate(pcp_ctx_t *ctx, int close_flows)
Definition: pcp_api.c:662
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)
Definition: pcp_client_db.c:64
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)
@ pss_wait_io
@ pss_not_working
@ pfs_wait_for_lifetime_renew
@ pfs_send
@ pfs_wait_after_short_life_error
@ pfs_failed
@ pfs_idle
@ pfs_wait_for_server_init
int gettimeofday(struct timeval *tv, struct timezone *tz)
void pcp_strerror(int errnum, char *buf, size_t buflen)
Definition: pcp_logger.c:165
void pcp_logger_init(void)
Definition: pcp_logger.c:50
#define PCP_LOG_END(level)
Definition: pcp_logger.h:73
#define PCP_LOG_BEGIN(level)
Definition: pcp_logger.h:75
#define PCP_LOG_FLOW(f, msg)
Definition: pcp_logger.h:85
#define ERR_BUF_LEN
Definition: pcp_logger.h:29
#define PCP_LOG(level, fmt,...)
Definition: pcp_logger.h:71
#define MAX_DEVICE_ID
#define PCP_OPCODE_PEER
#define MAX_GEO_STR
#define PCP_OPCODE_SADSCP
#define PCP_OPCODE_MAP
#define MAX_USER_ID
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)
Definition: pcp_socket.c:99
int pcp_socket_close(struct pcp_ctx_s *ctx)
Definition: pcp_socket.c:207
pcp_socket_vt_t default_socket_vt
Definition: pcp_socket.c:58
PCP_SOCKET pcp_socket_create(struct pcp_ctx_s *ctx, int domain, int type, int protocol)
Definition: pcp_socket.c:181
#define PCP_INVALID_SOCKET
Definition: pcp_socket.h:61
#define S6_ADDR32(sa6)
Definition: pcp_utils.h:114
#define OSDEP(x)
Definition: pcp_utils.h:109
#define strdup
pcp_flow_t * ffirst
Definition: pcp_api.c:330
pcp_flow_t * fprev
Definition: pcp_api.c:329
struct flow_key_data * kd
Definition: pcp_api.c:328
char * app_name
Definition: pcp_api.c:335
void * userdata
Definition: pcp_api.c:336
uint32_t lifetime
Definition: pcp_api.c:331
struct sockaddr * ext_addr
Definition: pcp_api.c:332
struct in6_addr * src_ip
Definition: pcp_api.c:333
uint8_t toler_fields
Definition: pcp_api.c:334
struct in6_addr dst_ip
Definition: pcp_client_db.h:73
struct flow_key_data::mp_keydata map_peer
struct in6_addr src_ip
Definition: pcp_client_db.h:66
struct in6_addr pcp_server_ip
Definition: pcp_client_db.h:67
uint8_t operation
Definition: pcp_client_db.h:65
pcp_socket_vt_t * virt_socket_tb
PCP_SOCKET socket
uint8_t learned_dscp
Definition: pcp.h:252
uint16_t dst_port
Definition: pcp.h:250
struct in6_addr int_ip
Definition: pcp.h:247
struct in6_addr dst_ip
Definition: pcp.h:249
pcp_fstate_e result
Definition: pcp.h:240
struct in6_addr pcp_server_ip
Definition: pcp.h:241
time_t recv_lifetime_end
Definition: pcp.h:244
uint16_t int_port
Definition: pcp.h:248
time_t lifetime_renew_s
Definition: pcp.h:245
uint8_t protocol
Definition: pcp.h:251
uint16_t ext_port
Definition: pcp.h:243
struct in6_addr ext_ip
Definition: pcp.h:242
uint8_t pcp_result_code
Definition: pcp.h:246
uint8_t third_party_option_present
uint16_t ext_port
uint8_t filter_option_present
struct timeval timeout
uint8_t filter_prefix
uint16_t filter_port
struct pcp_ctx_s * ctx
struct flow_key_data kd
void * user_data
struct pcp_flow_s * next_child
uint32_t lifetime
uint32_t key_bucket
struct pcp_flow_s::@5::@7 map_peer
struct in6_addr third_party_ip
uint32_t recv_result
struct in6_addr filter_ip
uint8_t pfailure_option_present
time_t recv_lifetime
struct in6_addr ext_ip
pcp_flow_state_e state
uint32_t pcp_ip[4]
struct timeval next_timeout
pcp_server_state_e server_state
uint32_t src_ip[4]
pcp_ctx_t * ctx
struct pcp_nonce nonce