1/* $Id: pcpserver.c,v 1.39 2015/06/22 07:28:21 nanard Exp $ */ 2/* MiniUPnP project 3 * Website : http://miniupnp.free.fr/ 4 * Author : Peter Tatrai 5 6Copyright (c) 2013 by Cisco Systems, Inc. 7All rights reserved. 8 9Redistribution and use in source and binary forms, with or without 10modification, are permitted provided that the following conditions are met: 11 12 * Redistributions of source code must retain the above copyright notice, 13 this list of conditions and the following disclaimer. 14 * Redistributions in binary form must reproduce the above copyright notice, 15 this list of conditions and the following disclaimer in the documentation 16 and/or other materials provided with the distribution. 17 * The name of the author may not be used to endorse or promote products 18 derived from this software without specific prior written permission. 19 20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30POSSIBILITY OF SUCH DAMAGE. 31*/ 32 33/* Current assumptions: 34 - IPv4 is always NATted (internal -> external) 35 - IPv6 is always firewalled (this may need some work, NAT6* do exist) 36 37 - we make the judgement based on (in order, picking first one available): 38 - third party adress 39 - internal client address 40 41 TODO : handle NAT46, NAT64, NPT66. In addition, beyond FW/NAT 42 choice, should also add for proxy (=as much as possible transparent 43 pass-through to one or more servers). 44 45 TODO: IPv6 permission handling (for the time being, we just assume 46 anyone on IPv6 is a good guy, but fixing that would include 47 upnppermissions rewrite to be AF neutral). 48*/ 49 50#include "config.h" 51 52#ifdef ENABLE_PCP 53 54#include <stdio.h> 55#include <stdlib.h> 56#include <string.h> 57#include <unistd.h> 58#include <errno.h> 59#include <string.h> 60#include <sys/types.h> 61#include <sys/socket.h> 62#include <sys/time.h> 63#include <netinet/in.h> 64#include <arpa/inet.h> 65#include <netdb.h> 66#include <time.h> 67#include <signal.h> 68#include <stdio.h> 69#include <ctype.h> 70#include <syslog.h> 71 72#include "pcpserver.h" 73#include "natpmp.h" 74#include "macros.h" 75#include "upnpglobalvars.h" 76#include "pcplearndscp.h" 77#include "upnpredirect.h" 78#include "commonrdr.h" 79#include "getifaddr.h" 80#include "asyncsendto.h" 81#include "upnputils.h" 82#include "portinuse.h" 83#include "pcp_msg_struct.h" 84#ifdef ENABLE_UPNPPINHOLE 85#include "upnppinhole.h" 86#endif /* ENABLE_UPNPPINHOLE */ 87 88 89#ifdef PCP_PEER 90/* TODO make this platform independent */ 91#ifdef USE_NETFILTER 92#include "netfilter/iptcrdr.h" 93#else 94#error "PCP Peer is only supported with NETFILTER" 95#endif /* USE_NETFILTER */ 96#endif /* PCP_PEER */ 97 98/* server specific information */ 99struct pcp_server_info { 100 uint8_t server_version; 101}; 102 103/* default server settings, highest version supported is the default */ 104static struct pcp_server_info this_server_info = {2}; 105 106 107/* structure holding information from PCP msg*/ 108/* all variables are in host byte order except IP addresses */ 109typedef struct pcp_info { 110 uint8_t version; 111 uint8_t opcode; 112 uint8_t result_code; 113 uint32_t lifetime; /* lifetime of the mapping */ 114 uint32_t epochtime; 115 /* both MAP and PEER opcode specific information */ 116 uint32_t nonce[3]; /* random value generated by client */ 117 uint8_t protocol; 118 uint16_t int_port; 119 const struct in6_addr *int_ip; /* in network order */ 120 uint16_t ext_port; 121 const struct in6_addr *ext_ip; /* Suggested external IP in network order*/ 122 /* PEER specific information */ 123#ifdef PCP_PEER 124 uint16_t peer_port; 125 const struct in6_addr *peer_ip; /* Destination IP in network order */ 126#endif /* PCP_PEER */ 127 128#ifdef PCP_SADSCP 129 /* SADSCP specific information */ 130 uint8_t delay_tolerance; 131 uint8_t loss_tolerance; 132 uint8_t jitter_tolerance; 133 uint8_t app_name_len; 134 const char* app_name; 135 uint8_t sadscp_dscp; 136 uint8_t matched_name; 137 int8_t is_sadscp_op; 138#endif 139 140#ifdef PCP_FLOWP 141 uint8_t dscp_up; 142 uint8_t dscp_down; 143 int flowp_present; 144#endif 145 uint8_t is_map_op; 146 uint8_t is_peer_op; 147 const struct in6_addr *thirdp_ip; 148 const struct in6_addr *mapped_ip; 149 char mapped_str[INET6_ADDRSTRLEN]; 150 int pfailure_present; 151 struct in6_addr sender_ip; 152 int is_fw; /* is this firewall operation? if not, nat. */ 153 char desc[64]; 154} pcp_info_t; 155 156#ifdef PCP_SADSCP 157int get_dscp_value(pcp_info_t *pcp_msg_info) { 158 159 unsigned int ind; 160 161 for (ind = 0; ind < num_dscp_values; ind++) { 162 163 if ((dscp_values_list[ind].app_name) && 164 (!strcmp(dscp_values_list[ind].app_name, 165 pcp_msg_info->app_name)) && 166 (pcp_msg_info->delay_tolerance == dscp_values_list[ind].delay) && 167 (pcp_msg_info->loss_tolerance == dscp_values_list[ind].loss) && 168 (pcp_msg_info->jitter_tolerance == dscp_values_list[ind].jitter) 169 ) 170 { 171 pcp_msg_info->sadscp_dscp = dscp_values_list[ind].dscp_value; 172 pcp_msg_info->matched_name = 1; 173 return 0; 174 } else 175 if ((pcp_msg_info->app_name_len==0) && 176 (dscp_values_list[ind].app_name_len==0) && 177 (pcp_msg_info->delay_tolerance == dscp_values_list[ind].delay) && 178 (pcp_msg_info->loss_tolerance == dscp_values_list[ind].loss) && 179 (pcp_msg_info->jitter_tolerance == dscp_values_list[ind].jitter) 180 ) 181 { 182 pcp_msg_info->sadscp_dscp = dscp_values_list[ind].dscp_value; 183 pcp_msg_info->matched_name = 0; 184 return 0; 185 } else 186 if ((dscp_values_list[ind].app_name_len==0) && 187 (pcp_msg_info->delay_tolerance == dscp_values_list[ind].delay) && 188 (pcp_msg_info->loss_tolerance == dscp_values_list[ind].loss) && 189 (pcp_msg_info->jitter_tolerance == dscp_values_list[ind].jitter) 190 ) 191 { 192 pcp_msg_info->sadscp_dscp = dscp_values_list[ind].dscp_value; 193 pcp_msg_info->matched_name = 0; 194 return 0; 195 } 196 } 197 //if nothing matched return Default value i.e. 0 198 pcp_msg_info->sadscp_dscp = 0; 199 pcp_msg_info->matched_name = 0; 200 return 0; 201} 202#endif 203/* 204 * Function extracting information from common_req (common request header) 205 * into pcp_msg_info. 206 * @return : when no problem occurred 0 is returned, 1 otherwise and appropriate 207 * result code is assigned to pcp_msg_info->result_code to indicate 208 * what kind of error occurred 209 */ 210static int parseCommonRequestHeader(const pcp_request_t *common_req, pcp_info_t *pcp_msg_info) 211{ 212 pcp_msg_info->version = common_req->ver ; 213 pcp_msg_info->opcode = common_req->r_opcode & 0x7f; 214 pcp_msg_info->lifetime = ntohl(common_req->req_lifetime); 215 pcp_msg_info->int_ip = &common_req->ip; 216 pcp_msg_info->mapped_ip = &common_req->ip; 217 218 219 if ( (common_req->ver > this_server_info.server_version) ) { 220 pcp_msg_info->result_code = PCP_ERR_UNSUPP_VERSION; 221 return 1; 222 } 223 224 if (pcp_msg_info->lifetime > max_lifetime ) { 225 pcp_msg_info->lifetime = max_lifetime; 226 } 227 228 if ( (pcp_msg_info->lifetime < min_lifetime) && (pcp_msg_info->lifetime != 0) ) { 229 pcp_msg_info->lifetime = min_lifetime; 230 } 231 232 return 0; 233} 234 235#ifdef DEBUG 236static void printMAPOpcodeVersion1(const pcp_map_v1_t *map_buf) 237{ 238 char map_addr[INET6_ADDRSTRLEN]; 239 syslog(LOG_DEBUG, "PCP MAP: v1 Opcode specific information. \n"); 240 syslog(LOG_DEBUG, "MAP protocol: \t\t %d\n",map_buf->protocol ); 241 syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", ntohs(map_buf->int_port) ); 242 syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", ntohs(map_buf->ext_port) ); 243 syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6, 244 &map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN)); 245} 246 247static void printMAPOpcodeVersion2(const pcp_map_v2_t *map_buf) 248{ 249 char map_addr[INET6_ADDRSTRLEN]; 250 syslog(LOG_DEBUG, "PCP MAP: v2 Opcode specific information."); 251 syslog(LOG_DEBUG, "MAP nonce: \t%08x%08x%08x", 252 map_buf->nonce[0], map_buf->nonce[1], map_buf->nonce[2]); 253 syslog(LOG_DEBUG, "MAP protocol:\t%d", map_buf->protocol); 254 syslog(LOG_DEBUG, "MAP int port:\t%d", ntohs(map_buf->int_port)); 255 syslog(LOG_DEBUG, "MAP ext port:\t%d", ntohs(map_buf->ext_port)); 256 syslog(LOG_DEBUG, "MAP Ext IP: \t%s", inet_ntop(AF_INET6, 257 &map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN)); 258} 259#endif /* DEBUG */ 260 261static int parsePCPMAP_version1(const pcp_map_v1_t *map_v1, 262 pcp_info_t *pcp_msg_info) 263{ 264 pcp_msg_info->is_map_op = 1; 265 pcp_msg_info->protocol = map_v1->protocol; 266 pcp_msg_info->int_port = ntohs(map_v1->int_port); 267 pcp_msg_info->ext_port = ntohs(map_v1->ext_port); 268 269 pcp_msg_info->ext_ip = &(map_v1->ext_ip); 270 271 if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){ 272 syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value."); 273 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 274 return 1; 275 } 276 return 0; 277} 278 279static int parsePCPMAP_version2(const pcp_map_v2_t *map_v2, 280 pcp_info_t *pcp_msg_info) 281{ 282 pcp_msg_info->is_map_op = 1; 283 memcpy(pcp_msg_info->nonce, map_v2->nonce, 12); 284 pcp_msg_info->protocol = map_v2->protocol; 285 pcp_msg_info->int_port = ntohs(map_v2->int_port); 286 pcp_msg_info->ext_port = ntohs(map_v2->ext_port); 287 288 pcp_msg_info->ext_ip = &(map_v2->ext_ip); 289 290 if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ) { 291 syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value."); 292 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 293 return PCP_ERR_MALFORMED_REQUEST; 294 } 295 296 return 0; 297} 298 299#ifdef PCP_PEER 300#ifdef DEBUG 301static void printPEEROpcodeVersion1(pcp_peer_v1_t *peer_buf) 302{ 303 char ext_addr[INET6_ADDRSTRLEN]; 304 char peer_addr[INET6_ADDRSTRLEN]; 305 syslog(LOG_DEBUG, "PCP PEER: v1 Opcode specific information. \n"); 306 syslog(LOG_DEBUG, "Protocol: \t\t %d\n",peer_buf->protocol ); 307 syslog(LOG_DEBUG, "Internal port: \t\t %d\n", ntohs(peer_buf->int_port) ); 308 syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->ext_ip, 309 ext_addr,INET6_ADDRSTRLEN)); 310 syslog(LOG_DEBUG, "External port port: \t\t %d\n", ntohs(peer_buf->ext_port) ); 311 syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->peer_ip, 312 peer_addr,INET6_ADDRSTRLEN)); 313 syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", ntohs(peer_buf->peer_port) ); 314} 315 316static void printPEEROpcodeVersion2(pcp_peer_v2_t *peer_buf) 317{ 318 char ext_addr[INET6_ADDRSTRLEN]; 319 char peer_addr[INET6_ADDRSTRLEN]; 320 321 syslog(LOG_DEBUG, "PCP PEER: v2 Opcode specific information."); 322 syslog(LOG_DEBUG, "nonce: \t%08x%08x%08x", 323 peer_buf->nonce[0], peer_buf->nonce[1], peer_buf->nonce[2]); 324 syslog(LOG_DEBUG, "Protocol: \t%d",peer_buf->protocol ); 325 syslog(LOG_DEBUG, "Internal port:\t%d", ntohs(peer_buf->int_port) ); 326 syslog(LOG_DEBUG, "External IP: \t%s", inet_ntop(AF_INET6, &peer_buf->ext_ip, 327 ext_addr,INET6_ADDRSTRLEN)); 328 syslog(LOG_DEBUG, "External port:\t%d", ntohs(peer_buf->ext_port) ); 329 syslog(LOG_DEBUG, "PEER IP: \t%s", inet_ntop(AF_INET6, &peer_buf->peer_ip, 330 peer_addr,INET6_ADDRSTRLEN)); 331 syslog(LOG_DEBUG, "PEER port: \t%d", ntohs(peer_buf->peer_port) ); 332} 333#endif /* DEBUG */ 334 335/* 336 * Function extracting information from peer_buf to pcp_msg_info 337 * @return : when no problem occurred 0 is returned, 1 otherwise 338 */ 339static int parsePCPPEER_version1(pcp_peer_v1_t *peer_buf, \ 340 pcp_info_t *pcp_msg_info) 341{ 342 pcp_msg_info->is_peer_op = 1; 343 pcp_msg_info->protocol = peer_buf->protocol; 344 pcp_msg_info->int_port = ntohs(peer_buf->int_port); 345 pcp_msg_info->ext_port = ntohs(peer_buf->ext_port); 346 pcp_msg_info->peer_port = ntohs(peer_buf->peer_port); 347 348 pcp_msg_info->ext_ip = &peer_buf->ext_ip; 349 pcp_msg_info->peer_ip = &peer_buf->peer_ip; 350 351 if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){ 352 syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value."); 353 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 354 return 1; 355 } 356 return 0; 357} 358 359/* 360 * Function extracting information from peer_buf to pcp_msg_info 361 * @return : when no problem occurred 0 is returned, 1 otherwise 362 */ 363static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \ 364 pcp_info_t *pcp_msg_info) 365{ 366 pcp_msg_info->is_peer_op = 1; 367 memcpy(pcp_msg_info->nonce, peer_buf->nonce, 12); 368 pcp_msg_info->protocol = peer_buf->protocol; 369 pcp_msg_info->int_port = ntohs(peer_buf->int_port); 370 pcp_msg_info->ext_port = ntohs(peer_buf->ext_port); 371 pcp_msg_info->peer_port = ntohs(peer_buf->peer_port); 372 373 pcp_msg_info->ext_ip = &peer_buf->ext_ip; 374 pcp_msg_info->peer_ip = &peer_buf->peer_ip; 375 376 if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){ 377 syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value."); 378 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 379 return 1; 380 } 381 return 0; 382} 383#endif /* PCP_PEER */ 384 385#ifdef PCP_SADSCP 386#ifdef DEBUG 387static void printSADSCPOpcode(pcp_sadscp_req_t *sadscp) { 388 unsigned char sadscp_tol; 389 sadscp_tol = sadscp->tolerance_fields; 390 391 syslog(LOG_DEBUG, "PCP SADSCP: Opcode specific information.\n"); 392 syslog(LOG_DEBUG, "Delay tolerance %d \n", (sadscp_tol>>6)&3 ); 393 syslog(LOG_DEBUG, "Loss tolerance %d \n", (sadscp_tol>>4)&3); 394 syslog(LOG_DEBUG, "Jitter tolerance %d \n", (sadscp_tol>>2)&3); 395 syslog(LOG_DEBUG, "RRR %d \n", sadscp_tol&3); 396 syslog(LOG_DEBUG, "AppName Length %d \n", sadscp->app_name_length); 397 if (sadscp->app_name) { 398 syslog(LOG_DEBUG, "Application name %.*s \n", sadscp->app_name_length, 399 sadscp->app_name); 400 } 401} 402#endif //DEBUG 403 404static int parseSADSCP(pcp_sadscp_req_t *sadscp, pcp_info_t *pcp_msg_info) { 405 406 pcp_msg_info->delay_tolerance = (sadscp->tolerance_fields>>6)&3; 407 pcp_msg_info->loss_tolerance = (sadscp->tolerance_fields>>4)&3; 408 pcp_msg_info->jitter_tolerance = (sadscp->tolerance_fields>>2)&3; 409 410 if (pcp_msg_info->delay_tolerance == 3 ) { 411 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 412 return 1; 413 } 414 if ( pcp_msg_info->loss_tolerance == 3 ) { 415 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 416 return 1; 417 } 418 if ( pcp_msg_info->jitter_tolerance == 3 ) { 419 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 420 return 1; 421 } 422 423 pcp_msg_info->app_name = sadscp->app_name; 424 pcp_msg_info->app_name_len = sadscp->app_name_length; 425 426 return 0; 427} 428#endif 429 430static int parsePCPOption(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info) 431{ 432#ifdef DEBUG 433 char third_addr[INET6_ADDRSTRLEN]; 434#endif 435 unsigned short option_length; 436 437 pcp_3rd_party_option_t* opt_3rd; 438#ifdef PCP_FLOWP 439 pcp_flow_priority_option_t* opt_flp; 440#endif 441 pcp_filter_option_t* opt_filter; 442 pcp_prefer_fail_option_t* opt_prefail; 443 pcp_options_hdr_t* opt_hdr; 444 445 opt_hdr = (pcp_options_hdr_t*)pcp_buf; 446 447 /* Do centralized option sanity checks here. */ 448 449 if (remain < (int)sizeof(*opt_hdr)) { 450 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 451 return 0; 452 } 453 454 option_length = ntohs(opt_hdr->len) + 4; 455 456 if (remain < option_length) { 457 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 458 return 0; 459 } 460 461 switch (opt_hdr->code) { 462 463 case PCP_OPTION_3RD_PARTY: 464 465 opt_3rd = (pcp_3rd_party_option_t*)pcp_buf; 466 if ( option_length != sizeof(*opt_3rd) ) { 467 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 468 return 0; 469 } 470#ifdef DEBUG 471 syslog(LOG_DEBUG, "PCP OPTION: \t Third party \n"); 472 syslog(LOG_DEBUG, "Third PARTY IP: \t %s\n", inet_ntop(AF_INET6, 473 &(opt_3rd->ip), third_addr, INET6_ADDRSTRLEN)); 474#endif 475 if (pcp_msg_info->thirdp_ip ) { 476 syslog(LOG_ERR, "PCP: THIRD PARTY OPTION was already present. \n"); 477 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 478 return 0; 479 } 480 else { 481 pcp_msg_info->thirdp_ip = &opt_3rd->ip; 482 pcp_msg_info->mapped_ip = &opt_3rd->ip; 483 } 484 break; 485 486 case PCP_OPTION_PREF_FAIL: 487 488 opt_prefail = (pcp_prefer_fail_option_t*)pcp_buf; 489 490 if ( option_length != sizeof(*opt_prefail) ) { 491 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 492 return 0; 493 } 494#ifdef DEBUG 495 syslog(LOG_DEBUG, "PCP OPTION: \t Prefer failure \n"); 496#endif 497 if (pcp_msg_info->opcode != PCP_OPCODE_MAP) { 498 syslog(LOG_DEBUG, "PCP: Unsupported OPTION for given OPCODE.\n"); 499 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 500 } 501 if (pcp_msg_info->pfailure_present != 0 ) { 502 syslog(LOG_DEBUG, "PCP: PREFER FAILURE OPTION was already present. \n"); 503 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 504 } 505 else { 506 pcp_msg_info->pfailure_present = 1; 507 } 508 break; 509 510 case PCP_OPTION_FILTER: 511 /* TODO fully implement filter */ 512 opt_filter = (pcp_filter_option_t*)pcp_buf; 513 514 if ( option_length != sizeof(*opt_filter) ) { 515 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 516 return 0; 517 } 518#ifdef DEBUG 519 syslog(LOG_DEBUG, "PCP OPTION: \t Filter\n"); 520#endif 521 if (pcp_msg_info->opcode != PCP_OPCODE_MAP) { 522 syslog(LOG_ERR, "PCP: Unsupported OPTION for given OPCODE.\n"); 523 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 524 return 0; 525 } 526 break; 527 528#ifdef PCP_FLOWP 529 case PCP_OPTION_FLOW_PRIORITY: 530 531#ifdef DEBUG 532 syslog(LOG_DEBUG, "PCP OPTION: \t Flow priority\n"); 533#endif 534 opt_flp = (pcp_flow_priority_option_t*)pcp_buf; 535 536 if ( option_length != sizeof (*opt_flp) ) { 537 syslog(LOG_ERR, "PCP: Error processing DSCP. sizeof %d and remaining %d . flow len %d \n", 538 (int)sizeof(pcp_flow_priority_option_t), remain, opt_flp->len); 539 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 540 return 0; 541 } 542 543#ifdef DEBUG 544 syslog(LOG_DEBUG, "DSCP UP: \t %d \n", opt_flp->dscp_up); 545 syslog(LOG_DEBUG, "DSCP DOWN: \t %d \n", opt_flp->dscp_down); 546#endif 547 pcp_msg_info->dscp_up = opt_flp->dscp_up; 548 pcp_msg_info->dscp_down = opt_flp->dscp_down; 549 pcp_msg_info->flowp_present = 1; 550 551 break; 552#endif 553 default: 554 if (opt_hdr->code < 128) { 555 syslog(LOG_ERR, "PCP: Unrecognized mandatory PCP OPTION: %d \n", opt_hdr->code); 556 /* Mandatory to understand */ 557 pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION; 558 remain = 0; 559 break; 560 } 561 /* TODO - log optional not understood options? */ 562 break; 563 } 564 return option_length; 565} 566 567 568static void parsePCPOptions(void* pcp_buf, int remain, pcp_info_t *pcp_msg_info) 569{ 570 int option_length; 571 572 while (remain > 0) { 573 option_length = parsePCPOption(pcp_buf, remain, pcp_msg_info); 574 if (!option_length) 575 break; 576 remain -= option_length; 577 pcp_buf += option_length; 578 } 579} 580 581 582/* CheckExternalAddress() 583 * Check that suggested external address in request match a real external 584 * IP address. 585 * Suggested address can also be 0 IPv4 or IPv6 address. 586 * (see http://tools.ietf.org/html/rfc6887#section-10 ) 587 * return values : 588 * 0 : check is OK 589 * -1 : check failed */ 590static int CheckExternalAddress(pcp_info_t* pcp_msg_info) 591{ 592 /* can contain a IPv4-mapped IPv6 address */ 593 static struct in6_addr external_addr; 594 int af; 595 596 af = IN6_IS_ADDR_V4MAPPED(pcp_msg_info->mapped_ip) 597 ? AF_INET : AF_INET6; 598 599 pcp_msg_info->is_fw = af == AF_INET6; 600 601 if (pcp_msg_info->is_fw) { 602 external_addr = *pcp_msg_info->mapped_ip; 603 } else { 604 /* TODO : be able to handle case with multiple 605 * external addresses */ 606 if(use_ext_ip_addr) { 607 if (inet_pton(AF_INET, use_ext_ip_addr, 608 ((uint32_t*)external_addr.s6_addr)+3) == 1) { 609 ((uint32_t*)external_addr.s6_addr)[0] = 0; 610 ((uint32_t*)external_addr.s6_addr)[1] = 0; 611 ((uint32_t*)external_addr.s6_addr)[2] = htonl(0xFFFF); 612 } else if (inet_pton(AF_INET6, use_ext_ip_addr, external_addr.s6_addr) 613 != 1) { 614 pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; 615 return -1; 616 } 617 } else { 618 if(!ext_if_name || ext_if_name[0]=='\0') { 619 pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; 620 return -1; 621 } 622 if(getifaddr_in6(ext_if_name, af, &external_addr) < 0) { 623 pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; 624 return -1; 625 } 626 } 627 } 628 if (pcp_msg_info->ext_ip == NULL || 629 IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip) || 630 (IN6_IS_ADDR_V4MAPPED(pcp_msg_info->ext_ip) 631 && ((uint32_t *)pcp_msg_info->ext_ip->s6_addr)[3] == INADDR_ANY)) { 632 /* no suggested external address : use real external address */ 633 pcp_msg_info->ext_ip = &external_addr; 634 return 0; 635 } 636 637 if (!IN6_ARE_ADDR_EQUAL(pcp_msg_info->ext_ip, &external_addr)) { 638 syslog(LOG_ERR, 639 "PCP: External IP in request didn't match interface IP \n"); 640#ifdef DEBUG 641 { 642 char s[INET6_ADDRSTRLEN]; 643 syslog(LOG_DEBUG, "Interface IP %s \n", 644 inet_ntop(AF_INET6, &external_addr.s6_addr, s, sizeof(s))); 645 syslog(LOG_DEBUG, "IP in the PCP request %s \n", 646 inet_ntop(AF_INET6, pcp_msg_info->ext_ip, s, sizeof(s))); 647 } 648#endif 649 650 if (pcp_msg_info->pfailure_present) { 651 pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL; 652 return -1; 653 } else { 654 pcp_msg_info->ext_ip = &external_addr; 655 } 656 657 } 658 659 return 0; 660} 661 662 663static const char* inet_n46top(const struct in6_addr* in, 664 char* buf, size_t buf_len) 665{ 666 if (IN6_IS_ADDR_V4MAPPED(in)) { 667 return inet_ntop(AF_INET, ((uint32_t*)(in->s6_addr))+3, buf, buf_len); 668 } else { 669 return inet_ntop(AF_INET6, in, buf, buf_len); 670 } 671} 672 673#ifdef PCP_PEER 674static void FillSA(struct sockaddr *sa, const struct in6_addr *in6, 675 uint16_t port) 676{ 677 if (IN6_IS_ADDR_V4MAPPED(in6)) { 678 struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; 679 sa4->sin_family = AF_INET; 680 sa4->sin_addr.s_addr = ((uint32_t*)(in6)->s6_addr)[3]; 681 sa4->sin_port = htons(port); 682 } else { 683 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; 684 sa6->sin6_family = AF_INET6; 685 sa6->sin6_addr = *in6; 686 sa6->sin6_port = htons(port); 687 } 688} 689 690static const char* inet_satop(struct sockaddr* sa, char* buf, size_t buf_len) 691{ 692 if (sa->sa_family == AF_INET) { 693 return inet_ntop(AF_INET, &(((struct sockaddr_in*)sa)->sin_addr), buf, buf_len); 694 } else { 695 return inet_ntop(AF_INET6, &(((struct sockaddr_in6*)sa)->sin6_addr), buf, buf_len); 696 } 697} 698 699static int CreatePCPPeer_NAT(pcp_info_t *pcp_msg_info) 700{ 701 struct sockaddr_storage intip; 702 struct sockaddr_storage peerip; 703 struct sockaddr_storage extip; 704 struct sockaddr_storage ret_extip; 705 706 uint8_t proto = pcp_msg_info->protocol; 707 708 uint16_t eport = pcp_msg_info->ext_port; /* public port */ 709 710 char peerip_s[INET6_ADDRSTRLEN], extip_s[INET6_ADDRSTRLEN]; 711 time_t timestamp = time(NULL) + pcp_msg_info->lifetime; 712 int r; 713 714 FillSA((struct sockaddr*)&intip, pcp_msg_info->mapped_ip, 715 pcp_msg_info->int_port); 716 FillSA((struct sockaddr*)&peerip, pcp_msg_info->peer_ip, 717 pcp_msg_info->peer_port); 718 FillSA((struct sockaddr*)&extip, pcp_msg_info->ext_ip, 719 eport); 720 721 inet_satop((struct sockaddr*)&peerip, peerip_s, sizeof(peerip_s)); 722 inet_satop((struct sockaddr*)&extip, extip_s, sizeof(extip_s)); 723 724 /* check if connection with given peer exists, if it was */ 725 /* already established use this external port */ 726 if (get_nat_ext_addr( (struct sockaddr*)&intip, (struct sockaddr*)&peerip, 727 proto, (struct sockaddr*)&ret_extip) == 1) { 728 if (ret_extip.ss_family == AF_INET) { 729 struct sockaddr_in* ret_ext4 = (struct sockaddr_in*)&ret_extip; 730 uint16_t ret_eport = ntohs(ret_ext4->sin_port); 731 eport = ret_eport; 732 } else if (ret_extip.ss_family == AF_INET6) { 733 struct sockaddr_in6* ret_ext6 = (struct sockaddr_in6*)&ret_extip; 734 uint16_t ret_eport = ntohs(ret_ext6->sin6_port); 735 eport = ret_eport; 736 } else { 737 return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; 738 } 739 } 740 /* Create Peer Mapping */ 741 if (eport == 0) { 742 eport = pcp_msg_info->int_port; 743 } 744 745#ifdef PCP_FLOWP 746 if (pcp_msg_info->flowp_present && pcp_msg_info->dscp_up) { 747 if (add_peer_dscp_rule2(ext_if_name, peerip_s, 748 pcp_msg_info->peer_port, pcp_msg_info->dscp_up, 749 pcp_msg_info->mapped_str, pcp_msg_info->int_port, 750 proto, pcp_msg_info->desc, timestamp) < 0 ) { 751 syslog(LOG_ERR, "PCP: failed to add flowp upstream mapping %s:%hu->%s:%hu '%s'", 752 pcp_msg_info->mapped_str, 753 pcp_msg_info->int_port, 754 peerip_s, 755 pcp_msg_info->peer_port, 756 pcp_msg_info->desc); 757 return PCP_ERR_NO_RESOURCES; 758 } 759 } 760 761 if (pcp_msg_info->flowp_present && pcp_msg_info->dscp_down) { 762 if (add_peer_dscp_rule2(ext_if_name, pcp_msg_info->mapped_str, 763 pcp_msg_info->int_port, pcp_msg_info->dscp_down, 764 peerip_s, pcp_msg_info->peer_port, proto, pcp_msg_info->desc, timestamp) 765 < 0 ) { 766 syslog(LOG_ERR, "PCP: failed to add flowp downstream mapping %s:%hu->%s:%hu '%s'", 767 pcp_msg_info->mapped_str, 768 pcp_msg_info->int_port, 769 peerip_s, 770 pcp_msg_info->peer_port, 771 pcp_msg_info->desc); 772 pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; 773 return PCP_ERR_NO_RESOURCES; 774 } 775 } 776#endif 777 778 r = add_peer_redirect_rule2(ext_if_name, 779 peerip_s, 780 pcp_msg_info->peer_port, 781 extip_s, 782 eport, 783 pcp_msg_info->mapped_str, 784 pcp_msg_info->int_port, 785 pcp_msg_info->protocol, 786 pcp_msg_info->desc, 787 timestamp); 788 if (r < 0) 789 return PCP_ERR_NO_RESOURCES; 790 pcp_msg_info->ext_port = eport; 791 return PCP_SUCCESS; 792} 793 794static void CreatePCPPeer(pcp_info_t *pcp_msg_info) 795{ 796 char peerip_s[INET6_ADDRSTRLEN]; 797 int r = -1; 798 799 if (!inet_n46top(pcp_msg_info->peer_ip, peerip_s, sizeof(peerip_s))) { 800 syslog(LOG_ERR, "inet_n46top(peer_ip): %m"); 801 return; 802 } 803 804 if (pcp_msg_info->is_fw) { 805#if 0 806 /* Someday, something like this is available.. and we're ready! */ 807#ifdef ENABLE_UPNPPINHOLE 808 pcp_msg_info->ext_port = pcp_msg_info->int_port; 809 r = upnp_add_outbound_pinhole(peerip_s, 810 pcp_msg_info->peer_port, 811 pcp_msg_info->mapped_str, 812 pcp_msg_info->int_port, 813 pcp_msg_info->protocol, 814 pcp_msg_info->desc, 815 pcp_msg_info->lifetime, NULL); 816#endif /* ENABLE_UPNPPINHOLE */ 817#else 818 r = PCP_ERR_UNSUPP_OPCODE; 819#endif /* 0 */ 820 } else { 821 r = CreatePCPPeer_NAT(pcp_msg_info); 822 } 823 /* TODO: add upnp function for PI */ 824 pcp_msg_info->result_code = r; 825 syslog(LOG_ERR, "PCP PEER: %s peer mapping %s %s:%hu(%hu)->%s:%hu '%s'", 826 r == PCP_SUCCESS ? "added" : "failed to add", 827 (pcp_msg_info->protocol==IPPROTO_TCP)?"TCP":"UDP", 828 pcp_msg_info->mapped_str, 829 pcp_msg_info->int_port, 830 pcp_msg_info->ext_port, 831 peerip_s, 832 pcp_msg_info->peer_port, 833 pcp_msg_info->desc); 834} 835 836static void DeletePCPPeer(pcp_info_t *pcp_msg_info) 837{ 838 uint16_t iport = pcp_msg_info->int_port; /* private port */ 839 uint16_t rport = pcp_msg_info->peer_port; /* private port */ 840 uint8_t proto = pcp_msg_info->protocol; 841 char rhost[INET6_ADDRSTRLEN]; 842 int r = -1; 843 844 /* remove requested mappings for this client */ 845 int index = 0; 846 unsigned short eport2, iport2, rport2; 847 char iaddr2[INET6_ADDRSTRLEN], rhost2[INET6_ADDRSTRLEN]; 848 int proto2; 849 char desc[64]; 850 unsigned int timestamp; 851#if 0 852 int uid; 853#endif /* 0 */ 854 855 if (pcp_msg_info->is_fw) { 856 pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE; 857 return; 858 } 859 860 inet_n46top((struct in6_addr*)pcp_msg_info->peer_ip, rhost, sizeof(rhost)); 861 862 for (index = 0 ; 863 (!pcp_msg_info->is_fw && 864 get_peer_rule_by_index(index, 0, 865 &eport2, iaddr2, sizeof(iaddr2), 866 &iport2, &proto2, 867 desc, sizeof(desc), 868 rhost2, sizeof(rhost2), &rport2, 869 ×tamp, 0, 0) >= 0) 870#if 0 871 /* Some day if outbound pinholes are supported.. */ 872 || 873 (pcp_msg_info->is_fw && 874 (uid=upnp_get_pinhole_uid_by_index(index))>=0 && 875 upnp_get_pinhole_info((unsigned short)uid, 876 rhost2, sizeof(rhost2), &rport2, 877 iaddr2, sizeof(iaddr2), &iport2, 878 &proto2, desc, sizeof(desc), 879 ×tamp, NULL) > 0) 880#endif /* 0 */ 881 ; 882 index++) 883 if((0 == strcmp(iaddr2, pcp_msg_info->mapped_str)) 884 && (0 == strcmp(rhost2, rhost)) 885 && (proto2==proto) 886 && 0 == strcmp(desc, pcp_msg_info->desc) 887 && (iport2==iport) && (rport2==rport)) { 888 if (!pcp_msg_info->is_fw) 889 r = _upnp_delete_redir(eport2, proto2); 890#if 0 891 else 892 r = upnp_delete_outboundpinhole(uid); 893#endif /* 0 */ 894 if(r<0) { 895 syslog(LOG_ERR, "PCP PEER: failed to remove peer mapping"); 896 } else { 897 syslog(LOG_DEBUG, "PCP PEER: %s port %hu peer mapping removed", 898 proto2==IPPROTO_TCP?"TCP":"UDP", eport2); 899 } 900 return; 901 } 902 if (r==-1) { 903 syslog(LOG_ERR, "PCP PEER: Failed to find PCP mapping internal port %hu, protocol %s", 904 iport, (pcp_msg_info->protocol == IPPROTO_TCP)?"TCP":"UDP"); 905 pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; 906 } 907} 908#endif /* PCP_PEER */ 909 910static int CreatePCPMap_NAT(pcp_info_t *pcp_msg_info) 911{ 912 int r = 0; 913 char iaddr_old[INET6_ADDRSTRLEN]; 914 uint16_t iport_old, eport_first = 0; 915 int any_eport_allowed = 0; 916 unsigned int timestamp = time(NULL) + pcp_msg_info->lifetime; 917 918 if (pcp_msg_info->ext_port == 0) { 919 pcp_msg_info->ext_port = pcp_msg_info->int_port; 920 } 921 922 /* TODO: Support non-TCP/UDP */ 923 if (pcp_msg_info->ext_port == 0) { 924 return PCP_ERR_MALFORMED_REQUEST; 925 } 926 927 do { 928 if (eport_first == 0) { /* first time in loop */ 929 eport_first = pcp_msg_info->ext_port; 930 } else if (pcp_msg_info->ext_port == eport_first) { /* no eport available */ 931 /* all eports rejected by permissions? */ 932 if (any_eport_allowed == 0) 933 return PCP_ERR_NOT_AUTHORIZED; 934 /* at least one eport allowed (but none available) */ 935 return PCP_ERR_NO_RESOURCES; 936 } 937 if ((IN6_IS_ADDR_V4MAPPED(pcp_msg_info->mapped_ip) && 938 (!check_upnp_rule_against_permissions(upnppermlist, 939 num_upnpperm, pcp_msg_info->ext_port, 940 ((struct in_addr*)pcp_msg_info->mapped_ip->s6_addr)[3], 941 pcp_msg_info->int_port)))) { 942 if (pcp_msg_info->pfailure_present) { 943 return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; 944 } 945 pcp_msg_info->ext_port++; 946 if (pcp_msg_info->ext_port == 0) { /* skip port zero */ 947 pcp_msg_info->ext_port++; 948 } 949 continue; 950 } 951 any_eport_allowed = 1; 952#ifdef CHECK_PORTINUSE 953 if (port_in_use(ext_if_name, pcp_msg_info->ext_port, pcp_msg_info->protocol, 954 pcp_msg_info->mapped_str, pcp_msg_info->int_port) > 0) { 955 syslog(LOG_INFO, "port %hu protocol %s already in use", 956 pcp_msg_info->ext_port, 957 (pcp_msg_info->protocol==IPPROTO_TCP)?"tcp":"udp"); 958 pcp_msg_info->ext_port++; 959 if (pcp_msg_info->ext_port == 0) { /* skip port zero */ 960 pcp_msg_info->ext_port++; 961 } 962 continue; 963 } 964#endif 965 r = get_redirect_rule(ext_if_name, 966 pcp_msg_info->ext_port, 967 pcp_msg_info->protocol, 968 iaddr_old, sizeof(iaddr_old), 969 &iport_old, 0, 0, 0, 0, 970 ×tamp, 0, 0); 971 972 if(r==0) { 973 if((strcmp(pcp_msg_info->mapped_str, iaddr_old)!=0) 974 || (pcp_msg_info->int_port != iport_old)) { 975 /* redirection already existing */ 976 if (pcp_msg_info->pfailure_present) { 977 return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; 978 } 979 } else { 980 syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", 981 pcp_msg_info->ext_port, (pcp_msg_info->protocol==IPPROTO_TCP)?"tcp":"udp", 982 iaddr_old, iport_old); 983 /* remove and then add again */ 984 if (_upnp_delete_redir(pcp_msg_info->ext_port, 985 pcp_msg_info->protocol)==0) { 986 break; 987 } else if (pcp_msg_info->pfailure_present) { 988 return PCP_ERR_CANNOT_PROVIDE_EXTERNAL; 989 } 990 } 991 pcp_msg_info->ext_port++; 992 if (pcp_msg_info->ext_port == 0) { /* skip port zero */ 993 pcp_msg_info->ext_port++; 994 } 995 } 996 } while (r==0); 997 998 r = upnp_redirect_internal(NULL, 999 pcp_msg_info->ext_port, 1000 pcp_msg_info->mapped_str, 1001 pcp_msg_info->int_port, 1002 pcp_msg_info->protocol, 1003 pcp_msg_info->desc, 1004 timestamp); 1005 if (r < 0) 1006 return PCP_ERR_NO_RESOURCES; 1007 return PCP_SUCCESS; 1008} 1009 1010static int CreatePCPMap_FW(pcp_info_t *pcp_msg_info) 1011{ 1012#ifdef ENABLE_UPNPPINHOLE 1013 int uid; 1014 int r = upnp_add_inboundpinhole(NULL, 0, 1015 pcp_msg_info->mapped_str, 1016 pcp_msg_info->int_port, 1017 pcp_msg_info->protocol, 1018 pcp_msg_info->desc, 1019 pcp_msg_info->lifetime, 1020 &uid); 1021 if (r < 0) 1022 return PCP_ERR_NO_RESOURCES; 1023 pcp_msg_info->ext_port = pcp_msg_info->int_port; 1024 return PCP_SUCCESS; 1025#else 1026 UNUSED(pcp_msg_info); 1027 return PCP_ERR_NO_RESOURCES; 1028#endif /* ENABLE_UPNPPINHOLE */ 1029} 1030 1031 1032/* internal external PCP remote peer actual remote peer 1033 * -------- ------- --------------- ------------------ 1034 * IPv4 firewall IPv4 IPv4 IPv4 IPv4 1035 * IPv6 firewall IPv6 IPv6 IPv6 IPv6 1036 * NAT44 IPv4 IPv4 IPv4 IPv4 1037 * NAT46 IPv4 IPv6 IPv4 IPv6 1038 * NAT64 IPv6 IPv4 IPv6 IPv4 1039 * NPTv6 IPv6 IPv6 IPv6 IPv6 1040 * 1041 * Address Families with MAP and PEER 1042 * 1043 * The 'internal' address is implicitly the same as the source IP 1044 * address of the PCP request, except when the THIRD_PARTY option is 1045 * used. 1046 * 1047 * The 'external' address is the Suggested External Address field of the 1048 * MAP or PEER request, and its address family is usually the same as 1049 * the 'internal' address family, except when technologies like NAT64 1050 * are used. 1051 * 1052 * The 'remote peer' address is the remote peer IP address of the PEER 1053 * request or the FILTER option of the MAP request, and is always the 1054 * same address family as the 'internal' address, even when NAT64 is 1055 * used. In NAT64, the IPv6 PCP client is not necessarily aware of the 1056 * NAT64 or aware of the actual IPv4 address of the remote peer, so it 1057 * expresses the IPv6 address from its perspective. */ 1058 1059/* TODO: Support more than basic NAT44 / IPv6 firewall cases. */ 1060static void CreatePCPMap(pcp_info_t *pcp_msg_info) 1061{ 1062 int r; 1063 1064 if (pcp_msg_info->is_fw) 1065 r = CreatePCPMap_FW(pcp_msg_info); 1066 else 1067 r = CreatePCPMap_NAT(pcp_msg_info); 1068 pcp_msg_info->result_code = r; 1069 syslog(LOG_ERR, "PCP MAP: %s mapping %s %hu->%s:%hu '%s'", 1070 r == PCP_SUCCESS ? "added" : "failed to add", 1071 (pcp_msg_info->protocol==IPPROTO_TCP)?"TCP":"UDP", 1072 pcp_msg_info->ext_port, 1073 pcp_msg_info->mapped_str, 1074 pcp_msg_info->int_port, 1075 pcp_msg_info->desc); 1076} 1077 1078static void DeletePCPMap(pcp_info_t *pcp_msg_info) 1079{ 1080 uint16_t iport = pcp_msg_info->int_port; /* private port */ 1081 uint8_t proto = pcp_msg_info->protocol; 1082 int r=-1; 1083 /* remove the mapping */ 1084 /* remove all the mappings for this client */ 1085 int index; 1086 unsigned short eport2, iport2; 1087 char iaddr2[16]; 1088 int proto2; 1089 char desc[64]; 1090 unsigned int timestamp; 1091#ifdef ENABLE_UPNPPINHOLE 1092 int uid = -1; 1093#endif /* ENABLE_UPNPPINHOLE */ 1094 1095 /* iterate through all rules and delete the requested ones */ 1096 for (index = 0 ; 1097 (!pcp_msg_info->is_fw && 1098 get_redirect_rule_by_index(index, 0, 1099 &eport2, iaddr2, sizeof(iaddr2), 1100 &iport2, &proto2, 1101 desc, sizeof(desc), 1102 0, 0, ×tamp, 0, 0) >= 0) 1103#ifdef ENABLE_UPNPPINHOLE 1104 || 1105 (pcp_msg_info->is_fw && 1106 (uid=upnp_get_pinhole_uid_by_index(index))>=0 && 1107 upnp_get_pinhole_info((unsigned short)uid, 1108 NULL, 0, NULL, 1109 iaddr2, sizeof(iaddr2), &iport2, 1110 &proto2, desc, sizeof(desc), 1111 ×tamp, NULL) > 0) 1112#endif /* ENABLE_UPNPPINHOLE */ 1113 ; 1114 index++) 1115 if(0 == strcmp(iaddr2, pcp_msg_info->mapped_str) 1116 && (proto2==proto) 1117 && 0 == strcmp(desc, pcp_msg_info->desc) 1118 && ((iport2==iport) || (iport==0))) { 1119 if (!pcp_msg_info->is_fw) { 1120 r = _upnp_delete_redir(eport2, proto2); 1121 } else { 1122#ifdef ENABLE_UPNPPINHOLE 1123 r = upnp_delete_inboundpinhole(uid); 1124#endif /* ENABLE_UPNPPINHOLE */ 1125 } 1126 break; 1127 } 1128 if (r >= 0) { 1129 syslog(LOG_DEBUG, "PCP: %s port %hu mapping removed", 1130 proto2==IPPROTO_TCP?"TCP":"UDP", eport2); 1131 } else { 1132 syslog(LOG_ERR, "Failed to remove PCP mapping internal port %hu, protocol %s", 1133 iport, (pcp_msg_info->protocol == IPPROTO_TCP)?"TCP":"UDP"); 1134 pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; 1135 } 1136} 1137 1138static int ValidatePCPMsg(pcp_info_t *pcp_msg_info) 1139{ 1140 if (pcp_msg_info->result_code) { 1141 return 0; 1142 } 1143 1144 /* RFC 6887, section 8.2: MUST return address mismatch if NAT 1145 * in middle. */ 1146 if (memcmp(pcp_msg_info->int_ip, 1147 &pcp_msg_info->sender_ip, 1148 sizeof(pcp_msg_info->sender_ip)) != 0) { 1149 pcp_msg_info->result_code = PCP_ERR_ADDRESS_MISMATCH; 1150 return 0; 1151 } 1152 1153 if (pcp_msg_info->thirdp_ip) { 1154 if (!GETFLAG(PCP_ALLOWTHIRDPARTYMASK)) { 1155 pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION; 1156 return 0; 1157 } 1158 1159 /* RFC687, section 13.1 - if sender ip == THIRD_PARTY, 1160 * it's an error. */ 1161 if (memcmp(pcp_msg_info->thirdp_ip, 1162 &pcp_msg_info->sender_ip, 1163 sizeof(pcp_msg_info->sender_ip)) == 0) { 1164 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1165 return 0; 1166 } 1167 } 1168 1169 /* Produce mapped_str for future use. */ 1170 if (!inet_n46top(pcp_msg_info->mapped_ip, pcp_msg_info->mapped_str, 1171 sizeof(pcp_msg_info->mapped_str))) { 1172 syslog(LOG_ERR, "inet_ntop(pcpserver): %m"); 1173 return 0; 1174 } 1175 1176 /* protocol zero means 'all protocols' : internal port MUST be zero */ 1177 if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port != 0) { 1178 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1179 return 0; 1180 } 1181 1182 if (pcp_msg_info->pfailure_present) { 1183 if ( (IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip) || 1184 ((IN6_IS_ADDR_V4MAPPED(pcp_msg_info->ext_ip)) && 1185 (((uint32_t*)pcp_msg_info->ext_ip->s6_addr)[3] == 0))) && 1186 (pcp_msg_info->ext_port == 0) 1187 ) 1188 { 1189 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 1190 return 0; 1191 } 1192 } 1193 1194 if (CheckExternalAddress(pcp_msg_info)) { 1195 return 0; 1196 } 1197 1198 /* Fill in the desc that describes uniquely what flow we're 1199 * dealing with (same code used in both create + delete of 1200 * MAP/PEER) */ 1201 switch (pcp_msg_info->opcode) { 1202 case PCP_OPCODE_MAP: 1203 case PCP_OPCODE_PEER: 1204 snprintf(pcp_msg_info->desc, sizeof(pcp_msg_info->desc), 1205 "PCP %s %08x%08x%08x", 1206 pcp_msg_info->opcode == PCP_OPCODE_MAP ? "MAP":"PEER", 1207 pcp_msg_info->nonce[0], 1208 pcp_msg_info->nonce[1], pcp_msg_info->nonce[2]); 1209 break; 1210 } 1211 return 1; 1212} 1213 1214/* 1215 * return value indicates whether the request is valid or not. 1216 * Based on the return value simple response can be formed. 1217 */ 1218static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) 1219{ 1220 int remainingSize; 1221 1222 const pcp_map_v1_t* map_v1; 1223 const pcp_map_v2_t* map_v2; 1224#ifdef PCP_PEER 1225 pcp_peer_v1_t* peer_v1; 1226 pcp_peer_v2_t* peer_v2; 1227#endif 1228 1229#ifdef PCP_SADSCP 1230 pcp_sadscp_req_t* sadscp; 1231#endif 1232 /* start with PCP_SUCCESS as result code, if everything is OK value will be unchanged */ 1233 pcp_msg_info->result_code = PCP_SUCCESS; 1234 1235 remainingSize = req_size; 1236 1237 /* discard request that exceeds maximal length, 1238 or that is shorter than PCP_MIN_LEN (=24) 1239 or that is not the multiple of 4 */ 1240 if (req_size < 3) 1241 return 0; /* ignore msg */ 1242 1243 if (req_size < PCP_MIN_LEN) { 1244 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1245 return 1; /* send response */ 1246 } 1247 1248 if ( (req_size > PCP_MAX_LEN) || ( (req_size & 3) != 0)) { 1249 syslog(LOG_ERR, "PCP: Size of PCP packet(%d) is larger than %d bytes or " 1250 "the size is not multiple of 4.\n", req_size, PCP_MAX_LEN); 1251 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1252 return 1; /* send response */ 1253 } 1254 1255 /* first parse request header */ 1256 if (parseCommonRequestHeader((pcp_request_t*)req, pcp_msg_info) ) { 1257 return 1; 1258 } 1259 1260 remainingSize -= sizeof(pcp_request_t); 1261 req += sizeof(pcp_request_t); 1262 1263 if (pcp_msg_info->version == 1) { 1264 /* legacy PCP version 1 support */ 1265 switch (pcp_msg_info->opcode) { 1266 case PCP_OPCODE_MAP: 1267 1268 remainingSize -= sizeof(pcp_map_v1_t); 1269 if (remainingSize < 0) { 1270 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1271 return pcp_msg_info->result_code; 1272 } 1273 1274 map_v1 = (pcp_map_v1_t*)req; 1275#ifdef DEBUG 1276 printMAPOpcodeVersion1(map_v1); 1277#endif /* DEBUG */ 1278 if ( parsePCPMAP_version1(map_v1, pcp_msg_info) ) { 1279 return pcp_msg_info->result_code; 1280 } 1281 1282 req += sizeof(pcp_map_v1_t); 1283 1284 parsePCPOptions(req, remainingSize, pcp_msg_info); 1285 if (ValidatePCPMsg(pcp_msg_info)) { 1286 if (pcp_msg_info->lifetime == 0) { 1287 DeletePCPMap(pcp_msg_info); 1288 } else { 1289 CreatePCPMap(pcp_msg_info); 1290 } 1291 } else { 1292 syslog(LOG_ERR, "PCP: Invalid PCP v1 MAP message."); 1293 } 1294 1295 1296 break; 1297 1298#ifdef PCP_PEER 1299 case PCP_OPCODE_PEER: 1300 1301 remainingSize -= sizeof(pcp_peer_v1_t); 1302 if (remainingSize < 0) { 1303 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1304 return pcp_msg_info->result_code; 1305 } 1306 peer_v1 = (pcp_peer_v1_t*)req; 1307 1308#ifdef DEBUG 1309 printPEEROpcodeVersion1(peer_v1); 1310#endif /* DEBUG */ 1311 if ( parsePCPPEER_version1(peer_v1, pcp_msg_info) ) { 1312 return pcp_msg_info->result_code; 1313 } 1314 1315 req += sizeof(pcp_peer_v1_t); 1316 1317 parsePCPOptions(req, remainingSize, pcp_msg_info); 1318 1319 if (ValidatePCPMsg(pcp_msg_info)) { 1320 if (pcp_msg_info->lifetime == 0) { 1321 DeletePCPPeer(pcp_msg_info); 1322 } else { 1323 CreatePCPPeer(pcp_msg_info); 1324 } 1325 } else { 1326 syslog(LOG_ERR, "PCP: Invalid PCP v1 PEER message."); 1327 } 1328 1329 1330 break; 1331#endif /* PCP_PEER */ 1332 default: 1333 pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE; 1334 break; 1335 } 1336 1337 } else if (pcp_msg_info->version == 2) { 1338 /* RFC 6887 PCP support 1339 * http://tools.ietf.org/html/rfc6887 */ 1340 switch (pcp_msg_info->opcode) { 1341 case PCP_OPCODE_ANNOUNCE: 1342 /* should check PCP Client's IP Address in request */ 1343 /* see http://tools.ietf.org/html/rfc6887#section-14.1 */ 1344 break; 1345 case PCP_OPCODE_MAP: 1346 1347 remainingSize -= sizeof(pcp_map_v2_t); 1348 if (remainingSize < 0) { 1349 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1350 return pcp_msg_info->result_code; 1351 } 1352 1353 map_v2 = (pcp_map_v2_t*)req; 1354 1355#ifdef DEBUG 1356 printMAPOpcodeVersion2(map_v2); 1357#endif /* DEBUG */ 1358 1359 if (parsePCPMAP_version2(map_v2, pcp_msg_info) ) { 1360 return pcp_msg_info->result_code; 1361 } 1362 req += sizeof(pcp_map_v2_t); 1363 1364 parsePCPOptions(req, remainingSize, pcp_msg_info); 1365 1366 if (ValidatePCPMsg(pcp_msg_info)) { 1367 if (pcp_msg_info->lifetime == 0) { 1368 DeletePCPMap(pcp_msg_info); 1369 } else { 1370 CreatePCPMap(pcp_msg_info); 1371 } 1372 } else { 1373 syslog(LOG_ERR, "PCP: Invalid PCP v2 MAP message."); 1374 } 1375 1376 1377 break; 1378 1379#ifdef PCP_PEER 1380 case PCP_OPCODE_PEER: 1381 1382 remainingSize -= sizeof(pcp_peer_v2_t); 1383 if (remainingSize < 0) { 1384 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1385 return pcp_msg_info->result_code; 1386 } 1387 peer_v2 = (pcp_peer_v2_t*)req; 1388 1389#ifdef DEBUG 1390 printPEEROpcodeVersion2(peer_v2); 1391#endif /* DEBUG */ 1392 parsePCPPEER_version2(peer_v2, pcp_msg_info); 1393 req += sizeof(pcp_peer_v2_t); 1394 1395 if (pcp_msg_info->result_code != 0) { 1396 return pcp_msg_info->result_code; 1397 } 1398 1399 parsePCPOptions(req, remainingSize, pcp_msg_info); 1400 1401 if (ValidatePCPMsg(pcp_msg_info)) { 1402 if (pcp_msg_info->lifetime == 0) { 1403 DeletePCPPeer(pcp_msg_info); 1404 } else { 1405 CreatePCPPeer(pcp_msg_info); 1406 } 1407 } else { 1408 syslog(LOG_ERR, "PCP: Invalid PCP v2 PEER message."); 1409 } 1410 1411 break; 1412#endif /* PCP_PEER */ 1413 1414#ifdef PCP_SADSCP 1415 case PCP_OPCODE_SADSCP: 1416 remainingSize -= sizeof(pcp_sadscp_req_t); 1417 if (remainingSize < 0) { 1418 pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; 1419 return pcp_msg_info->result_code; 1420 } 1421 1422 sadscp = (pcp_sadscp_req_t*)req; 1423 req += sizeof(pcp_sadscp_req_t); 1424 1425 if (sadscp->app_name_length > remainingSize) { 1426 pcp_msg_info->result_code = PCP_ERR_MALFORMED_OPTION; 1427 } 1428 1429#ifdef DEBUG 1430 printSADSCPOpcode(sadscp); 1431#endif 1432 if (parseSADSCP(sadscp, pcp_msg_info)) { 1433 return pcp_msg_info->result_code; 1434 } 1435 1436 get_dscp_value(pcp_msg_info); 1437 1438 1439 break; 1440#endif 1441 default: 1442 pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE; 1443 break; 1444 } 1445 } else { 1446 pcp_msg_info->result_code = PCP_ERR_UNSUPP_VERSION; 1447 return pcp_msg_info->result_code; 1448 } 1449 return 1; 1450} 1451 1452 1453static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) 1454{ 1455 pcp_response_t *resp = (pcp_response_t*)response; 1456 1457 resp->reserved = 0; 1458 resp->reserved1[0]=0; 1459 resp->reserved1[1]=0; 1460 resp->reserved1[2]=0; 1461 if (pcp_msg_info->result_code == PCP_ERR_UNSUPP_VERSION ) { 1462 /* highest supported version */ 1463 resp->ver = this_server_info.server_version; 1464 } else { 1465 resp->ver = pcp_msg_info->version; 1466 } 1467 1468 resp->r_opcode |= 0x80; 1469 resp->result_code = pcp_msg_info->result_code; 1470 resp->epochtime = htonl(time(NULL) - startup_time); 1471 switch (pcp_msg_info->result_code) { 1472 /*long lifetime errors*/ 1473 case PCP_ERR_UNSUPP_VERSION: 1474 case PCP_ERR_NOT_AUTHORIZED: 1475 case PCP_ERR_MALFORMED_REQUEST: 1476 case PCP_ERR_UNSUPP_OPCODE: 1477 case PCP_ERR_UNSUPP_OPTION: 1478 case PCP_ERR_MALFORMED_OPTION: 1479 case PCP_ERR_UNSUPP_PROTOCOL: 1480 case PCP_ERR_ADDRESS_MISMATCH: 1481 case PCP_ERR_CANNOT_PROVIDE_EXTERNAL: 1482 case PCP_ERR_EXCESSIVE_REMOTE_PEERS: 1483 resp->lifetime = 0; 1484 break; 1485 1486 case PCP_ERR_NETWORK_FAILURE: 1487 case PCP_ERR_NO_RESOURCES: 1488 case PCP_ERR_USER_EX_QUOTA: 1489 resp->lifetime = htonl(30); 1490 break; 1491 1492 case PCP_SUCCESS: 1493 default: 1494 resp->lifetime = htonl(pcp_msg_info->lifetime); 1495 break; 1496 } 1497 1498 if (resp->r_opcode == 0x81) { /* MAP response */ 1499 if (resp->ver == 1 ) { 1500 pcp_map_v1_t *mapr = (pcp_map_v1_t *)resp->next_data; 1501 mapr->ext_ip = *pcp_msg_info->ext_ip; 1502 mapr->ext_port = htons(pcp_msg_info->ext_port); 1503 mapr->int_port = htons(pcp_msg_info->int_port); 1504 } 1505 else if (resp->ver == 2 ) { 1506 pcp_map_v2_t *mapr = (pcp_map_v2_t *)resp->next_data; 1507 mapr->ext_ip = *pcp_msg_info->ext_ip; 1508 mapr->ext_port = htons(pcp_msg_info->ext_port); 1509 mapr->int_port = htons(pcp_msg_info->int_port); 1510 } 1511 } 1512#ifdef PCP_PEER 1513 else if (resp->r_opcode == 0x82) { /* PEER response */ 1514 if (resp->ver == 1 ){ 1515 pcp_peer_v1_t* peer_resp = (pcp_peer_v1_t*)resp->next_data; 1516 peer_resp->ext_port = htons(pcp_msg_info->ext_port); 1517 peer_resp->int_port = htons(pcp_msg_info->int_port); 1518 peer_resp->peer_port = htons(pcp_msg_info->peer_port); 1519 peer_resp->ext_ip = *pcp_msg_info->ext_ip; 1520 } 1521 else if (resp->ver == 2 ){ 1522 pcp_peer_v2_t* peer_resp = (pcp_peer_v2_t*)resp->next_data; 1523 peer_resp->ext_port = htons(pcp_msg_info->ext_port); 1524 peer_resp->int_port = htons(pcp_msg_info->int_port); 1525 peer_resp->peer_port = htons(pcp_msg_info->peer_port); 1526 peer_resp->ext_ip = *pcp_msg_info->ext_ip; 1527 } 1528 } 1529#endif /* PCP_PEER */ 1530 1531#ifdef PCP_SADSCP 1532 else if (resp->r_opcode == 0x83) { /*SADSCP response*/ 1533 pcp_sadscp_resp_t *sadscp_resp = (pcp_sadscp_resp_t*)resp->next_data; 1534 sadscp_resp->a_r_dscp_value = pcp_msg_info->matched_name<<7; 1535 sadscp_resp->a_r_dscp_value &= ~(1<<6); 1536 sadscp_resp->a_r_dscp_value |= (pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK); 1537 memset(sadscp_resp->reserved, 0, sizeof(sadscp_resp->reserved)); 1538 } 1539#endif /* PCP_SADSCP */ 1540} 1541 1542int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, 1543 const struct sockaddr *senderaddr, 1544 const struct sockaddr_in6 *receiveraddr) 1545{ 1546 pcp_info_t pcp_msg_info; 1547 struct lan_addr_s * lan_addr; 1548 char addr_str[64]; 1549 1550 memset(&pcp_msg_info, 0, sizeof(pcp_info_t)); 1551 1552 if(senderaddr->sa_family == AF_INET) { 1553 const struct sockaddr_in * senderaddr_v4 = 1554 (const struct sockaddr_in *)senderaddr; 1555 pcp_msg_info.sender_ip.s6_addr[11] = 0xff; 1556 pcp_msg_info.sender_ip.s6_addr[10] = 0xff; 1557 memcpy(pcp_msg_info.sender_ip.s6_addr+12, 1558 &senderaddr_v4->sin_addr, 4); 1559 } else if(senderaddr->sa_family == AF_INET6) { 1560 const struct sockaddr_in6 * senderaddr_v6 = 1561 (const struct sockaddr_in6 *)senderaddr; 1562 pcp_msg_info.sender_ip = senderaddr_v6->sin6_addr; 1563 } else { 1564 syslog(LOG_WARNING, "unknown PCP packet sender address family %d", 1565 senderaddr->sa_family); 1566 return 0; 1567 } 1568 1569 if(sockaddr_to_string(senderaddr, addr_str, sizeof(addr_str))) 1570 syslog(LOG_DEBUG, "PCP request received from %s %dbytes", 1571 addr_str, len); 1572 1573 if(buff[1] & 128) { 1574 /* discarding PCP responses silently */ 1575 return 0; 1576 } 1577 1578 /* If we're in allow third party-mode, we probably don't care 1579 * about locality either. Let's hope firewall is ok. */ 1580 if (!GETFLAG(PCP_ALLOWTHIRDPARTYMASK)) { 1581 lan_addr = get_lan_for_peer(senderaddr); 1582 if(lan_addr == NULL) { 1583 syslog(LOG_INFO, "PCP packet sender %s not from a LAN, ignoring", 1584 addr_str); 1585 return 0; 1586 } 1587 } 1588 1589 if (processPCPRequest(buff, len, &pcp_msg_info) ) { 1590 1591 createPCPResponse(buff, &pcp_msg_info); 1592 1593 if(len < PCP_MIN_LEN) 1594 len = PCP_MIN_LEN; 1595 else 1596 len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */ 1597 len = sendto_or_schedule2(s, buff, len, 0, senderaddr, 1598 (senderaddr->sa_family == AF_INET) ? 1599 sizeof(struct sockaddr_in) : 1600 sizeof(struct sockaddr_in6), 1601 receiveraddr); 1602 if( len < 0 ) { 1603 syslog(LOG_ERR, "sendto(pcpserver): %m"); 1604 } 1605 } 1606 1607 return 0; 1608} 1609 1610#ifdef ENABLE_IPV6 1611int OpenAndConfPCPv6Socket(void) 1612{ 1613 int s; 1614 int i = 1; 1615 struct sockaddr_in6 addr; 1616 s = socket(PF_INET6, SOCK_DGRAM, 0/*IPPROTO_UDP*/); 1617 if(s < 0) { 1618 syslog(LOG_ERR, "%s: socket(): %m", "OpenAndConfPCPv6Socket"); 1619 return -1; 1620 } 1621 if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) { 1622 syslog(LOG_WARNING, "%s: setsockopt(SO_REUSEADDR): %m", 1623 "OpenAndConfPCPv6Socket"); 1624 } 1625#ifdef IPV6_V6ONLY 1626 /* force IPV6 only for IPV6 socket. 1627 * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */ 1628 if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0) { 1629 syslog(LOG_WARNING, "%s: setsockopt(IPV6_V6ONLY): %m", 1630 "OpenAndConfPCPv6Socket"); 1631 } 1632#endif 1633#ifdef IPV6_RECVPKTINFO 1634 /* see RFC3542 */ 1635 if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &i, sizeof(i)) < 0) { 1636 syslog(LOG_WARNING, "%s: setsockopt(IPV6_RECVPKTINFO): %m", 1637 "OpenAndConfPCPv6Socket"); 1638 } 1639#endif 1640 if(!set_non_blocking(s)) { 1641 syslog(LOG_WARNING, "%s: set_non_blocking(): %m", 1642 "OpenAndConfPCPv6Socket"); 1643 } 1644 memset(&addr, 0, sizeof(addr)); 1645 addr.sin6_family = AF_INET6; 1646 addr.sin6_port = htons(NATPMP_PORT); 1647 addr.sin6_addr = ipv6_bind_addr; 1648 if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { 1649 syslog(LOG_ERR, "%s: bind(): %m", "OpenAndConfPCPv6Socket"); 1650 close(s); 1651 return -1; 1652 } 1653 return s; 1654} 1655#endif /*ENABLE_IPV6*/ 1656#endif /*ENABLE_PCP*/ 1657