mirror of
https://github.com/rofafor/vdr-plugin-iptv.git
synced 2023-10-10 13:37:03 +02:00
Refactored multicast source address validation.
This commit is contained in:
parent
b0dba49fbc
commit
2d583e8cfa
4
HISTORY
4
HISTORY
@ -142,11 +142,11 @@ VDR Plugin 'iptv' Revision History
|
||||
|
||||
- Updated for vdr-1.7.15.
|
||||
|
||||
2010-09-12: Version 0.4.3
|
||||
2010-09-15: Version 0.4.3
|
||||
|
||||
- Renamed Sid scanner to section id scanner and added
|
||||
experimental Tid/Nid support into it.
|
||||
- Added validation for source addresses of socket data.
|
||||
- Added optional source address validation for UDP protocol.
|
||||
- Fixed audio pid detection in pid scanner.
|
||||
- Changed ProvidesChannel() to set the need of detaching
|
||||
receivers due to VDR's channel selection mechanism.
|
||||
|
3
README
3
README
@ -161,6 +161,9 @@ Notes:
|
||||
- EIT scanning functionality can be disabled for all IPTV channels by applying
|
||||
the "disable_eitscan" patch to the VDR.
|
||||
|
||||
- Source address validation can be enabled for UDP protocol separated by
|
||||
adding the source address after a ';' character: "U=239.192.0.1;239.192.0.2"
|
||||
|
||||
Acknowledgements:
|
||||
|
||||
- The IPTV section filtering code is derived from Linux kernel.
|
||||
|
@ -109,7 +109,7 @@ bool cIptvProtocolExt::Open(void)
|
||||
if (!strlen(*scriptFile))
|
||||
return false;
|
||||
// Create the listening socket
|
||||
OpenSocket(INADDR_LOOPBACK, socketPort);
|
||||
OpenSocket(socketPort);
|
||||
// Execute the external script
|
||||
ExecuteScript();
|
||||
isActive = true;
|
||||
|
@ -19,10 +19,10 @@
|
||||
#include "protocolhttp.h"
|
||||
|
||||
cIptvProtocolHttp::cIptvProtocolHttp()
|
||||
: streamAddr(NULL),
|
||||
streamPath(strdup("/"))
|
||||
{
|
||||
debug("cIptvProtocolHttp::cIptvProtocolHttp()\n");
|
||||
streamAddr = strdup("");
|
||||
streamPath = strdup("/");
|
||||
}
|
||||
|
||||
cIptvProtocolHttp::~cIptvProtocolHttp()
|
||||
@ -59,7 +59,7 @@ bool cIptvProtocolHttp::Connect(void)
|
||||
}
|
||||
|
||||
// Ensure that socket is valid
|
||||
OpenSocket(sockAddr.sin_addr.s_addr, socketPort);
|
||||
OpenSocket(socketPort);
|
||||
|
||||
int err = connect(socketDesc, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
|
||||
// Non-blocking sockets always report in-progress error when connected
|
||||
|
@ -19,9 +19,10 @@
|
||||
#include "socket.h"
|
||||
|
||||
cIptvProtocolUdp::cIptvProtocolUdp()
|
||||
: streamAddr(strdup("")),
|
||||
sourceAddr(strdup(""))
|
||||
{
|
||||
debug("cIptvProtocolUdp::cIptvProtocolUdp()\n");
|
||||
streamAddr = strdup("");
|
||||
}
|
||||
|
||||
cIptvProtocolUdp::~cIptvProtocolUdp()
|
||||
@ -31,6 +32,7 @@ cIptvProtocolUdp::~cIptvProtocolUdp()
|
||||
cIptvProtocolUdp::Close();
|
||||
// Free allocated memory
|
||||
free(streamAddr);
|
||||
free(sourceAddr);
|
||||
}
|
||||
|
||||
bool cIptvProtocolUdp::JoinMulticast(void)
|
||||
@ -39,7 +41,7 @@ bool cIptvProtocolUdp::JoinMulticast(void)
|
||||
// Check that stream address is valid
|
||||
if (!isActive && !isempty(streamAddr)) {
|
||||
// Ensure that socket is valid
|
||||
OpenSocket(inet_addr(streamAddr), socketPort);
|
||||
OpenSocket(socketPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr));
|
||||
// Join a new multicast group
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = inet_addr(streamAddr);
|
||||
@ -59,7 +61,7 @@ bool cIptvProtocolUdp::DropMulticast(void)
|
||||
// Check that stream address is valid
|
||||
if (isActive && !isempty(streamAddr)) {
|
||||
// Ensure that socket is valid
|
||||
OpenSocket(inet_addr(streamAddr), socketPort);
|
||||
OpenSocket(socketPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr));
|
||||
// Drop the multicast group
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = inet_addr(streamAddr);
|
||||
@ -100,14 +102,21 @@ bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int
|
||||
{
|
||||
debug("cIptvProtocolUdp::Set(): Location=%s Parameter=%d Index=%d\n", Location, Parameter, Index);
|
||||
if (!isempty(Location)) {
|
||||
// Drop the multicast group
|
||||
DropMulticast();
|
||||
// Update stream address and port
|
||||
streamAddr = strcpyrealloc(streamAddr, Location);
|
||||
socketPort = Parameter;
|
||||
// Join a new multicast group
|
||||
JoinMulticast();
|
||||
}
|
||||
// Drop the multicast group
|
||||
DropMulticast();
|
||||
// Update stream address and port
|
||||
streamAddr = strcpyrealloc(streamAddr, Location);
|
||||
char *p = strstr(streamAddr, ";");
|
||||
if (p) {
|
||||
sourceAddr = strcpyrealloc(sourceAddr, p + 1);
|
||||
*p = 0;
|
||||
}
|
||||
else
|
||||
sourceAddr = strcpyrealloc(sourceAddr, "");
|
||||
socketPort = Parameter;
|
||||
// Join a new multicast group
|
||||
JoinMulticast();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
class cIptvProtocolUdp : public cIptvUdpSocket, public cIptvProtocolIf {
|
||||
private:
|
||||
char* streamAddr;
|
||||
char* sourceAddr;
|
||||
|
||||
private:
|
||||
bool JoinMulticast(void);
|
||||
|
41
socket.c
41
socket.c
@ -20,11 +20,10 @@
|
||||
cIptvSocket::cIptvSocket()
|
||||
: socketDesc(-1),
|
||||
socketPort(0),
|
||||
inetAddr(INADDR_NONE),
|
||||
isActive(false)
|
||||
{
|
||||
debug("cIptvSocket::cIptvSocket()\n");
|
||||
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||
memset(&sockAddr, '\0', sizeof(sockAddr));
|
||||
}
|
||||
|
||||
cIptvSocket::~cIptvSocket()
|
||||
@ -34,7 +33,7 @@ cIptvSocket::~cIptvSocket()
|
||||
CloseSocket();
|
||||
}
|
||||
|
||||
bool cIptvSocket::OpenSocket(const in_addr_t InetAddr, const int Port, const bool isUdp)
|
||||
bool cIptvSocket::OpenSocket(const int Port, const bool isUdp)
|
||||
{
|
||||
debug("cIptvSocket::OpenSocket()\n");
|
||||
// If socket is there already and it is bound to a different port, it must
|
||||
@ -43,9 +42,6 @@ bool cIptvSocket::OpenSocket(const in_addr_t InetAddr, const int Port, const boo
|
||||
debug("cIptvSocket::OpenSocket(): Socket tear-down\n");
|
||||
CloseSocket();
|
||||
}
|
||||
// inetAddr must be set after CloseSocket()
|
||||
if (inetAddr != InetAddr)
|
||||
inetAddr = InetAddr;
|
||||
// Bind to the socket if it is not active already
|
||||
if (socketDesc < 0) {
|
||||
int yes = 1;
|
||||
@ -65,7 +61,7 @@ bool cIptvSocket::OpenSocket(const in_addr_t InetAddr, const int Port, const boo
|
||||
ERROR_IF_FUNC(setsockopt(socketDesc, SOL_IP, IP_PKTINFO, &yes, sizeof(yes)) < 0, "setsockopt(IP_PKTINFO)",
|
||||
CloseSocket(), return false);
|
||||
// Bind socket
|
||||
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||
memset(&sockAddr, '\0', sizeof(sockAddr));
|
||||
sockAddr.sin_family = AF_INET;
|
||||
sockAddr.sin_port = htons((uint16_t)(Port & 0xFFFF));
|
||||
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
@ -87,13 +83,13 @@ void cIptvSocket::CloseSocket(void)
|
||||
close(socketDesc);
|
||||
socketDesc = -1;
|
||||
socketPort = 0;
|
||||
inetAddr = INADDR_NONE;
|
||||
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||
}
|
||||
}
|
||||
|
||||
// UDP socket class
|
||||
cIptvUdpSocket::cIptvUdpSocket()
|
||||
: sourceAddr(INADDR_ANY)
|
||||
{
|
||||
debug("cIptvUdpSocket::cIptvUdpSocket()\n");
|
||||
}
|
||||
@ -103,10 +99,18 @@ cIptvUdpSocket::~cIptvUdpSocket()
|
||||
debug("cIptvUdpSocket::~cIptvUdpSocket()\n");
|
||||
}
|
||||
|
||||
bool cIptvUdpSocket::OpenSocket(const in_addr_t InetAddr, const int Port)
|
||||
bool cIptvUdpSocket::OpenSocket(const int Port, const in_addr_t SourceAddr)
|
||||
{
|
||||
debug("cIptvUdpSocket::OpenSocket()\n");
|
||||
return cIptvSocket::OpenSocket(InetAddr, Port, true);
|
||||
sourceAddr = SourceAddr;
|
||||
return cIptvSocket::OpenSocket(Port, true);
|
||||
}
|
||||
|
||||
void cIptvUdpSocket::CloseSocket(void)
|
||||
{
|
||||
debug("cIptvUdpSocket::CloseSocket()\n");
|
||||
sourceAddr = INADDR_ANY;
|
||||
cIptvSocket::CloseSocket();
|
||||
}
|
||||
|
||||
int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||
@ -137,15 +141,16 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||
// Read data from socket
|
||||
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
||||
len = (int)recvmsg(socketDesc, &msgh, MSG_DONTWAIT);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
else if (len > 0) {
|
||||
ERROR_IF_RET(len < 0, "recvmsg()", return -1);
|
||||
if (len > 0) {
|
||||
// Process auxiliary received data and validate source address
|
||||
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
||||
for (cmsg = CMSG_FIRSTHDR(&msgh); (sourceAddr != INADDR_ANY) && (cmsg != NULL); cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
||||
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
||||
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
|
||||
if (i->ipi_addr.s_addr != inetAddr)
|
||||
if (i->ipi_addr.s_addr != sourceAddr) {
|
||||
//debug("Discard packet due to invalid source address: %s", inet_ntoa(i->ipi_addr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (BufferAddr[0] == TS_SYNC_BYTE)
|
||||
@ -193,10 +198,10 @@ cIptvTcpSocket::~cIptvTcpSocket()
|
||||
debug("cIptvTcpSocket::~cIptvTcpSocket()\n");
|
||||
}
|
||||
|
||||
bool cIptvTcpSocket::OpenSocket(const in_addr_t InetAddr, const int Port)
|
||||
bool cIptvTcpSocket::OpenSocket(const int Port)
|
||||
{
|
||||
debug("cIptvTcpSocket::OpenSocket()\n");
|
||||
return cIptvSocket::OpenSocket(InetAddr, Port, false);
|
||||
return cIptvSocket::OpenSocket(Port, false);
|
||||
}
|
||||
|
||||
int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||
@ -213,7 +218,5 @@ int cIptvTcpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
|
||||
if (isActive && socketDesc && BufferAddr && (BufferLen > 0))
|
||||
len = (int)recvfrom(socketDesc, BufferAddr, BufferLen, MSG_DONTWAIT,
|
||||
(struct sockaddr *)&sockAddr, &addrlen);
|
||||
//if (inetAddr != sockAddr.sin_addr.s_addr)
|
||||
// return -1;
|
||||
return len;
|
||||
}
|
||||
|
11
socket.h
11
socket.h
@ -14,12 +14,11 @@ class cIptvSocket {
|
||||
protected:
|
||||
int socketDesc;
|
||||
int socketPort;
|
||||
in_addr_t inetAddr;
|
||||
struct sockaddr_in sockAddr;
|
||||
bool isActive;
|
||||
|
||||
protected:
|
||||
bool OpenSocket(const in_addr_t InetAddr, const int Port, const bool isUdp);
|
||||
bool OpenSocket(const int Port, const bool isUdp);
|
||||
void CloseSocket(void);
|
||||
|
||||
public:
|
||||
@ -28,11 +27,15 @@ public:
|
||||
};
|
||||
|
||||
class cIptvUdpSocket : public cIptvSocket {
|
||||
private:
|
||||
in_addr_t sourceAddr;
|
||||
|
||||
public:
|
||||
cIptvUdpSocket();
|
||||
virtual ~cIptvUdpSocket();
|
||||
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||
bool OpenSocket(const in_addr_t InetAddr, const int Port);
|
||||
bool OpenSocket(const int Port, const in_addr_t SourceAddr = INADDR_ANY);
|
||||
void CloseSocket(void);
|
||||
};
|
||||
|
||||
class cIptvTcpSocket : public cIptvSocket {
|
||||
@ -40,7 +43,7 @@ public:
|
||||
cIptvTcpSocket();
|
||||
virtual ~cIptvTcpSocket();
|
||||
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
|
||||
bool OpenSocket(const in_addr_t InetAddr, const int Port);
|
||||
bool OpenSocket(const int Port);
|
||||
};
|
||||
|
||||
#endif // __IPTV_SOCKET_H
|
||||
|
Loading…
Reference in New Issue
Block a user