1
0
mirror of https://github.com/rofafor/vdr-plugin-iptv.git synced 2023-10-10 13:37:03 +02:00

Changed UDP protocol to always utilize the source address validation.

This commit is contained in:
Rolf Ahrenberg 2012-04-02 00:35:32 +03:00
parent 9145fb8bb8
commit c475b26515
6 changed files with 31 additions and 41 deletions

View File

@ -164,3 +164,5 @@ VDR Plugin 'iptv' Revision History
- Updated for vdr-1.7.27. - Updated for vdr-1.7.27.
- Fixed some channel switching bugs. - Fixed some channel switching bugs.
- Added support for a service interface. - Added support for a service interface.
- Changed UDP protocol to always utilize the source address
validation.

3
README
View File

@ -161,9 +161,6 @@ Notes:
- EIT scanning functionality can be disabled for all IPTV channels by applying - EIT scanning functionality can be disabled for all IPTV channels by applying
the "disable_eitscan" patch to the VDR. 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"
- Section id and pid scanners should be disabled after the correct data is - Section id and pid scanners should be disabled after the correct data is
found. This can be made via VDR's channel editor. found. This can be made via VDR's channel editor.

View File

@ -20,7 +20,6 @@
cIptvProtocolUdp::cIptvProtocolUdp() cIptvProtocolUdp::cIptvProtocolUdp()
: streamAddr(strdup("")), : streamAddr(strdup("")),
sourceAddr(strdup("")),
streamPort(0) streamPort(0)
{ {
debug("cIptvProtocolUdp::cIptvProtocolUdp()\n"); debug("cIptvProtocolUdp::cIptvProtocolUdp()\n");
@ -33,33 +32,31 @@ cIptvProtocolUdp::~cIptvProtocolUdp()
cIptvProtocolUdp::Close(); cIptvProtocolUdp::Close();
// Free allocated memory // Free allocated memory
free(streamAddr); free(streamAddr);
free(sourceAddr);
} }
bool cIptvProtocolUdp::Open(void) bool cIptvProtocolUdp::Open(void)
{ {
debug("cIptvProtocolUdp::Open(): sourceAddr=%s streamAddr=%s\n", sourceAddr, streamAddr); debug("cIptvProtocolUdp::Open(): streamAddr=%s\n", streamAddr);
OpenSocket(streamPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
// Join a new multicast group // Join a new multicast group
JoinMulticast(inet_addr(streamAddr)); JoinMulticast();
} }
return true; return true;
} }
bool cIptvProtocolUdp::Close(void) bool cIptvProtocolUdp::Close(void)
{ {
debug("cIptvProtocolUdp::Close(): sourceAddr=%s streamAddr=%s\n", sourceAddr, streamAddr); debug("cIptvProtocolUdp::Close(): streamAddr=%s\n", streamAddr);
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
// Drop the multicast group // Drop the multicast group
OpenSocket(streamPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
DropMulticast(inet_addr(streamAddr)); DropMulticast();
} }
// Close the socket // Close the socket
CloseSocket(); CloseSocket();
// Do NOT reset stream and source addresses // Do NOT reset stream and source addresses
//streamAddr = strcpyrealloc(streamAddr, ""); //streamAddr = strcpyrealloc(streamAddr, "");
//sourceAddr = strcpyrealloc(sourceAddr, "");
//streamPort = 0; //streamPort = 0;
return true; return true;
} }
@ -75,23 +72,16 @@ bool cIptvProtocolUdp::Set(const char* Location, const int Parameter, const int
if (!isempty(Location)) { if (!isempty(Location)) {
// Drop the multicast group // Drop the multicast group
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
OpenSocket(streamPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
DropMulticast(inet_addr(streamAddr)); DropMulticast();
} }
// Update stream address and port // Update stream address and port
streamAddr = strcpyrealloc(streamAddr, Location); streamAddr = strcpyrealloc(streamAddr, Location);
char *p = strstr(streamAddr, ";");
if (p) {
sourceAddr = strcpyrealloc(sourceAddr, p + 1);
*p = 0;
}
else
sourceAddr = strcpyrealloc(sourceAddr, "");
streamPort = Parameter; streamPort = Parameter;
// Join a new multicast group // Join a new multicast group
if (!isempty(streamAddr)) { if (!isempty(streamAddr)) {
OpenSocket(streamPort, isempty(sourceAddr) ? INADDR_ANY : inet_addr(sourceAddr)); OpenSocket(streamPort, inet_addr(streamAddr));
JoinMulticast(inet_addr(streamAddr)); JoinMulticast();
} }
} }
return true; return true;

View File

@ -15,7 +15,6 @@
class cIptvProtocolUdp : public cIptvUdpSocket, public cIptvProtocolIf { class cIptvProtocolUdp : public cIptvUdpSocket, public cIptvProtocolIf {
private: private:
char* streamAddr; char* streamAddr;
char* sourceAddr;
int streamPort; int streamPort;
public: public:

View File

@ -18,8 +18,8 @@
#include "socket.h" #include "socket.h"
cIptvSocket::cIptvSocket() cIptvSocket::cIptvSocket()
: socketDesc(-1), : socketPort(0),
socketPort(0), socketDesc(-1),
isActive(false) isActive(false)
{ {
debug("cIptvSocket::cIptvSocket()\n"); debug("cIptvSocket::cIptvSocket()\n");
@ -89,7 +89,7 @@ void cIptvSocket::CloseSocket(void)
// UDP socket class // UDP socket class
cIptvUdpSocket::cIptvUdpSocket() cIptvUdpSocket::cIptvUdpSocket()
: sourceAddr(INADDR_ANY) : streamAddr(INADDR_ANY)
{ {
debug("cIptvUdpSocket::cIptvUdpSocket()\n"); debug("cIptvUdpSocket::cIptvUdpSocket()\n");
} }
@ -99,28 +99,28 @@ cIptvUdpSocket::~cIptvUdpSocket()
debug("cIptvUdpSocket::~cIptvUdpSocket()\n"); debug("cIptvUdpSocket::~cIptvUdpSocket()\n");
} }
bool cIptvUdpSocket::OpenSocket(const int Port, const in_addr_t SourceAddr) bool cIptvUdpSocket::OpenSocket(const int Port, const in_addr_t StreamAddr)
{ {
debug("cIptvUdpSocket::OpenSocket()\n"); debug("cIptvUdpSocket::OpenSocket()\n");
sourceAddr = SourceAddr; streamAddr = StreamAddr;
return cIptvSocket::OpenSocket(Port, true); return cIptvSocket::OpenSocket(Port, true);
} }
void cIptvUdpSocket::CloseSocket(void) void cIptvUdpSocket::CloseSocket(void)
{ {
debug("cIptvUdpSocket::CloseSocket()\n"); debug("cIptvUdpSocket::CloseSocket()\n");
sourceAddr = INADDR_ANY; streamAddr = INADDR_ANY;
cIptvSocket::CloseSocket(); cIptvSocket::CloseSocket();
} }
bool cIptvUdpSocket::JoinMulticast(const in_addr_t StreamAddr) bool cIptvUdpSocket::JoinMulticast(void)
{ {
debug("cIptvUdpSocket::JoinMulticast()\n"); debug("cIptvUdpSocket::JoinMulticast()\n");
// Check if socket exists // Check if socket exists
if (!isActive && (socketDesc >= 0)) { if (!isActive && (socketDesc >= 0)) {
// Join a new multicast group // Join a new multicast group
struct ip_mreq mreq; struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = StreamAddr; mreq.imr_multiaddr.s_addr = streamAddr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY); mreq.imr_interface.s_addr = htonl(INADDR_ANY);
ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_ADD_MEMBERSHIP)", return false); ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_ADD_MEMBERSHIP)", return false);
// Update multicasting flag // Update multicasting flag
@ -129,14 +129,14 @@ bool cIptvUdpSocket::JoinMulticast(const in_addr_t StreamAddr)
return true; return true;
} }
bool cIptvUdpSocket::DropMulticast(const in_addr_t StreamAddr) bool cIptvUdpSocket::DropMulticast(void)
{ {
debug("cIptvUdpSocket::DropMulticast()\n"); debug("cIptvUdpSocket::DropMulticast()\n");
// Check if socket exists // Check if socket exists
if (isActive && (socketDesc >= 0)) { if (isActive && (socketDesc >= 0)) {
// Drop the existing multicast group // Drop the existing multicast group
struct ip_mreq mreq; struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = StreamAddr; mreq.imr_multiaddr.s_addr = streamAddr;
mreq.imr_interface.s_addr = htonl(INADDR_ANY); mreq.imr_interface.s_addr = htonl(INADDR_ANY);
ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_DROP_MEMBERSHIP)", return false); ERROR_IF_RET(setsockopt(socketDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0, "setsockopt(IP_DROP_MEMBERSHIP)", return false);
// Update multicasting flag // Update multicasting flag
@ -180,10 +180,10 @@ int cIptvUdpSocket::Read(unsigned char* BufferAddr, unsigned int BufferLen)
} }
else if (len > 0) { else if (len > 0) {
// Process auxiliary received data and validate source address // Process auxiliary received data and validate source address
for (cmsg = CMSG_FIRSTHDR(&msgh); (sourceAddr != INADDR_ANY) && (cmsg != NULL); cmsg = CMSG_NXTHDR(&msgh, cmsg)) { for (cmsg = CMSG_FIRSTHDR(&msgh); (streamAddr != INADDR_ANY) && (cmsg != NULL); cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) { if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg); struct in_pktinfo *i = (struct in_pktinfo *)CMSG_DATA(cmsg);
if (i->ipi_addr.s_addr != sourceAddr) { if (i->ipi_addr.s_addr != streamAddr) {
//debug("Discard packet due to invalid source address: %s", inet_ntoa(i->ipi_addr)); //debug("Discard packet due to invalid source address: %s", inet_ntoa(i->ipi_addr));
return 0; return 0;
} }

View File

@ -11,9 +11,11 @@
#include <arpa/inet.h> #include <arpa/inet.h>
class cIptvSocket { class cIptvSocket {
private:
int socketPort;
protected: protected:
int socketDesc; int socketDesc;
int socketPort;
struct sockaddr_in sockAddr; struct sockaddr_in sockAddr;
bool isActive; bool isActive;
@ -28,16 +30,16 @@ public:
class cIptvUdpSocket : public cIptvSocket { class cIptvUdpSocket : public cIptvSocket {
private: private:
in_addr_t sourceAddr; in_addr_t streamAddr;
public: public:
cIptvUdpSocket(); cIptvUdpSocket();
virtual ~cIptvUdpSocket(); virtual ~cIptvUdpSocket();
virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen); virtual int Read(unsigned char* BufferAddr, unsigned int BufferLen);
bool OpenSocket(const int Port, const in_addr_t SourceAddr = INADDR_ANY); bool OpenSocket(const int Port, const in_addr_t StreamAddr = INADDR_ANY);
void CloseSocket(void); void CloseSocket(void);
bool JoinMulticast(const in_addr_t StreamAddr); bool JoinMulticast(void);
bool DropMulticast(const in_addr_t StreamAddr); bool DropMulticast(void);
}; };
class cIptvTcpSocket : public cIptvSocket { class cIptvTcpSocket : public cIptvSocket {