miniupnpd: start work to enable IPv6 PCP operations

This commit is contained in:
Thomas Bernard 2014-03-24 12:07:31 +01:00
parent f70484f27f
commit ad88cc0819
7 changed files with 154 additions and 45 deletions

View File

@ -1,4 +1,7 @@
$Id: Changelog.txt,v 1.365 2014/03/14 21:26:34 nanard Exp $
$Id: Changelog.txt,v 1.366 2014/03/24 11:03:50 nanard Exp $
2014/03/24:
start work to enable IPv6 PCP operations
2014/03/14:
reject renewal of subscribtion that already timeouted

View File

@ -1,4 +1,4 @@
# $Id: Makefile.linux,v 1.81 2014/01/27 10:06:58 nanard Exp $
# $Id: Makefile.linux,v 1.84 2014/03/24 10:43:25 nanard Exp $
# MiniUPnP project
# (c) 2006-2014 Thomas Bernard
# http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
@ -253,9 +253,10 @@ minissdp.o: upnputils.h getroute.h asyncsendto.h codelength.h
natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h
natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h
natpmp.o: asyncsendto.h
pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h
pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h
pcpserver.o: getifaddr.h asyncsendto.h pcp_msg_struct.h
pcpserver.o: config.h pcpserver.h natpmp.h macros.h upnpglobalvars.h
pcpserver.o: upnppermissions.h miniupnpdtypes.h pcplearndscp.h upnpredirect.h
pcpserver.o: commonrdr.h getifaddr.h asyncsendto.h upnputils.h
pcpserver.o: pcp_msg_struct.h netfilter/iptcrdr.h commonrdr.h
upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h
upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h
upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h

View File

@ -1,4 +1,4 @@
/* $Id: miniupnpd.c,v 1.189 2014/03/10 11:04:52 nanard Exp $ */
/* $Id: miniupnpd.c,v 1.190 2014/03/24 10:49:44 nanard Exp $ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
* (c) 2006-2014 Thomas Bernard
@ -1460,6 +1460,9 @@ main(int argc, char * * argv)
#ifdef ENABLE_NATPMP
int * snatpmp = NULL; /* also used for PCP */
#endif
#if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
int spcp_v6 = -1;
#endif
#ifdef ENABLE_NFQUEUE
int nfqh = -1;
#endif
@ -1648,6 +1651,10 @@ main(int argc, char * * argv)
}
#endif
#if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
spcp_v6 = OpenAndConfPCPv6Socket();
#endif
/* for miniupnpdctl */
#ifdef USE_MINIUPNPDCTL
sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl");
@ -1842,6 +1849,12 @@ main(int argc, char * * argv)
}
}
#endif
#if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
if(spcp_v6 >= 0) {
FD_SET(spcp_v6, &readset);
max_fd = MAX(max_fd, spcp_v6);
}
#endif
#ifdef USE_MINIUPNPDCTL
if(sctl >= 0) {
FD_SET(sctl, &readset);
@ -1978,19 +1991,23 @@ main(int argc, char * * argv)
{
unsigned char msg_buff[PCP_MAX_LEN];
struct sockaddr_in senderaddr;
socklen_t senderaddrlen;
int len;
memset(msg_buff, 0, PCP_MAX_LEN);
len = ReceiveNATPMPOrPCPPacket(snatpmp[i], &senderaddr,
msg_buff, sizeof(msg_buff));
senderaddrlen = sizeof(senderaddr);
len = ReceiveNATPMPOrPCPPacket(snatpmp[i],
(struct sockaddr *)&senderaddr,
&senderaddrlen,
msg_buff, sizeof(msg_buff));
if (len < 1)
continue;
#ifdef ENABLE_PCP
if (msg_buff[0]==0) { /* version equals to 0 -> means NAT-PMP */
ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len,
&senderaddr);
&senderaddr);
} else { /* everything else can be PCP */
ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len,
&senderaddr);
(struct sockaddr *)&senderaddr);
}
#else
@ -1998,6 +2015,25 @@ main(int argc, char * * argv)
#endif
}
}
#endif
#if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
/* in IPv6, only PCP is supported, not NAT-PMP */
if(spcp_v6 >= 0 && FD_ISSET(spcp_v6, &readset))
{
unsigned char msg_buff[PCP_MAX_LEN];
struct sockaddr_in6 senderaddr;
socklen_t senderaddrlen;
int len;
memset(msg_buff, 0, PCP_MAX_LEN);
senderaddrlen = sizeof(senderaddr);
len = ReceiveNATPMPOrPCPPacket(spcp_v6,
(struct sockaddr *)&senderaddr,
&senderaddrlen,
msg_buff, sizeof(msg_buff));
if(len >= 1)
ProcessIncomingPCPPacket(spcp_v6, msg_buff, len,
(struct sockaddr *)&senderaddr);
}
#endif
/* process SSDP packets */
if(sudp >= 0 && FD_ISSET(sudp, &readset))
@ -2119,6 +2155,13 @@ shutdown:
}
}
#endif
#if defined(ENABLE_IPV6) && defined(ENABLE_PCP)
if(spcp_v6 >= 0)
{
close(spcp_v6);
spcp_v6 = -1;
}
#endif
#ifdef USE_MINIUPNPDCTL
if(sctl>=0)
{

View File

@ -1,4 +1,4 @@
/* $Id: natpmp.c,v 1.39 2014/03/07 10:43:30 nanard Exp $ */
/* $Id: natpmp.c,v 1.43 2014/03/24 10:49:45 nanard Exp $ */
/* MiniUPnP project
* (c) 2007-2014 Thomas Bernard
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
@ -34,13 +34,13 @@ int OpenAndConfNATPMPSocket(in_addr_t addr)
snatpmp = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_UDP*/);
if(snatpmp<0)
{
syslog(LOG_ERR, "%s: socket(natpmp): %m",
syslog(LOG_ERR, "%s: socket(): %m",
"OpenAndConfNATPMPSocket");
return -1;
}
if(setsockopt(snatpmp, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
{
syslog(LOG_WARNING, "%s: setsockopt(natpmp, SO_REUSEADDR): %m",
syslog(LOG_WARNING, "%s: setsockopt(SO_REUSEADDR): %m",
"OpenAndConfNATPMPSocket");
}
if(!set_non_blocking(snatpmp))
@ -57,7 +57,8 @@ int OpenAndConfNATPMPSocket(in_addr_t addr)
natpmp_addr.sin_addr.s_addr = addr;
if(bind(snatpmp, (struct sockaddr *)&natpmp_addr, sizeof(natpmp_addr)) < 0)
{
syslog(LOG_ERR, "bind(natpmp): %m");
syslog(LOG_ERR, "%s: bind(): %m",
"OpenAndConfNATPMPSocket");
close(snatpmp);
return -1;
}
@ -67,22 +68,25 @@ int OpenAndConfNATPMPSocket(in_addr_t addr)
int OpenAndConfNATPMPSockets(int * sockets)
{
int i, j;
int i;
struct lan_addr_s * lan_addr;
for(i = 0, lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next, i++)
for(i = 0, lan_addr = lan_addrs.lh_first;
lan_addr != NULL;
lan_addr = lan_addr->list.le_next)
{
sockets[i] = OpenAndConfNATPMPSocket(lan_addr->addr.s_addr);
if(sockets[i] < 0)
{
for(j=0; j<i; j++)
{
close(sockets[j]);
sockets[j] = -1;
}
return -1;
}
goto error;
i++;
}
return 0;
error:
while(--i >= 0)
{
close(sockets[i]);
sockets[i] = -1;
}
return -1;
}
static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr)
@ -124,15 +128,15 @@ static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr
* The sender information is stored in senderaddr.
* Returns number of bytes recevied, even if number is negative.
*/
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr,
unsigned char *msg_buff, size_t msg_buff_size)
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr,
socklen_t * senderaddrlen,
unsigned char * msg_buff, size_t msg_buff_size)
{
socklen_t senderaddrlen = sizeof(*senderaddr);
int n;
n = recvfrom(s, msg_buff, msg_buff_size, 0,
(struct sockaddr *)senderaddr, &senderaddrlen);
senderaddr, senderaddrlen);
if(n<0) {
/* EAGAIN, EWOULDBLOCK and EINTR : silently ignore (retry next time)

View File

@ -1,4 +1,4 @@
/* $Id: natpmp.h,v 1.11 2014/02/01 17:17:35 nanard Exp $ */
/* $Id: natpmp.h,v 1.12 2014/03/24 10:49:46 nanard Exp $ */
/* MiniUPnP project
* author : Thomas Bernard
* website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
@ -20,11 +20,12 @@
int OpenAndConfNATPMPSockets(int * sockets);
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr,
unsigned char *msg_buff, size_t msg_buff_size);
int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr,
socklen_t * senderaddrlen,
unsigned char * msg_buff, size_t msg_buff_size);
void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len,
struct sockaddr_in *senderaddr);
void ProcessIncomingNATPMPPacket(int s, unsigned char * msg_buff, int len,
struct sockaddr_in * senderaddr);
void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets);

View File

@ -1,4 +1,4 @@
/* $Id: pcpserver.c,v 1.20 2014/03/22 12:06:15 nanard Exp $ */
/* $Id: pcpserver.c,v 1.24 2014/03/24 11:03:52 nanard Exp $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Peter Tatrai
@ -53,6 +53,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <syslog.h>
#include "pcpserver.h"
#include "natpmp.h"
#include "macros.h"
#include "upnpglobalvars.h"
#include "pcplearndscp.h"
@ -60,6 +61,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "commonrdr.h"
#include "getifaddr.h"
#include "asyncsendto.h"
#include "upnputils.h"
#include "pcp_msg_struct.h"
#ifdef PCP_PEER
@ -117,7 +119,7 @@ typedef struct pcp_info {
uint8_t is_peer_op;
int thirdp_present; /* indicate presence of the options */
int pfailure_present;
char senderaddrstr[INET_ADDRSTRLEN];
char senderaddrstr[INET_ADDRSTRLEN]; /* only if IPv4 sender */
} pcp_info_t;
@ -1385,19 +1387,29 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info)
}
int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len,
struct sockaddr_in *senderaddr)
const struct sockaddr * senderaddr)
{
pcp_info_t pcp_msg_info;
#ifdef DEBUG
char addr_str[64];
#endif
memset(&pcp_msg_info, 0, sizeof(pcp_info_t));
if(!inet_ntop(AF_INET, &senderaddr->sin_addr,
pcp_msg_info.senderaddrstr,
sizeof(pcp_msg_info.senderaddrstr))) {
syslog(LOG_ERR, "inet_ntop(pcpserver): %m");
if(senderaddr->sa_family == AF_INET) {
const struct sockaddr_in * senderaddr_v4;
senderaddr_v4 = (const struct sockaddr_in *)senderaddr;
if(!inet_ntop(AF_INET, &senderaddr_v4->sin_addr,
pcp_msg_info.senderaddrstr,
sizeof(pcp_msg_info.senderaddrstr))) {
syslog(LOG_ERR, "inet_ntop(pcpserver): %m");
}
}
syslog(LOG_DEBUG, "PCP request received from %s:%hu %dbytes",
pcp_msg_info.senderaddrstr, ntohs(senderaddr->sin_port), len);
#ifdef DEBUG
if(sockaddr_to_string(senderaddr, addr_str, sizeof(addr_str)))
syslog(LOG_DEBUG, "PCP request received from %s %dbytes",
addr_str, len);
#endif
if(buff[1] & 128) {
/* discarding PCP responses silently */
@ -1421,4 +1433,44 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len,
return 0;
}
#ifdef ENABLE_IPV6
int OpenAndConfPCPv6Socket(void)
{
int s;
int i = 1;
struct sockaddr_in6 addr;
s = socket(PF_INET6, SOCK_DGRAM, 0/*IPPROTO_UDP*/);
if(s < 0) {
syslog(LOG_ERR, "%s: socket(): %m", "OpenAndConfPCPv6Socket");
return -1;
}
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) {
syslog(LOG_WARNING, "%s: setsockopt(SO_REUSEADDR): %m",
"OpenAndConfPCPv6Socket");
}
#ifdef IPV6_V6ONLY
/* force IPV6 only for IPV6 socket.
* see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0) {
syslog(LOG_WARNING, "%s: setsockopt(IPV6_V6ONLY): %m",
"OpenAndConfPCPv6Socket");
}
#endif
if(!set_non_blocking(s)) {
syslog(LOG_WARNING, "%s: set_non_blocking(): %m",
"OpenAndConfPCPv6Socket");
}
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(NATPMP_PORT);
addr.sin6_addr = in6addr_any;
if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
syslog(LOG_ERR, "%s: bind(): %m", "OpenAndConfPCPv6Socket");
close(s);
return -1;
}
return s;
}
#endif /*ENABLE_IPV6*/
#endif /*ENABLE_PCP*/

View File

@ -1,4 +1,4 @@
/* $Id: pcpserver.h,v 1.2 2013/12/13 15:48:39 nanard Exp $ */
/* $Id: pcpserver.h,v 1.3 2014/03/24 10:49:46 nanard Exp $ */
/* MiniUPnP project
* Website : http://miniupnp.free.fr/
* Author : Peter Tatrai
@ -36,12 +36,17 @@ POSSIBILITY OF SUCH DAMAGE.
#define PCP_MIN_LEN 24
#define PCP_MAX_LEN 1100
struct sockaddr_in;
struct sockaddr;
/*
* returns 0 upon success 1 otherwise
*/
int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len,
struct sockaddr_in *senderaddr);
const struct sockaddr *senderaddr);
/*
* returns the socket
*/
int OpenAndConfPCPv6Socket(void);
#endif /* PCPSERVER_H_INCLUDED */