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				     &timestamp, 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					    &timestamp, 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				      &timestamp, 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, &timestamp, 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				    &timestamp, 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