miniupnpd: Retreive PCP packed IPV6 destination address

This commit is contained in:
Thomas Bernard 2014-05-19 15:27:34 +02:00
parent 5f288bf804
commit d851ad4c25
5 changed files with 79 additions and 5 deletions

View File

@ -2102,6 +2102,7 @@ main(int argc, char * * argv)
len = ReceiveNATPMPOrPCPPacket(snatpmp[i],
(struct sockaddr *)&senderaddr,
&senderaddrlen,
NULL,
msg_buff, sizeof(msg_buff));
if (len < 1)
continue;
@ -2111,7 +2112,7 @@ main(int argc, char * * argv)
&senderaddr);
} else { /* everything else can be PCP */
ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len,
(struct sockaddr *)&senderaddr);
(struct sockaddr *)&senderaddr, NULL);
}
#else
@ -2127,16 +2128,19 @@ main(int argc, char * * argv)
unsigned char msg_buff[PCP_MAX_LEN];
struct sockaddr_in6 senderaddr;
socklen_t senderaddrlen;
struct sockaddr_in6 receiveraddr;
int len;
memset(msg_buff, 0, PCP_MAX_LEN);
senderaddrlen = sizeof(senderaddr);
len = ReceiveNATPMPOrPCPPacket(spcp_v6,
(struct sockaddr *)&senderaddr,
&senderaddrlen,
&receiveraddr,
msg_buff, sizeof(msg_buff));
if(len >= 1)
ProcessIncomingPCPPacket(spcp_v6, msg_buff, len,
(struct sockaddr *)&senderaddr);
(struct sockaddr *)&senderaddr,
&receiveraddr);
}
#endif
/* process SSDP packets */

View File

@ -1,4 +1,4 @@
/* $Id: natpmp.c,v 1.43 2014/03/24 10:49:45 nanard Exp $ */
/* $Id: natpmp.c,v 1.47 2014/05/19 12:51:52 nanard Exp $ */
/* MiniUPnP project
* (c) 2007-2014 Thomas Bernard
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
@ -14,6 +14,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/uio.h>
#include "macros.h"
#include "config.h"
@ -161,9 +162,63 @@ static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr
*/
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr,
socklen_t * senderaddrlen,
struct sockaddr_in6 * receiveraddr,
unsigned char * msg_buff, size_t msg_buff_size)
{
#if IPV6_PKTINFO
struct iovec iov;
uint8_t c[1000];
struct msghdr msg;
int n;
struct cmsghdr *h;
iov.iov_base = msg_buff;
iov.iov_len = msg_buff_size;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_name = senderaddr;
msg.msg_namelen = *senderaddrlen;
msg.msg_control = c;
msg.msg_controllen = sizeof(c);
n = recvmsg(s, &msg, 0);
if(n < 0) {
/* EAGAIN, EWOULDBLOCK and EINTR : silently ignore (retry next time)
* other errors : log to LOG_ERR */
if(errno != EAGAIN &&
errno != EWOULDBLOCK &&
errno != EINTR) {
syslog(LOG_ERR, "recvmsg(natpmp): %m");
}
return n;
}
if(receiveraddr) {
memset(receiveraddr, 0, sizeof(struct sockaddr_in6));
}
if ((msg.msg_flags & MSG_TRUNC) || (msg.msg_flags & MSG_CTRUNC)) {
syslog(LOG_WARNING, "%s: truncated message",
"ReceiveNATPMPOrPCPPacket");
}
for(h = CMSG_FIRSTHDR(&msg); h;
h = CMSG_NXTHDR(&msg, h)) {
if(h->cmsg_level == IPPROTO_IPV6 && h->cmsg_type == IPV6_PKTINFO) {
char tmp[INET6_ADDRSTRLEN];
struct in6_pktinfo *ipi6 = (struct in6_pktinfo *)CMSG_DATA(h);
syslog(LOG_DEBUG, "%s: packet destination: %s scope_id=%u",
"ReceiveNATPMPOrPCPPacket",
inet_ntop(AF_INET6, &ipi6->ipi6_addr, tmp, sizeof(tmp)),
ipi6->ipi6_ifindex);
if(receiveraddr) {
receiveraddr->sin6_addr = ipi6->ipi6_addr;
receiveraddr->sin6_scope_id = ipi6->ipi6_ifindex;
receiveraddr->sin6_family = AF_INET6;
receiveraddr->sin6_port = htons(NATPMP_PORT);
}
}
}
#else
int n;
n = recvfrom(s, msg_buff, msg_buff_size, 0,
@ -179,6 +234,7 @@ int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr,
}
return n;
}
#endif
return n;
}

View File

@ -20,8 +20,10 @@
int OpenAndConfNATPMPSockets(int * sockets);
/* receiveraddr is only used with IPV6 sockets */
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr,
socklen_t * senderaddrlen,
struct sockaddr_in6 * receiveraddr,
unsigned char * msg_buff, size_t msg_buff_size);
void ProcessIncomingNATPMPPacket(int s, unsigned char * msg_buff, int len,

View File

@ -1538,7 +1538,8 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
}
int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len,
const struct sockaddr * senderaddr)
const struct sockaddr *senderaddr,
const struct sockaddr_in6 *receiveraddr)
{
pcp_info_t pcp_msg_info;
struct lan_addr_s * lan_addr;
@ -1591,6 +1592,7 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len,
len = PCP_MIN_LEN;
else
len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */
/* TODO : send using receiveraddr as source address */
len = sendto_or_schedule(s, buff, len, 0, senderaddr,
(senderaddr->sa_family == AF_INET) ?
sizeof(struct sockaddr_in) :
@ -1625,6 +1627,13 @@ int OpenAndConfPCPv6Socket(void)
syslog(LOG_WARNING, "%s: setsockopt(IPV6_V6ONLY): %m",
"OpenAndConfPCPv6Socket");
}
#endif
#ifdef IPV6_RECVPKTINFO
/* see RFC3542 */
if(setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &i, sizeof(i)) < 0) {
syslog(LOG_WARNING, "%s: setsockopt(IPV6_RECVPKTINFO): %m",
"OpenAndConfPCPv6Socket");
}
#endif
if(!set_non_blocking(s)) {
syslog(LOG_WARNING, "%s: set_non_blocking(): %m",

View File

@ -39,10 +39,13 @@ POSSIBILITY OF SUCH DAMAGE.
struct sockaddr;
/*
* receiveraddr is only used for IPV6
*
* returns 0 upon success 1 otherwise
*/
int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len,
const struct sockaddr *senderaddr);
const struct sockaddr *senderaddr,
const struct sockaddr_in6 *receiveraddr);
/*
* returns the socket