Project Alice
Loading...
Searching...
No Matches
pcp_event_handler.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#include <stddef.h>
33#include <stdint.h>
34#include <stdlib.h>
35#include <string.h>
36#include <stdio.h>
37#include <errno.h>
38#include <time.h>
39#include <assert.h>
40
41#ifdef WIN32
44#else
45//#include <unistd.h>
46#include <sys/socket.h>
47#include <sys/select.h>
48#include <netinet/in.h>
49#include <arpa/inet.h>
50#include <sys/time.h>
51#endif
52
53#include "pcp.h"
54#include "pcp_utils.h"
55#include "pcp_msg.h"
56#include "pcp_msg_structs.h"
57#include "pcp_logger.h"
58#include "pcp_event_handler.h"
60#include "net/pcp_socket.h"
61
62#ifndef MIN
63#define MIN(a, b) (a<b?a:b)
64#endif
65#ifndef MAX
66#define MAX(a, b) (a>b?a:b)
67#endif
68#define PCP_RT(rtprev) ((rtprev=rtprev<<1),(((8192+(1024-(rand()&2047))) \
69 * MIN (MAX(rtprev,PCP_RETX_IRT), PCP_RETX_MRT))>>13))
70
71static pcp_flow_event_e fhndl_send(pcp_flow_t *f, pcp_recv_msg_t *msg);
72static pcp_flow_event_e fhndl_resend(pcp_flow_t *f, pcp_recv_msg_t *msg);
73static pcp_flow_event_e fhndl_send_renew(pcp_flow_t *f, pcp_recv_msg_t *msg);
74static pcp_flow_event_e fhndl_shortlifeerror(pcp_flow_t *f, pcp_recv_msg_t *msg);
75static pcp_flow_event_e fhndl_received_success(pcp_flow_t *f, pcp_recv_msg_t *msg);
76static pcp_flow_event_e fhndl_clear_timeouts(pcp_flow_t *f, pcp_recv_msg_t *msg);
77static pcp_flow_event_e fhndl_waitresp(pcp_flow_t *f, pcp_recv_msg_t *msg);
78
79static pcp_server_state_e handle_wait_io_receive_msg(pcp_server_t *s);
80static pcp_server_state_e handle_server_ping(pcp_server_t *s);
81static pcp_server_state_e handle_wait_ping_resp_timeout(pcp_server_t *s);
82static pcp_server_state_e handle_wait_ping_resp_recv(pcp_server_t *s);
83static pcp_server_state_e handle_version_negotiation(pcp_server_t *s);
84static pcp_server_state_e handle_send_all_msgs(pcp_server_t *s);
85static pcp_server_state_e handle_server_restart(pcp_server_t *s);
86static pcp_server_state_e handle_wait_io_timeout(pcp_server_t *s);
87static pcp_server_state_e handle_server_set_not_working(pcp_server_t *s);
88static pcp_server_state_e handle_server_not_working(pcp_server_t *s);
89static pcp_server_state_e handle_server_reping(pcp_server_t *s);
90static pcp_server_state_e pcp_terminate_server(pcp_server_t *s);
91static pcp_server_state_e log_unexepected_state_event(pcp_server_t *s);
92static pcp_server_state_e ignore_events(pcp_server_t *s);
93
94
96// Flow State Machine definition
97
99
100typedef struct pcp_flow_state_trans {
105
106static pcp_flow_state_trans_t flow_transitions[]={
107 {pfs_any, pfs_wait_resp, fhndl_waitresp},
108 {pfs_wait_resp, pfs_send, fhndl_resend},
109 {pfs_any, pfs_send, fhndl_send},
110 {pfs_any, pfs_wait_after_short_life_error, fhndl_shortlifeerror},
111 {pfs_wait_resp, pfs_wait_for_lifetime_renew, fhndl_received_success},
112 {pfs_any, pfs_send_renew, fhndl_send_renew},
114 {pfs_any, pfs_wait_for_server_init, fhndl_clear_timeouts},
115 {pfs_any, pfs_failed, fhndl_clear_timeouts},
116};
117
118#define FLOW_TRANS_COUNT (sizeof(flow_transitions)/sizeof(*flow_transitions))
119
120typedef struct pcp_flow_state_event {
125
126static pcp_flow_state_events_t flow_events_sm[]={
153// { pfs_failed, fev_server_restarted, pfs_send},
157// Long lifetime Error Responses from PCP server
172};
173
174#define FLOW_EVENTS_SM_COUNT (sizeof(flow_events_sm)/sizeof(*flow_events_sm))
175
176static pcp_errno pcp_flow_send_msg(pcp_flow_t *flow, pcp_server_t *s)
177{
178 ssize_t ret;
179 size_t to_send_count;
180 pcp_ctx_t *ctx=s->ctx;
181
183
184 if ((!flow->pcp_msg_buffer) || (flow->pcp_msg_len == 0)) {
185 build_pcp_msg(flow);
186 if (flow->pcp_msg_buffer == NULL) {
187 PCP_LOG(PCP_LOGLVL_DEBUG, "Cannot build PCP MSG (flow bucket:%d)",
188 flow->key_bucket);
190 return PCP_ERR_SEND_FAILED;
191 }
192 }
193
194 to_send_count=flow->pcp_msg_len;
195
196 while (to_send_count != 0) {
197 ret=flow->pcp_msg_len - to_send_count;
198
199 ret=pcp_socket_sendto(ctx, flow->pcp_msg_buffer + ret,
200 flow->pcp_msg_len - ret, MSG_DONTWAIT,
201 (struct sockaddr*)&s->pcp_server_saddr,
202 (socklen_t)SA_LEN((struct sockaddr*)&s->pcp_server_saddr));
203 if (ret <= 0) {
204 PCP_LOG(PCP_LOGLVL_WARN, "Error occurred while sending "
205 "PCP packet to server %s", s->pcp_server_paddr);
207 return PCP_ERR_SEND_FAILED;
208 }
209 to_send_count-=ret;
210 }
211
212 PCP_LOG(PCP_LOGLVL_INFO, "Sent PCP MSG (flow bucket:%d)",
213 flow->key_bucket);
214
216
218 return PCP_ERR_SUCCESS;
219}
220
221static pcp_errno read_msg(pcp_ctx_t *ctx, pcp_recv_msg_t *msg)
222{
223 ssize_t ret;
224 socklen_t src_len=sizeof(msg->rcvd_from_addr);
225
226 memset(msg, 0, sizeof(*msg));
227
228 if ((ret=pcp_socket_recvfrom(ctx, msg->pcp_msg_buffer,
229 sizeof(msg->pcp_msg_buffer), MSG_DONTWAIT,
230 (struct sockaddr*)&msg->rcvd_from_addr, &src_len)) < 0) {
231 return (pcp_errno)ret;
232 }
233
234 msg->pcp_msg_len=(uint32_t)ret;
235
236 return PCP_ERR_SUCCESS;
237}
238
240// Flow State Transitions Handlers
241
242static pcp_flow_event_e fhndl_send(pcp_flow_t *f, UNUSED pcp_recv_msg_t *msg)
243{
246
247 if (!s) {
249 return fev_failed;
250 }
251
252 if (s->restart_flow_msg == f) {
253 return fev_ignored;
254 }
255
256 if (pcp_flow_send_msg(f, s) != PCP_ERR_SUCCESS) {
258 return fev_failed;
259 }
260
262 //set timeout field
263 gettimeofday(&f->timeout, NULL);
264 f->timeout.tv_sec+=f->resend_timeout / 1000;
265 f->timeout.tv_usec+=(f->resend_timeout % 1000) * 1000;
266
268 return fev_msg_sent;
269}
270
271static pcp_flow_event_e fhndl_resend(pcp_flow_t *f, UNUSED pcp_recv_msg_t *msg)
272{
275
276 if (!s) {
278 return fev_failed;
279 }
280
281#if PCP_RETX_MRC>0
282 if (++f->retry_count >= PCP_RETX_MRC) {
283 return fev_failed;
284 }
285#endif
286
287 if (pcp_flow_send_msg(f, s) != PCP_ERR_SUCCESS) {
289 return fev_failed;
290 }
291
293
294#if (PCP_RETX_MRD>0)
295 {
296 int tdiff = (curtime - f->created_time)*1000;
297 if (tdiff > PCP_RETX_MRD) {
298 return fev_failed;
299 }
300 if (tdiff > f->resend_timeout) {
301 f->resend_timeout = tdiff;
302 }
303 }
304#endif
305
306 //set timeout field
307 gettimeofday(&f->timeout, NULL);
308 f->timeout.tv_sec+=f->resend_timeout / 1000;
309 f->timeout.tv_usec+=(f->resend_timeout % 1000) * 1000;
310
312 return fev_msg_sent;
313}
314
315static pcp_flow_event_e fhndl_shortlifeerror(pcp_flow_t *f, pcp_recv_msg_t *msg)
316{
318 "f->pcp_server_index=%d, f->state = %d, f->key_bucket=%d",
319 f->pcp_server_indx, f->state, f->key_bucket);
320
321 f->recv_result=msg->recv_result;
322
323 gettimeofday(&f->timeout, NULL);
324 f->timeout.tv_sec+=msg->recv_lifetime;
325
326 return fev_none;
327}
328
329static pcp_flow_event_e fhndl_received_success(pcp_flow_t *f,
330 pcp_recv_msg_t *msg)
331{
332 struct timeval ctv;
333
336 if ((f->kd.operation == PCP_OPCODE_MAP)
337 || (f->kd.operation == PCP_OPCODE_PEER)) {
340#ifdef PCP_SADSCP
341 } else if (f->kd.operation == PCP_OPCODE_SADSCP) {
342 f->sadscp.learned_dscp = msg->recv_dscp;
343#endif
344 }
345 f->recv_result=msg->recv_result;
346
347 gettimeofday(&ctv, NULL);
348
349 if (msg->recv_lifetime == 0) {
350 f->timeout.tv_sec=0;
351 f->timeout.tv_usec=0;
352 } else {
353 f->timeout=ctv;
354 f->timeout.tv_sec+=(long int)((f->recv_lifetime - ctv.tv_sec) >> 1);
355 }
356
358 return fev_none;
359}
360
361static pcp_flow_event_e fhndl_send_renew(pcp_flow_t *f,
363{
365 long timeout_add;
366
367 if (!s) {
368 return fev_failed;
369 }
370
371 if (pcp_flow_send_msg(f, s) != PCP_ERR_SUCCESS) {
372 return fev_failed;
373 }
374
375 gettimeofday(&f->timeout, NULL);
376 timeout_add=(long)((f->recv_lifetime - f->timeout.tv_sec) >> 1);
377
378 if (timeout_add == 0) {
379 return fev_failed;
380 } else {
381 f->timeout.tv_sec+=timeout_add;
382 }
383
384 return fev_msg_sent;
385}
386
387static pcp_flow_event_e fhndl_clear_timeouts(pcp_flow_t *f, pcp_recv_msg_t *msg)
388{
389 if (msg) {
390 f->recv_result=msg->recv_result;
391 }
393 f->timeout.tv_sec=0;
394 f->timeout.tv_usec=0;
395
396 return fev_none;
397}
398
399static pcp_flow_event_e fhndl_waitresp(pcp_flow_t *f,
401{
402 struct timeval ctv;
403
404 gettimeofday(&ctv, NULL);
405 if (timeval_comp(&f->timeout, &ctv) < 0) {
406 return fev_failed;
407 }
408
409 return fev_none;
410}
411
412static void flow_change_notify(pcp_flow_t *flow, pcp_fstate_e state);
413
414static pcp_flow_state_e handle_flow_event(pcp_flow_t *f, pcp_flow_event_e ev,
416{
417 pcp_flow_state_e cur_state=f->state, next_state;
419 pcp_flow_state_events_t *esm_end=flow_events_sm + FLOW_EVENTS_SM_COUNT;
421 pcp_flow_state_trans_t *trans_end=flow_transitions + FLOW_TRANS_COUNT;
422 pcp_fstate_e before, after;
423 struct in6_addr prev_ext_addr=f->map_peer.ext_ip;
424 uint16_t prev_ext_port=f->map_peer.ext_port;
425
427 pcp_eval_flow_state(f, &before);
428 for (;;) {
429 for (esm=flow_events_sm; esm < esm_end; ++esm) {
430 if (((esm->state == cur_state) || (esm->state == pfs_any))
431 && (esm->event == ev)) {
432 break;
433 }
434 }
435
436 if (esm == esm_end) {
437 //TODO:log
438 goto end;
439 }
440
441 next_state=esm->new_state;
442
443 for (trans=flow_transitions; trans < trans_end; ++trans) {
444 if (((trans->state_from == cur_state)
445 || (trans->state_from == pfs_any))
446 && (trans->state_to == next_state)) {
447
448#if PCP_MAX_LOG_LEVEL>=PCP_LOGLVL_DEBUG
449 pcp_flow_event_e prev_ev=ev;
450#endif
451 f->state=next_state;
452
454 "Executing event handler %s\n flow \t: %d (server %d)\n"
455 " states\t: %s => %s\n event\t: %s",
456 dbg_get_func_name(trans->handler), f->key_bucket, f->pcp_server_indx, dbg_get_state_name(cur_state), dbg_get_state_name(next_state), dbg_get_event_name(prev_ev));
457
458 ev=trans->handler(f, r);
459
461 "Return from event handler's %s \n result event: %s",
462 dbg_get_func_name(trans->handler), dbg_get_event_name(ev));
463
464 cur_state=next_state;
465
466 if (ev == fev_none) {
467 goto end;
468 }
469 break;
470 }
471 }
472
473 //no transition handler
474 if (trans == trans_end) {
475 f->state=next_state;
476 goto end;
477 }
478 }
479end:
480 pcp_eval_flow_state(f, &after);
481 if ((before != after)
482 || (!IN6_ARE_ADDR_EQUAL(&prev_ext_addr, &f->map_peer.ext_ip))
483 || (prev_ext_port != f->map_peer.ext_port)) {
484 flow_change_notify(f, after);
485 }
486
488 return f->state;
489}
490
492// Helper functions for server state handlers
493
494static pcp_flow_t *server_process_rcvd_pcp_msg(pcp_server_t *s,
495 pcp_recv_msg_t *msg)
496{
497 pcp_flow_t *f;
498#ifndef PCP_DISABLE_NATPMP
499 if (msg->recv_version == 0) {
500 if (msg->kd.operation == NATPMP_OPCODE_ANNOUNCE) {
502 if ((s->pcp_version == 0) && (s->ping_flow_msg)
504 f=s->ping_flow_msg;
505 } else {
506 f=NULL;
507 }
508 } else {
510 S6_ADDR32(&msg->assigned_ext_ip)[2]=htonl(0xFFFF);
511 S6_ADDR32(&msg->assigned_ext_ip)[1]=0;
512 S6_ADDR32(&msg->assigned_ext_ip)[0]=0;
513
514 f=pcp_get_flow(&msg->kd, s);
515 }
516 } else {
517 f=pcp_get_flow(&msg->kd, s);
518 }
519#else
520 f = pcp_get_flow(&msg->kd, s->index);
521#endif
522
523 if (!f) {
524 return NULL;
525 }
526
528 "Found matching flow %d to received PCP message.", f->key_bucket);
529
530 handle_flow_event(f, (pcp_flow_event_e)(FEV_RES_BEGIN + msg->recv_result), msg);
531
532 return f;
533}
534
535static int check_flow_timeout(pcp_flow_t *f, void *timeout)
536{
537 struct timeval *tout=(struct timeval* )timeout;
538 struct timeval ctv;
539
540 if ((f->timeout.tv_sec == 0) && (f->timeout.tv_usec == 0)) {
541 return 0;
542 }
543
544 gettimeofday(&ctv, NULL);
545 if (timeval_comp(&f->timeout, &ctv) <= 0) {
546 // timed out
547 if (f->state == pfs_wait_resp) {
549 "Recv of PCP response for flow %d timed out.",
550 f->key_bucket);
551 }
552 handle_flow_event(f, fev_flow_timedout, NULL);
553 }
554
555 if ((f->timeout.tv_sec == 0) && (f->timeout.tv_usec == 0)) {
556 return 0;
557 }
558
559 timeval_subtract(&ctv, &f->timeout, &ctv);
560
561 if ((tout->tv_sec == 0) && (tout->tv_usec == 0)) {
562 *tout=ctv;
563 return 0;
564 }
565
566 if (timeval_comp(&ctv, tout) < 0) {
567 *tout=ctv;
568 }
569
570 return 0;
571}
572
576};
577
578static int get_first_flow_iter(pcp_flow_t *f, void *data)
579{
580 struct get_first_flow_iter_data *d=(struct get_first_flow_iter_data *)data;
581
582 if (f->pcp_server_indx == d->s->index) {
583 d->msg=f;
584 return 1;
585 } else {
586 return 0;
587 }
588}
589
590#ifndef PCP_DISABLE_NATPMP
591static inline pcp_flow_t *create_natpmp_ann_msg(pcp_server_t *s)
592{
593 struct flow_key_data kd;
594
595 memset(&kd, 0, sizeof(kd));
596 memcpy(&kd.src_ip, s->src_ip, sizeof(kd.src_ip));
597 memcpy(&kd.pcp_server_ip, s->pcp_ip, sizeof(kd.pcp_server_ip));
598 memcpy(&kd.nonce, &s->nonce, sizeof(kd.nonce));
599 kd.operation=NATPMP_OPCODE_ANNOUNCE;
600
603
604 return s->ping_flow_msg;
605}
606#endif
607
608static inline pcp_flow_t *get_ping_msg(pcp_server_t *s)
609{
611
613 if (!s)
614 return NULL;
615
616 find_data.s=s;
617 find_data.msg=NULL;
618
619 pcp_db_foreach_flow(s->ctx, get_first_flow_iter, &find_data);
620
622
624 return find_data.msg;
625}
626
630};
631
632static int flow_send_event_iter(pcp_flow_t *f, void *data)
633{
634 struct flow_iterator_data *d=(struct flow_iterator_data *)data;
635
636 if (f->pcp_server_indx == d->s->index) {
637 handle_flow_event(f, d->event, NULL);
638 check_flow_timeout(f, &d->s->next_timeout);
639 }
640
641 return 0;
642}
643
645// Server state machine event handlers
646
647static pcp_server_state_e handle_server_ping(pcp_server_t *s)
648{
649 pcp_flow_t *msg;
651 s->ping_count=0;
652
653 msg=get_ping_msg(s);
654
655 if (!msg) {
656 s->next_timeout.tv_sec=0;
657 s->next_timeout.tv_usec=0;
658 return pss_ping;
659 }
660
661 msg->retry_count=0;
662
663 PCP_LOG(PCP_LOGLVL_INFO, "Pinging PCP server at address %s",
665
666 if (handle_flow_event(msg, fev_send, NULL) != pfs_failed) {
667 s->next_timeout=msg->timeout;
668
670 return pss_wait_ping_resp;
671 }
672
673 gettimeofday(&s->next_timeout, NULL);
675 return pss_set_not_working;
676}
677
678static pcp_server_state_e handle_wait_ping_resp_timeout(pcp_server_t *s)
679{
680 if (++s->ping_count >= PCP_MAX_PING_COUNT) {
681 gettimeofday(&s->next_timeout, NULL);
682 return pss_set_not_working;
683 }
684
685 if (!s->ping_flow_msg) {
686 gettimeofday(&s->next_timeout, NULL);
687 return pss_ping;
688 }
689
690 if (handle_flow_event(s->ping_flow_msg, fev_flow_timedout, NULL)
691 == pfs_failed) {
692 gettimeofday(&s->next_timeout, NULL);
693 return pss_set_not_working;
694 }
695
696 if (s->ping_flow_msg) {
698 } else {
699 s->next_timeout.tv_sec=0;
700 s->next_timeout.tv_usec=0;
701 return pss_ping;
702 }
703 return pss_wait_ping_resp;
704}
705
706static pcp_server_state_e handle_wait_ping_resp_recv(pcp_server_t *s)
707{
708 pcp_server_state_e res=handle_wait_io_receive_msg(s);
709
710 switch (res) {
713 break;
714 case pss_wait_io:
716 break;
717 default:
718 break;
719 }
720 return res;
721}
722
723static pcp_server_state_e handle_version_negotiation(pcp_server_t *s)
724{
725 pcp_flow_t *ping_msg;
726
727 if (s->next_version == s->pcp_version) {
728 s->next_version--;
729 }
730
731 if (s->pcp_version == 0
734#endif
735 ) {
737 "Version negotiation failed for PCP server %s. "
738 "Disabling sending PCP messages to this server.",
740
741 return pss_set_not_working;
742 }
743
745 "Version %d not supported by server %s. Trying version %d.",
748
749 ping_msg=s->ping_flow_msg;
750
751#ifndef PCP_DISABLE_NATPMP
752 if (s->pcp_version == 0) {
753 if (ping_msg) {
755 ping_msg->timeout.tv_sec=0;
756 ping_msg->timeout.tv_usec=0;
757 }
758 ping_msg=create_natpmp_ann_msg(s);
759 }
760#endif
761
762 if (!ping_msg) {
763 ping_msg=get_ping_msg(s);
764 if (!ping_msg) {
765 s->next_timeout.tv_sec=0;
766 s->next_timeout.tv_usec=0;
767 return pss_ping;
768 }
769 }
770
771 ping_msg->retry_count=0;
772 ping_msg->resend_timeout=0;
773
774 handle_flow_event(ping_msg, fev_send, NULL);
775 if (ping_msg->state == pfs_failed) {
776 return pss_set_not_working;
777 }
778
779 s->next_timeout=ping_msg->timeout;
780
781 return pss_wait_ping_resp;
782}
783
784static pcp_server_state_e handle_send_all_msgs(pcp_server_t *s)
785{
787
788 pcp_db_foreach_flow(s->ctx, flow_send_event_iter, &d);
789 gettimeofday(&s->next_timeout, NULL);
790
792}
793
794static pcp_server_state_e handle_server_restart(pcp_server_t *s)
795{
797
798 pcp_db_foreach_flow(s->ctx, flow_send_event_iter, &d);
799 s->restart_flow_msg=NULL;
800 gettimeofday(&s->next_timeout, NULL);
801
803}
804
805static pcp_server_state_e handle_wait_io_receive_msg(pcp_server_t *s)
806{
807 pcp_recv_msg_t *msg=&s->ctx->msg;
808 pcp_flow_t *f;
809
811 "Received PCP packet from server at %s, size %d, result_code %d, epoch %d",
813
814 switch (msg->recv_result) {
816 PCP_LOG(PCP_LOGLVL_DEBUG, "PCP server %s returned "
817 "result_code=Unsupported version", s->pcp_server_paddr);
818 gettimeofday(&s->next_timeout, NULL);
822 PCP_LOG(PCP_LOGLVL_WARN, "There is PCP-unaware NAT present "
823 "between client and PCP server %s. "
824 "Sending of PCP messages was disabled.", s->pcp_server_paddr);
825 gettimeofday(&s->next_timeout, NULL);
826 return pss_set_not_working;
827 }
828
829 f=server_process_rcvd_pcp_msg(s, msg);
830
831 if (compare_epochs(msg, s)) {
832 s->epoch=msg->recv_epoch;
833 s->cepoch=msg->received_time;
834 gettimeofday(&s->next_timeout, NULL);
836
837 return pss_server_restart;
838 }
839
840 gettimeofday(&s->next_timeout, NULL);
841
843}
844
845static pcp_server_state_e handle_wait_io_timeout(pcp_server_t *s)
846{
847 struct timeval ctv;
848
849 s->next_timeout.tv_sec=0;
850 s->next_timeout.tv_usec=0;
851
852 pcp_db_foreach_flow(s->ctx, check_flow_timeout, &s->next_timeout);
853
854 if ((s->next_timeout.tv_sec != 0) || (s->next_timeout.tv_usec != 0)) {
855 gettimeofday(&ctv, NULL);
856 s->next_timeout.tv_sec+=ctv.tv_sec;
857 s->next_timeout.tv_usec+=ctv.tv_usec;
858 timeval_align(&s->next_timeout);
859 }
860
861 return pss_wait_io;
862}
863
864static pcp_server_state_e handle_server_set_not_working(pcp_server_t *s)
865{
867
868 PCP_LOG(PCP_LOGLVL_DEBUG, "Entered function %s", __FUNCTION__);
869 PCP_LOG(PCP_LOGLVL_WARN, "PCP server %s failed to respond. "
870 "Disabling sending of PCP messages to this server for %d minutes.",
872
873 pcp_db_foreach_flow(s->ctx, flow_send_event_iter, &d);
874
875 gettimeofday(&s->next_timeout, NULL);
877
878 return pss_not_working;
879}
880
881static pcp_server_state_e handle_server_not_working(pcp_server_t *s)
882{
883 struct timeval ctv;
884
885 gettimeofday(&ctv, NULL);
886 if (timeval_comp(&ctv, &s->next_timeout) < 0) {
887 pcp_recv_msg_t *msg=&s->ctx->msg;
888 pcp_flow_t *f;
889
891 "Received PCP packet from server at %s, size %d, result_code %d, epoch %d",
893
894 switch (msg->recv_result) {
896 return pss_not_working;
898 return pss_not_working;
899 }
900
901 f=server_process_rcvd_pcp_msg(s, msg);
902
903 s->epoch=msg->recv_epoch;
904 s->cepoch=msg->received_time;
905 gettimeofday(&s->next_timeout, NULL);
906 s->restart_flow_msg=f;
907
908 return pss_server_restart;
909 }
910
911 s->next_timeout=ctv;
912
913 return pss_server_reping;
914
915}
916
917static pcp_server_state_e handle_server_reping(pcp_server_t *s)
918{
919 PCP_LOG(PCP_LOGLVL_INFO, "Trying to ping PCP server %s again. ",
921
923 gettimeofday(&s->next_timeout, NULL);
924
925 return pss_ping;
926}
927
928static pcp_server_state_e pcp_terminate_server(pcp_server_t *s)
929{
930 s->next_timeout.tv_sec=0;
931 s->next_timeout.tv_usec=0;
932
933 PCP_LOG(PCP_LOGLVL_INFO, "PCP server %s terminated. ",
935
936 return pss_allocated;
937}
938
939static pcp_server_state_e ignore_events(pcp_server_t *s)
940{
941 s->next_timeout.tv_sec=0;
942 s->next_timeout.tv_usec=0;
943
944 return s->server_state;
945}
946
947//LCOV_EXCL_START
948static pcp_server_state_e log_unexepected_state_event(pcp_server_t *s)
949{
950 PCP_LOG(PCP_LOGLVL_PERR, "Event happened in the state %d on PCP server %s"
951 " and there is no event handler defined.",
953
954 gettimeofday(&s->next_timeout, NULL);
955 return pss_set_not_working;
956}
957//LCOV_EXCL_STOP
959// Server State Machine definition
960
962
968
970 pcp_terminate_server},
971// -> allocated
972 {pss_ping, pcpe_any, handle_server_ping},
973 // -> wait_ping_resp | set_not_working
974 {pss_wait_ping_resp, pcpe_timeout, handle_wait_ping_resp_timeout},
975 // -> wait_ping_resp | set_not_working
976 {pss_wait_ping_resp, pcpe_io_event, handle_wait_ping_resp_recv},
977 // -> wait ping_resp | pss_send_waiting_msgs | set_not_working | version_neg
978 {pss_version_negotiation, pcpe_any, handle_version_negotiation},
979 // -> wait ping_resp | set_not_working
980 {pss_send_all_msgs, pcpe_any, handle_send_all_msgs},
981 // -> wait_io
982 {pss_wait_io, pcpe_io_event, handle_wait_io_receive_msg},
983 // -> wait_io_calc_nearest_timeout | server_restart |version_negotiation | set_not_working
984 {pss_wait_io, pcpe_timeout, handle_wait_io_timeout},
985 // -> wait_io | server_restart
986 {pss_wait_io_calc_nearest_timeout, pcpe_any, handle_wait_io_timeout},
987 // -> wait_io
988 {pss_server_restart, pcpe_any, handle_server_restart},
989 // -> wait_io
990 {pss_server_reping, pcpe_any, handle_server_reping},
991 // -> ping
992 {pss_set_not_working, pcpe_any, handle_server_set_not_working},
993 // -> not_working
994 {pss_not_working, pcpe_any, handle_server_not_working},
995 // -> reping
996 {pss_allocated, pcpe_any, ignore_events},
997 {pss_any, pcpe_any, log_unexepected_state_event}
998// -> last_state
999 };
1000
1001#define SERVER_STATE_MACHINE_COUNT (sizeof(server_sm)/sizeof(*server_sm))
1002
1004{
1005 unsigned i;
1006
1008 if (!s) {
1009 return PCP_ERR_BAD_ARGS;
1010 }
1011
1012 for (i=0; i < SERVER_STATE_MACHINE_COUNT; ++i) {
1013 pcp_server_state_machine_t *state_def=server_sm + i;
1014 if ((state_def->state == s->server_state)
1015 || (state_def->state == pss_any)) {
1016 if ((state_def->event == pcpe_any) || (state_def->event == event)) {
1018 "Executing server state handler %s\n server \t: %s (index %d)\n"
1019 " state\t: %s\n"
1020 " event\t: %s",
1021 dbg_get_func_name(state_def->handler), s->pcp_server_paddr, s->index, dbg_get_sstate_name(s->server_state), dbg_get_sevent_name(event));
1022
1023 s->server_state=state_def->handler(s);
1024
1026 "Return from server state handler's %s \n result state: %s",
1027 dbg_get_func_name(state_def->handler), dbg_get_sstate_name(s->server_state));
1028
1029 break;
1030 }
1031 }
1033 return PCP_ERR_SUCCESS;
1034}
1035
1037 struct timeval *res_timeout;
1039};
1040
1041static int hserver_iter(pcp_server_t *s, void *data)
1042{
1043 pcp_event_e ev=((struct hserver_iter_data*)data)->ev;
1044 struct timeval *res_timeout=((struct hserver_iter_data*)data)->res_timeout;
1045 struct timeval ctv;
1046
1048 if ((s == NULL) || (s->server_state == pss_unitialized) || (data == NULL)) {
1050 return 0;
1051 }
1052
1053 if (ev != pcpe_timeout)
1055
1056 while (1) {
1057 gettimeofday(&ctv, NULL);
1058 if (((s->next_timeout.tv_sec == 0) && (s->next_timeout.tv_usec == 0))
1059 || (!timeval_subtract(&ctv, &s->next_timeout, &ctv))) {
1060 break;
1061 }
1063 }
1064
1065 if ((!res_timeout)
1066 || ((s->next_timeout.tv_sec == 0) && (s->next_timeout.tv_usec == 0))) {
1068 return 0;
1069 }
1070
1071 if ((res_timeout->tv_sec == 0) && (res_timeout->tv_usec == 0)) {
1072
1073 *res_timeout=ctv;
1074
1075 } else if (timeval_comp(&ctv, res_timeout) < 0) {
1076
1077 *res_timeout=ctv;
1078 }
1079
1081 return 0;
1082}
1083
1085// Exported functions
1086
1087int pcp_pulse(pcp_ctx_t *ctx, struct timeval *next_timeout)
1088{
1089 pcp_recv_msg_t *msg;
1090 struct timeval tmp_timeout={0, 0};
1091
1092 if (!ctx) {
1093 return PCP_ERR_BAD_ARGS;
1094 }
1095
1096 msg=&ctx->msg;
1097
1098 if (!next_timeout) {
1099 next_timeout=&tmp_timeout;
1100 }
1101
1102 memset(msg, 1, sizeof(*msg));
1103
1104 if (read_msg(ctx, msg) == PCP_ERR_SUCCESS) {
1105 struct in6_addr ip6;
1106 pcp_server_t *s;
1107 struct hserver_iter_data param={NULL, pcpe_io_event};
1108
1109 msg->received_time=time(NULL);
1110
1111 if (!validate_pcp_msg(msg)) {
1112 PCP_LOG(PCP_LOGLVL_PERR, "%s", "Invalid PCP msg");
1113 goto process_timeouts;
1114 }
1115
1116 if ((parse_response(msg)) != PCP_ERR_SUCCESS) {
1117 PCP_LOG(PCP_LOGLVL_PERR, "%s", "Cannot parse PCP msg");
1118 goto process_timeouts;
1119 }
1120
1121 pcp_fill_in6_addr(&ip6, NULL, (struct sockaddr*)&msg->rcvd_from_addr);
1122 s=get_pcp_server_by_ip(ctx, &ip6);
1123
1124 if (s) {
1125 msg->pcp_server_indx=s->index;
1126 memcpy(&msg->kd.src_ip, s->src_ip, sizeof(struct in6_addr));
1127 memcpy(&msg->kd.pcp_server_ip, s->pcp_ip, sizeof(struct in6_addr));
1128 if (msg->recv_version < 2) {
1129 memcpy(&msg->kd.nonce, &s->nonce, sizeof(struct pcp_nonce));
1130 }
1131
1132 // process pcpe_io_event for server
1133 hserver_iter(s, &param);
1134 }
1135 }
1136
1137process_timeouts:
1138 {
1139 struct hserver_iter_data param={next_timeout, pcpe_timeout};
1140 pcp_db_foreach_server(ctx, hserver_iter, &param);
1141 }
1142
1144 return (next_timeout->tv_sec * 1000) + (next_timeout->tv_usec / 1000);
1145}
1146
1148{
1149 struct timeval curtime;
1150 pcp_server_t*s;
1151
1152 if (!f)
1153 return;
1154
1155 gettimeofday(&curtime, NULL);
1157 if (s) {
1158 s->next_timeout=curtime;
1159 }
1161 f->timeout=curtime;
1162 if ((f->state != pfs_wait_for_server_init) && (f->state != pfs_idle)
1163 && (f->state != pfs_failed)) {
1164 f->state=pfs_send;
1165 }
1166}
1167
1169 void *cb_arg)
1170{
1171 if (ctx) {
1172 ctx->flow_change_cb_fun=cb_fun;
1173 ctx->flow_change_cb_arg=cb_arg;
1174 }
1175}
1176
1177static void flow_change_notify(pcp_flow_t *flow, pcp_fstate_e state)
1178{
1179 struct sockaddr_storage src_addr, ext_addr;
1180 pcp_ctx_t *ctx=flow->ctx;
1181
1182 PCP_LOG_DEBUG( "Flow's %d state changed to: %s",
1183 flow->key_bucket, dbg_get_fstate_name(state));
1184
1185 if (ctx->flow_change_cb_fun) {
1186 pcp_fill_sockaddr((struct sockaddr*)&src_addr, &flow->kd.src_ip,
1187 flow->kd.map_peer.src_port, 0, 0/* scope_id */);
1188 if (state == pcp_state_succeeded) {
1189 pcp_fill_sockaddr((struct sockaddr*)&ext_addr,
1190 &flow->map_peer.ext_ip, flow->map_peer.ext_port, 0,
1191 0/* scope_id */);
1192 } else {
1193 memset(&ext_addr, 0, sizeof(ext_addr));
1194 ext_addr.ss_family=AF_INET;
1195 }
1196 ctx->flow_change_cb_fun(flow, (struct sockaddr*)&src_addr,
1197 (struct sockaddr*)&ext_addr, state, ctx->flow_change_cb_arg);
1198 }
1199}
#define PCP_MAX_SUPPORTED_VERSION
#define PCP_SERVER_DISCOVERY_RETRY_DELAY
#define PCP_MAX_PING_COUNT
#define PCP_RETX_IRT
#define PCP_RETX_MRD
#define PCP_RETX_MRC
#define PCP_MIN_SUPPORTED_VERSION
Definition: events.cpp:8
uint uint32_t
uchar uint8_t
int pcp_eval_flow_state(pcp_flow_t *flow, pcp_fstate_e *fstate)
Definition: pcp_api.c:136
@ 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
void(* pcp_flow_change_notify)(pcp_flow_t *f, struct sockaddr *src_addr, struct sockaddr *ext_addr, pcp_fstate_e, void *cb_arg)
Definition: pcp.h:259
pcp_fstate_e
Definition: pcp.h:231
@ pcp_state_succeeded
Definition: pcp.h:233
pcp_errno
Definition: pcp.h:65
@ PCP_ERR_SUCCESS
Definition: pcp.h:66
@ PCP_ERR_BAD_ARGS
Definition: pcp.h:74
@ PCP_ERR_SEND_FAILED
Definition: pcp.h:70
pcp_errno pcp_db_foreach_flow(pcp_ctx_t *ctx, pcp_db_flow_iterate f, void *data)
pcp_server_t * get_pcp_server(pcp_ctx_t *ctx, int pcp_server_index)
void pcp_flow_clear_msg_buf(pcp_flow_t *f)
Definition: pcp_client_db.c:91
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
pcp_server_t * get_pcp_server_by_ip(pcp_ctx_t *ctx, struct in6_addr *ip)
pcp_flow_t * pcp_get_flow(struct flow_key_data *fkd, pcp_server_t *s)
struct pcp_server_state_machine pcp_server_state_machine_t
struct pcp_flow_state_trans pcp_flow_state_trans_t
void pcp_flow_updated(pcp_flow_t *f)
void pcp_set_flow_change_cb(pcp_ctx_t *ctx, pcp_flow_change_notify cb_fun, void *cb_arg)
struct pcp_flow_state_event pcp_flow_state_events_t
#define FLOW_EVENTS_SM_COUNT
#define PCP_RT(rtprev)
#define SERVER_STATE_MACHINE_COUNT
#define FLOW_TRANS_COUNT
pcp_server_state_e(* handle_server_state_event)(pcp_server_t *s)
pcp_flow_event_e(* handle_flow_state_event)(pcp_flow_t *f, pcp_recv_msg_t *msg)
int pcp_pulse(pcp_ctx_t *ctx, struct timeval *next_timeout)
pcp_errno run_server_state_machine(pcp_server_t *s, pcp_event_e event)
pcp_server_state_e
@ pss_wait_io
@ pss_ping
@ pss_unitialized
@ pss_allocated
@ pss_set_not_working
@ pss_server_restart
@ pss_not_working
@ pss_wait_io_calc_nearest_timeout
@ pss_version_negotiation
@ pss_wait_ping_resp
@ pss_send_all_msgs
@ pss_any
@ pss_server_reping
pcp_event_e
@ pcpe_timeout
@ pcpe_terminate
@ pcpe_io_event
@ pcpe_any
pcp_flow_event_e
@ fev_res_malformed_request
@ fev_res_unsupp_version
@ fev_res_address_mismatch
@ fev_res_unsupp_protocol
@ fev_failed
@ fev_server_restarted
@ fev_server_initialized
@ fev_res_success
@ fev_send
@ fev_res_user_ex_quota
@ fev_res_unsupp_opcode
@ fev_res_network_failure
@ fev_none
@ fev_res_unsupp_option
@ fev_res_exc_remote_peers
@ fev_msg_sent
@ fev_res_cant_provide_ext
@ fev_flow_timedout
@ fev_res_not_authorized
@ FEV_RES_BEGIN
@ fev_res_no_resources
@ fev_ignored
pcp_flow_state_e
@ pfs_wait_for_lifetime_renew
@ pfs_any
@ pfs_send
@ pfs_send_renew
@ pfs_wait_after_short_life_error
@ pfs_failed
@ pfs_idle
@ pfs_wait_for_server_init
@ pfs_wait_resp
int gettimeofday(struct timeval *tv, struct timezone *tz)
#define PCP_LOG_END(level)
Definition: pcp_logger.h:73
#define PCP_LOG_BEGIN(level)
Definition: pcp_logger.h:75
#define PCP_LOG(level, fmt,...)
Definition: pcp_logger.h:71
#define PCP_LOG_DEBUG(fmt,...)
Definition: pcp_logger.h:79
int validate_pcp_msg(pcp_recv_msg_t *f)
Definition: pcp_msg.c:449
void * build_pcp_msg(pcp_flow_t *flow)
Definition: pcp_msg.c:370
pcp_errno parse_response(pcp_recv_msg_t *f)
Definition: pcp_msg.c:686
#define NATPMP_OPCODE_ANNOUNCE
#define PCP_RES_ADDRESS_MISMATCH
#define PCP_OPCODE_PEER
#define PCP_OPCODE_ANNOUNCE
#define PCP_OPCODE_SADSCP
#define PCP_OPCODE_MAP
#define PCP_RES_UNSUPP_VERSION
void pcp_fill_in6_addr(struct in6_addr *dst_ip6, uint16_t *dst_port, struct sockaddr *src)
Definition: pcp_socket.c:99
ssize_t pcp_socket_recvfrom(struct pcp_ctx_s *ctx, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
Definition: pcp_socket.c:189
void pcp_fill_sockaddr(struct sockaddr *dst, struct in6_addr *sip, uint16_t sport, int ret_ipv6_mapped_ipv4, uint32_t scope_id)
Definition: pcp_socket.c:132
ssize_t pcp_socket_sendto(struct pcp_ctx_s *ctx, const void *buf, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)
Definition: pcp_socket.c:198
#define SA_LEN(addr)
Definition: pcp_socket.h:112
#define S6_ADDR32(sa6)
Definition: pcp_utils.h:114
#define UNUSED
Definition: pcp_utils.h:38
#define ssize_t
#define MSG_DONTWAIT
pcp_flow_event_e event
struct flow_key_data::mp_keydata map_peer
struct in6_addr src_ip
Definition: pcp_client_db.h:66
struct pcp_nonce nonce
Definition: pcp_client_db.h:68
struct in6_addr pcp_server_ip
Definition: pcp_client_db.h:67
uint8_t operation
Definition: pcp_client_db.h:65
struct timeval * res_timeout
pcp_recv_msg_t msg
void * flow_change_cb_arg
pcp_flow_change_notify flow_change_cb_fun
uint32_t pcp_server_indx
uint32_t pcp_msg_len
uint16_t ext_port
struct timeval timeout
uint32_t retry_count
struct pcp_ctx_s * ctx
struct flow_key_data kd
uint32_t key_bucket
struct pcp_flow_s::@5::@7 map_peer
char * pcp_msg_buffer
uint32_t recv_result
uint32_t resend_timeout
time_t recv_lifetime
struct in6_addr ext_ip
pcp_flow_state_e state
pcp_flow_event_e event
pcp_flow_state_e new_state
pcp_flow_state_e state
pcp_flow_state_e state_to
handle_flow_state_event handler
pcp_flow_state_e state_from
time_t received_time
Definition: pcp_client_db.h:92
uint32_t pcp_msg_len
Definition: pcp_client_db.h:98
uint8_t recv_dscp
Definition: pcp_client_db.h:87
uint32_t recv_epoch
Definition: pcp_client_db.h:89
uint32_t recv_result
Definition: pcp_client_db.h:91
struct flow_key_data kd
Definition: pcp_client_db.h:81
char pcp_msg_buffer[PCP_MAX_LEN]
Definition: pcp_client_db.h:99
uint32_t recv_version
Definition: pcp_client_db.h:88
struct sockaddr_storage rcvd_from_addr
Definition: pcp_client_db.h:96
uint16_t assigned_ext_port
Definition: pcp_client_db.h:86
uint32_t recv_lifetime
Definition: pcp_client_db.h:90
uint32_t pcp_server_indx
Definition: pcp_client_db.h:95
struct in6_addr assigned_ext_ip
Definition: pcp_client_db.h:85
pcp_server_state_e state
handle_server_state_event handler
pcp_flow_t * restart_flow_msg
uint32_t index
uint32_t natpmp_ext_addr
uint32_t pcp_ip[4]
pcp_flow_t * ping_flow_msg
struct timeval next_timeout
uint8_t pcp_version
struct sockaddr_storage pcp_server_saddr
pcp_server_state_e server_state
uint32_t ping_count
char pcp_server_paddr[INET6_ADDRSTRLEN]
time_t cepoch
uint32_t epoch
uint32_t src_ip[4]
uint8_t next_version
pcp_ctx_t * ctx
struct pcp_nonce nonce