Project Alice
Loading...
Searching...
No Matches
pcp_msg.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#ifdef WIN32
41#else
42#include <sys/socket.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45#endif //WIN32
46#include "pcp.h"
47#include "pcp_utils.h"
48#include "pcp_msg.h"
49#include "pcp_msg_structs.h"
50#include "pcp_logger.h"
51
52static void *add_filter_option(pcp_flow_t *f, void *cur)
53{
55
56 filter_op->option=PCP_OPTION_FILTER;
57 filter_op->reserved=0;
58 filter_op->len=htons(sizeof(pcp_filter_option_t) - sizeof(pcp_options_hdr_t));
59 filter_op->reserved2=0;
60 filter_op->filter_prefix=f->filter_prefix;
61 filter_op->filter_peer_port=f->filter_port;
62 memcpy(&filter_op->filter_peer_ip, &f->filter_ip,
63 sizeof(filter_op->filter_peer_ip));
64 cur=filter_op->next_data;
65
66 return cur;
67}
68
69static void *add_prefer_failure_option(void *cur)
70{
72
73 pfailure_op->option=PCP_OPTION_PREF_FAIL;
74 pfailure_op->reserved=0;
75 pfailure_op->len=htons(sizeof(pcp_prefer_fail_option_t) - sizeof(pcp_options_hdr_t));
76 cur=pfailure_op->next_data;
77
78 return cur;
79}
80
81static void *add_third_party_option(pcp_flow_t *f, void *cur)
82{
84
86 tp_op->reserved=0;
87 memcpy(tp_op->ip, &f->third_party_ip, sizeof(f->third_party_ip));
88 tp_op->len=htons(sizeof(*tp_op) - sizeof(pcp_options_hdr_t));
89 cur=tp_op->next_data;
90
91 return cur;
92}
93
94#ifdef PCP_EXPERIMENTAL
95static void *add_userid_option(pcp_flow_t *f, void *cur)
96{
97 pcp_userid_option_t *userid_op = (pcp_userid_option_t *) cur;
98
99 userid_op->option=PCP_OPTION_USERID;
100 userid_op->len=htons(sizeof(pcp_userid_option_t) - sizeof(pcp_options_hdr_t));
101 memcpy(&(userid_op->userid[0]), &(f->f_userid.userid[0]), MAX_USER_ID);
102 cur=userid_op + 1;
103
104 return cur;
105}
106
107static void *add_location_option(pcp_flow_t *f, void *cur)
108{
109 pcp_location_option_t *location_op = (pcp_location_option_t *) cur;
110
111 location_op->option=PCP_OPTION_LOCATION;
112 location_op->len=htons(sizeof(pcp_location_option_t) - sizeof(pcp_options_hdr_t));
113 memcpy(&(location_op->location[0]), &(f->f_location.location[0]), MAX_GEO_STR);
114 cur=location_op + 1;
115
116 return cur;
117}
118
119static void *add_deviceid_option(pcp_flow_t *f, void *cur)
120{
121 pcp_deviceid_option_t *deviceid_op = (pcp_deviceid_option_t *) cur;
122
123 deviceid_op->option=PCP_OPTION_DEVICEID;
125 deviceid_op->len=htons(sizeof(pcp_deviceid_option_t) - sizeof(pcp_options_hdr_t));
126 memcpy(&(deviceid_op->deviceid[0]), &(f->f_deviceid.deviceid[0]), MAX_DEVICE_ID);
127 cur=deviceid_op + 1;
128
130 return cur;
131}
132#endif
133
134#ifdef PCP_FLOW_PRIORITY
135static void *add_flowp_option(pcp_flow_t *f, void *cur)
136{
138
140 flowp_op->len=htons(sizeof(pcp_flow_priority_option_t) - sizeof(pcp_options_hdr_t));
141 flowp_op->dscp_up=f->flowp_dscp_up;
142 flowp_op->dscp_down=f->flowp_dscp_down;
143 cur=flowp_op->next_data;
144
145 return cur;
146}
147#endif
148
149#ifdef PCP_EXPERIMENTAL
150static inline pcp_metadata_option_t *add_md_option(pcp_flow_t *f,
151 pcp_metadata_option_t *md_opt, md_val_t *md)
152{
153 size_t len_md=md->val_len;
154 uint32_t padding=(4 - (len_md % 4)) % 4;
155 size_t pcp_msg_len=((const char*)md_opt) - f->pcp_msg_buffer;
156
157 if ( (pcp_msg_len + (sizeof(pcp_metadata_option_t) + len_md + padding)) >
158 PCP_MAX_LEN) {
159 return md_opt;
160 }
161
163 md_opt->metadata_id=htonl(md->md_id);
164 memcpy(md_opt->metadata, md->val_buf, len_md);
165 md_opt->len=htons(sizeof(*md_opt) - sizeof(pcp_options_hdr_t) + len_md + padding);
166
167 return (pcp_metadata_option_t *)(((uint8_t *)(md_opt+1)) + len_md + padding);
168}
169
170static void *add_md_options(pcp_flow_t *f, void *cur)
171{
172 uint32_t i;
173 md_val_t *md;
175
176 for (i=f->md_val_count, md=f->md_vals; i>0 && md!=NULL; --i, ++md)
177 {
178 if (md->val_len) {
179 md_opt = add_md_option(f, md_opt, md);
180 }
181 }
182 return md_opt;
183}
184#endif
185
186static pcp_errno build_pcp_options(pcp_flow_t *flow, void *cur)
187{
188#ifdef PCP_FLOW_PRIORITY
189 if (flow->flowp_option_present) {
190 cur=add_flowp_option(flow, cur);
191 }
192#endif
193 if (flow->filter_option_present) {
194 cur=add_filter_option(flow, cur);
195 }
196
197 if (flow->pfailure_option_present) {
198 cur=add_prefer_failure_option(cur);
199 }
200 if (flow->third_party_option_present) {
201 cur=add_third_party_option(flow, cur);
202 }
203#ifdef PCP_EXPERIMENTAL
204 if (flow->f_deviceid.deviceid[0] != '\0') {
205 cur=add_deviceid_option(flow, cur);
206 }
207
208 if (flow->f_userid.userid[0] != '\0') {
209 cur=add_userid_option(flow, cur);
210 }
211
212 if (flow->f_location.location[0] != '\0') {
213 cur=add_location_option(flow, cur);
214 }
215
216 if (flow->md_val_count>0) {
217 cur=add_md_options(flow, cur);
218 }
219#endif
220
221 flow->pcp_msg_len=(uint32_t)(((char*)cur) - flow->pcp_msg_buffer);
222
223 //TODO: implement building all pcp options into msg
224 return PCP_ERR_SUCCESS;
225}
226
227static pcp_errno build_pcp_peer(pcp_server_t *server, pcp_flow_t *flow,
228 void *peer_loc)
229{
230 void *next=NULL;
231
232 if (server->pcp_version == 1) {
233 pcp_peer_v1_t *peer_info=(pcp_peer_v1_t *)peer_loc;
234
235 peer_info->protocol=flow->kd.map_peer.protocol;
236 peer_info->int_port=flow->kd.map_peer.src_port;
237 peer_info->ext_port=flow->map_peer.ext_port;
238 peer_info->peer_port=flow->kd.map_peer.dst_port;
239 memcpy(peer_info->ext_ip, &flow->map_peer.ext_ip,
240 sizeof(peer_info->ext_ip));
241 memcpy(peer_info->peer_ip, &flow->kd.map_peer.dst_ip,
242 sizeof(peer_info->peer_ip));
243 next=peer_info + 1;
244 } else if (server->pcp_version == 2) {
245 pcp_peer_v2_t *peer_info=(pcp_peer_v2_t *)peer_loc;
246
247 peer_info->protocol=flow->kd.map_peer.protocol;
248 peer_info->int_port=flow->kd.map_peer.src_port;
249 peer_info->ext_port=flow->map_peer.ext_port;
250 peer_info->peer_port=flow->kd.map_peer.dst_port;
251 memcpy(peer_info->ext_ip, &flow->map_peer.ext_ip,
252 sizeof(peer_info->ext_ip));
253 memcpy(peer_info->peer_ip, &flow->kd.map_peer.dst_ip,
254 sizeof(peer_info->peer_ip));
255 peer_info->nonce=flow->kd.nonce;
256 next=peer_info + 1;
257 } else {
259 }
260 return build_pcp_options(flow, next);
261}
262
263static pcp_errno build_pcp_map(pcp_server_t *server, pcp_flow_t *flow,
264 void *map_loc)
265{
266 void *next=NULL;
267
268 if (server->pcp_version == 1) {
269 pcp_map_v1_t *map_info=(pcp_map_v1_t *)map_loc;
270
271 map_info->protocol=flow->kd.map_peer.protocol;
272 map_info->int_port=flow->kd.map_peer.src_port;
273 map_info->ext_port=flow->map_peer.ext_port;
274 memcpy(map_info->ext_ip, &flow->map_peer.ext_ip,
275 sizeof(map_info->ext_ip));
276 next=map_info + 1;
277 } else if (server->pcp_version == 2) {
278 pcp_map_v2_t *map_info=(pcp_map_v2_t *)map_loc;
279
280 map_info->protocol=flow->kd.map_peer.protocol;
281 map_info->int_port=flow->kd.map_peer.src_port;
282 map_info->ext_port=flow->map_peer.ext_port;
283 memcpy(map_info->ext_ip, &flow->map_peer.ext_ip,
284 sizeof(map_info->ext_ip));
285 map_info->nonce=flow->kd.nonce;
286 next=map_info + 1;
287 } else {
289 }
290
291 return build_pcp_options(flow, next);
292}
293
294#ifdef PCP_SADSCP
295static pcp_errno build_pcp_sadscp(pcp_server_t *server, pcp_flow_t *flow,
296 void *sadscp_loc)
297{
298 void *next=NULL;
299
300 if (server->pcp_version == 1) {
302 } else if (server->pcp_version == 2) {
303 size_t fill_len;
304 pcp_sadscp_req_t *sadscp=(pcp_sadscp_req_t *)sadscp_loc;
305
306 sadscp->nonce=flow->kd.nonce;
307 sadscp->tolerance_fields=flow->sadscp.toler_fields;
308
309 //app name fill size to multiple of 4
310 fill_len=(4-((flow->sadscp.app_name_length+2)%4))%4;
311
312 sadscp->app_name_length=flow->sadscp.app_name_length + fill_len;
313 if (flow->sadscp_app_name) {
314 memcpy(sadscp->app_name, flow->sadscp_app_name,
315 flow->sadscp.app_name_length);
316 } else {
317 memset(sadscp->app_name, 0,
318 flow->sadscp.app_name_length);
319 }
320
321 next=((uint8_t *)sadscp_loc) + sizeof(pcp_sadscp_req_t) +
322 sadscp->app_name_length;
323 } else {
325 }
326
327 return build_pcp_options(flow, next);
328}
329#endif
330
331#ifndef PCP_DISABLE_NATPMP
332static pcp_errno build_natpmp_msg(pcp_flow_t *flow)
333{
334 nat_pmp_announce_req_t *ann_msg;
335 nat_pmp_map_req_t *map_info;
336
337 switch (flow->kd.operation) {
339 ann_msg=(nat_pmp_announce_req_t *)flow->pcp_msg_buffer;
340 ann_msg->ver=0;
342 flow->pcp_msg_len=sizeof(*ann_msg);
344
345 case PCP_OPCODE_MAP:
346 map_info=(nat_pmp_map_req_t *)flow->pcp_msg_buffer;
347 switch (flow->kd.map_peer.protocol) {
348 case IPPROTO_TCP:
350 break;
351 case IPPROTO_UDP:
353 break;
354 default:
356 }
357 map_info->ver=0;
358 map_info->lifetime=htonl(flow->lifetime);
359 map_info->int_port=flow->kd.map_peer.src_port;
360 map_info->ext_port=flow->map_peer.ext_port;
361 flow->pcp_msg_len=sizeof(*map_info);
363
364 default:
366 }
367}
368#endif
369
371{
372 ssize_t ret=-1;
374 pcp_request_t *req;
375 // pointer used for referencing next data structure in linked list
376 void *next_data=NULL;
377
379
380 if (!flow) {
381 return NULL;
382 }
383
385
386 if (!pcp_server) {
387 return NULL;
388 }
389
390 if (!flow->pcp_msg_buffer) {
391 flow->pcp_msg_buffer=(char*)calloc(1, PCP_MAX_LEN);
392 if (flow->pcp_msg_buffer == NULL) {
394 "Malloc can't allocate enough memory for the pcp_flow.");
396 return NULL;
397 }
398 }
399
400 req=(pcp_request_t *)flow->pcp_msg_buffer;
401
402 if (pcp_server->pcp_version == 0) {
403 // NATPMP
404#ifndef PCP_DISABLE_NATPMP
405 ret=build_natpmp_msg(flow);
406#endif
407 } else {
408
409 req->ver=pcp_server->pcp_version;
410
411 req->r_opcode|=(uint8_t)(flow->kd.operation & 0x7f); //set opcode
412 req->req_lifetime=htonl((uint32_t)flow->lifetime);
413
414 memcpy(&req->ip, &flow->kd.src_ip, 16);
415 // next data in the packet
416 next_data=req->next_data;
417 flow->pcp_msg_len=(uint32_t)((uint8_t *)next_data - (uint8_t *)req);
418
419 switch (flow->kd.operation) {
420 case PCP_OPCODE_PEER:
421 ret=build_pcp_peer(pcp_server, flow, next_data);
422 break;
423 case PCP_OPCODE_MAP:
424 ret=build_pcp_map(pcp_server, flow, next_data);
425 break;
426#ifdef PCP_SADSCP
428 ret=build_pcp_sadscp(pcp_server, flow, next_data);
429 break;
430#endif
432 ret=0;
433 break;
434 }
435 }
436
437 if (ret < 0) {
438 PCP_LOG(PCP_LOGLVL_ERR, "%s", "Unsupported operation.");
439 free(flow->pcp_msg_buffer);
440 flow->pcp_msg_buffer=NULL;
441 flow->pcp_msg_len=0;
442 req=NULL;
443 }
444
446 return req;
447}
448
450{
451 pcp_response_t *resp;
452
453 //check size
454 if (((f->pcp_msg_len & 3) != 0) || (f->pcp_msg_len < 4)
455 || (f->pcp_msg_len > PCP_MAX_LEN)) {
456 PCP_LOG(PCP_LOGLVL_WARN, "Received packet with invalid size %d)",
457 f->pcp_msg_len);
458 return 0;
459 }
460
462 if ((resp->ver)&&!(resp->r_opcode & 0x80)) {
464 "Received packet without response bit set");
465 return 0;
466 }
467
468 if (resp->ver > PCP_MAX_SUPPORTED_VERSION) {
470 "Received PCP msg using unsupported PCP version %d", resp->ver);
471 return 0;
472 }
473
474 return 1;
475}
476
477static pcp_errno parse_options(UNUSED pcp_recv_msg_t *f, UNUSED void *r)
478{
479 //TODO: implement parsing of pcp options
480 return PCP_ERR_SUCCESS;
481}
482
483static pcp_errno parse_v1_map(pcp_recv_msg_t *f, void *r)
484{
486 size_t rest_size=f->pcp_msg_len - (((char*)r) - f->pcp_msg_buffer);
487
488 if (rest_size < sizeof(pcp_map_v1_t)) {
489 return PCP_ERR_RECV_FAILED;
490 }
491
492 m=(pcp_map_v1_t *)r;
493 f->kd.map_peer.src_port=m->int_port;
494 f->kd.map_peer.protocol=m->protocol;
495 f->assigned_ext_port=m->ext_port;
496 memcpy(&f->assigned_ext_ip, m->ext_ip, sizeof(f->assigned_ext_ip));
497
498 if (rest_size > sizeof(pcp_map_v1_t)) {
499 return parse_options(f, m + 1);
500 }
501 return PCP_ERR_SUCCESS;
502}
503
504static pcp_errno parse_v2_map(pcp_recv_msg_t *f, void *r)
505{
507 size_t rest_size=f->pcp_msg_len - (((char*)r) - f->pcp_msg_buffer);
508
509 if (rest_size < sizeof(pcp_map_v2_t)) {
510 return PCP_ERR_RECV_FAILED;
511 }
512
513 m=(pcp_map_v2_t *)r;
514 f->kd.nonce=m->nonce;
515 f->kd.map_peer.src_port=m->int_port;
516 f->kd.map_peer.protocol=m->protocol;
517 f->assigned_ext_port=m->ext_port;
518 memcpy(&f->assigned_ext_ip, m->ext_ip, sizeof(f->assigned_ext_ip));
519
520 if (rest_size > sizeof(pcp_map_v2_t)) {
521 return parse_options(f, m + 1);
522 }
523 return PCP_ERR_SUCCESS;
524}
525
526static pcp_errno parse_v1_peer(pcp_recv_msg_t *f, void *r)
527{
529 size_t rest_size=f->pcp_msg_len - (((char*)r) - f->pcp_msg_buffer);
530
531 if (rest_size < sizeof(pcp_peer_v1_t)) {
532 return PCP_ERR_RECV_FAILED;
533 }
534
535 m=(pcp_peer_v1_t *)r;
536 f->kd.map_peer.src_port=m->int_port;
537 f->kd.map_peer.protocol=m->protocol;
538 f->kd.map_peer.dst_port=m->peer_port;
539 f->assigned_ext_port=m->ext_port;
540 memcpy(&f->kd.map_peer.dst_ip, m->peer_ip, sizeof(f->kd.map_peer.dst_ip));
541 memcpy(&f->assigned_ext_ip, m->ext_ip, sizeof(f->assigned_ext_ip));
542
543 if (rest_size > sizeof(pcp_peer_v1_t)) {
544 return parse_options(f, m + 1);
545 }
546 return PCP_ERR_SUCCESS;
547}
548
549static pcp_errno parse_v2_peer(pcp_recv_msg_t *f, void *r)
550{
552 size_t rest_size=f->pcp_msg_len - (((char*)r) - f->pcp_msg_buffer);
553
554 if (rest_size < sizeof(pcp_peer_v2_t)) {
555 return PCP_ERR_RECV_FAILED;
556 }
557
558 m=(pcp_peer_v2_t *)r;
559 f->kd.nonce=m->nonce;
560 f->kd.map_peer.src_port=m->int_port;
561 f->kd.map_peer.protocol=m->protocol;
562 f->kd.map_peer.dst_port=m->peer_port;
563 f->assigned_ext_port=m->ext_port;
564 memcpy(&f->kd.map_peer.dst_ip, m->peer_ip, sizeof(f->kd.map_peer.dst_ip));
565 memcpy(&f->assigned_ext_ip, m->ext_ip, sizeof(f->assigned_ext_ip));
566
567 if (rest_size > sizeof(pcp_peer_v2_t)) {
568 return parse_options(f, m + 1);
569 }
570 return PCP_ERR_SUCCESS;
571}
572
573#ifdef PCP_SADSCP
574static pcp_errno parse_sadscp(pcp_recv_msg_t *f, void *r)
575{
577 size_t rest_size = f->pcp_msg_len - (((char*) r) - f->pcp_msg_buffer);
578
579 if (rest_size < sizeof(pcp_sadscp_resp_t)) {
580 return PCP_ERR_RECV_FAILED;
581 }
582 d = (pcp_sadscp_resp_t *) r;
583 f->kd.nonce = d->nonce;
584 f->recv_dscp = d->a_r_dscp & (0x3f); //mask 6 lower bits
585
586 return PCP_ERR_SUCCESS;
587}
588#endif
589
590#ifndef PCP_DISABLE_NATPMP
591static pcp_errno parse_v0_resp(pcp_recv_msg_t *f, pcp_response_t *resp)
592{
593 switch(f->kd.operation) {
595 if (f->pcp_msg_len == sizeof(nat_pmp_announce_resp_t)) {
597
598 f->recv_epoch=ntohl(r->epoch);
599 S6_ADDR32(&f->assigned_ext_ip)[0]=0;
600 S6_ADDR32(&f->assigned_ext_ip)[1]=0;
601 S6_ADDR32(&f->assigned_ext_ip)[2]=htonl(0xFFFF);
603
604 return PCP_ERR_SUCCESS;
605 }
606 break;
609 if (f->pcp_msg_len == sizeof(nat_pmp_map_resp_t)) {
611
614 f->recv_epoch=ntohl(r->epoch);
615 f->recv_lifetime=ntohl(r->lifetime);
616 f->recv_result=ntohs(r->result);
619 IPPROTO_TCP : IPPROTO_UDP);
621 return PCP_ERR_SUCCESS;
622 }
623 break;
624 default:
625 break;
626 }
627
628 if (f->pcp_msg_len == sizeof(nat_pmp_inv_version_resp_t)) {
630
631 f->recv_result=ntohs(r->result);
632 f->recv_epoch=ntohl(r->epoch);
633 return PCP_ERR_SUCCESS;
634 }
635
636 return PCP_ERR_RECV_FAILED;
637}
638#endif
639
640static pcp_errno parse_v1_resp(pcp_recv_msg_t *f, pcp_response_t *resp)
641{
642 if (f->pcp_msg_len < sizeof(pcp_response_t)) {
643 return PCP_ERR_RECV_FAILED;
644 }
645
646 f->recv_lifetime=ntohl(resp->lifetime);
647 f->recv_epoch=ntohl(resp->epochtime);
648
649 switch (f->kd.operation) {
651 return PCP_ERR_SUCCESS;
652 case PCP_OPCODE_MAP:
653 return parse_v1_map(f, resp->next_data);
654 case PCP_OPCODE_PEER:
655 return parse_v1_peer(f, resp->next_data);
656 default:
657 return PCP_ERR_RECV_FAILED;
658 }
659}
660
661static pcp_errno parse_v2_resp(pcp_recv_msg_t *f, pcp_response_t *resp)
662{
663 if (f->pcp_msg_len < sizeof(pcp_response_t)) {
664 return PCP_ERR_RECV_FAILED;
665 }
666
667 f->recv_lifetime=ntohl(resp->lifetime);
668 f->recv_epoch=ntohl(resp->epochtime);
669
670 switch (f->kd.operation) {
672 return PCP_ERR_SUCCESS;
673 case PCP_OPCODE_MAP:
674 return parse_v2_map(f, resp->next_data);
675 case PCP_OPCODE_PEER:
676 return parse_v2_peer(f, resp->next_data);
677#ifdef PCP_SADSCP
679 return parse_sadscp(f, resp->next_data);
680#endif
681 default:
682 return PCP_ERR_RECV_FAILED;
683 }
684}
685
687{
689
690 f->recv_version=resp->ver;
691 f->recv_result=resp->result_code;
692 memset(&f->kd, 0, sizeof(f->kd));
693
694 f->kd.operation=resp->r_opcode & 0x7f;
695
696 PCP_LOG(PCP_LOGLVL_DEBUG, "parse_response: version: %d", f->recv_version);
697 PCP_LOG(PCP_LOGLVL_DEBUG, "parse_response: result: %d", f->recv_result);
698
699 switch (f->recv_version) {
700#ifndef PCP_DISABLE_NATPMP
701 case 0:
702 return parse_v0_resp(f, resp);
703 break;
704#endif
705 case 1:
706 return parse_v1_resp(f, resp);
707 break;
708 case 2:
709 return parse_v2_resp(f, resp);
710 break;
711 }
713}
714
#define PCP_MAX_SUPPORTED_VERSION
uint uint32_t
uchar uint8_t
@ PCP_LOGLVL_ERR
Definition: pcp.h:86
@ PCP_LOGLVL_DEBUG
Definition: pcp.h:90
@ PCP_LOGLVL_WARN
Definition: pcp.h:87
pcp_errno
Definition: pcp.h:65
@ PCP_ERR_SUCCESS
Definition: pcp.h:66
@ PCP_ERR_RECV_FAILED
Definition: pcp.h:71
@ PCP_ERR_UNSUP_VERSION
Definition: pcp.h:72
pcp_server_t * get_pcp_server(pcp_ctx_t *ctx, int pcp_server_index)
#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
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_MAP_UDP
@ PCP_OPTION_PREF_FAIL
@ PCP_OPTION_FILTER
@ PCP_OPTION_LOCATION
@ PCP_OPTION_FLOW_PRIORITY
@ PCP_OPTION_USERID
@ PCP_OPTION_3RD_PARTY
@ PCP_OPTION_METADATA
@ PCP_OPTION_DEVICEID
#define MAX_DEVICE_ID
#define NATPMP_OPCODE_ANNOUNCE
#define PCP_RES_UNSUPP_OPCODE
#define PCP_OPCODE_PEER
#define PCP_RES_SUCCESS
#define PCP_OPCODE_ANNOUNCE
struct pcp_sadscp_req pcp_sadscp_req_t
#define NATPMP_OPCODE_MAP_TCP
#define PCP_RES_UNSUPP_PROTOCOL
#define MAX_GEO_STR
#define PCP_MAX_LEN
#define PCP_OPCODE_SADSCP
#define PCP_OPCODE_MAP
#define MAX_USER_ID
#define S6_ADDR32(sa6)
Definition: pcp_utils.h:114
#define UNUSED
Definition: pcp_utils.h:38
#define ssize_t
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 pcp_nonce nonce
Definition: pcp_client_db.h:68
uint8_t operation
Definition: pcp_client_db.h:65
char deviceid[MAX_DEVICE_ID]
uint32_t filter_peer_ip[4]
uint32_t pcp_server_indx
uint32_t pcp_msg_len
uint8_t third_party_option_present
uint16_t ext_port
uint8_t filter_option_present
uint8_t filter_prefix
uint16_t filter_port
struct pcp_ctx_s * ctx
struct flow_key_data kd
uint32_t lifetime
struct in6_addr third_party_ip
char * pcp_msg_buffer
struct in6_addr filter_ip
struct pcp_flow_s::@6::@8 map_peer
uint8_t pfailure_option_present
struct in6_addr ext_ip
char location[MAX_GEO_STR]
uint8_t protocol
uint32_t ext_ip[4]
uint16_t ext_port
uint16_t int_port
uint32_t ext_ip[4]
uint16_t int_port
struct pcp_nonce nonce
uint16_t ext_port
uint8_t protocol
uint16_t int_port
uint32_t ext_ip[4]
uint32_t peer_ip[4]
uint8_t protocol
uint16_t peer_port
uint16_t ext_port
uint8_t protocol
uint32_t ext_ip[4]
struct pcp_nonce nonce
uint16_t int_port
uint32_t peer_ip[4]
uint16_t ext_port
uint16_t peer_port
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
uint16_t assigned_ext_port
Definition: pcp_client_db.h:86
uint32_t recv_lifetime
Definition: pcp_client_db.h:90
struct in6_addr assigned_ext_ip
Definition: pcp_client_db.h:85
uint32_t lifetime
uint8_t result_code
uint32_t epochtime
uint8_t r_opcode
uint8_t next_data[0]
struct pcp_nonce nonce
uint8_t tolerance_fields
uint8_t app_name_length
uint8_t pcp_version
char userid[MAX_USER_ID]