[Sumover-dev] [svn commit] r3796 - vic/trunk/net
sumover-dev at cs.ucl.ac.uk
sumover-dev at cs.ucl.ac.uk
Wed Aug 23 14:58:24 BST 2006
Author: piers
Date: Wed Aug 23 14:57:55 2006
New Revision: 3796
Modified:
vic/trunk/net/net-ip.cpp
vic/trunk/net/net-ipv6.cpp
vic/trunk/net/net.cpp
vic/trunk/net/net.h
Log:
Added Source-Specific Multicast (SSM) support - tested IPv4 on WinXP.
Modified: vic/trunk/net/net-ip.cpp
==============================================================================
--- vic/trunk/net/net-ip.cpp (original)
+++ vic/trunk/net/net-ip.cpp Wed Aug 23 14:57:55 2006
@@ -56,6 +56,7 @@
#include "net-addr.h"
#ifndef INET_ADDRSTRLEN
+// IPv4 Address len = 4*3(addr bytes)+3(dots)+1(null terminator)=16
#define INET_ADDRSTRLEN (16)
#endif
@@ -96,7 +97,7 @@
class IPNetwork : public Network {
public:
- IPNetwork() : Network(*(new IPAddress), *(new IPAddress)) {;}
+ IPNetwork() : Network(*(new IPAddress), *(new IPAddress), *(new IPAddress)) {;}
virtual int command(int argc, const char*const* argv);
virtual void reset();
virtual Address* alloc(const char* name) {
@@ -116,7 +117,7 @@
int close();
int localname(sockaddr_in*);
int openssock(Address & addr, u_short port, int ttl);
- int openrsock(Address & addr, u_short port, Address & local);
+ int openrsock(Address & g_addr, Address & s_addr_ssm, u_short port, Address & local);
time_t last_reset_;
};
@@ -160,7 +161,7 @@
}
char* cp = tcl.result();
if (strcmp(argv[1], "addr") == 0) {
- strcpy(cp, addr_);
+ strcpy(cp, g_addr_);
return (TCL_OK);
}
if (strcmp(argv[1], "interface") == 0) {
@@ -180,7 +181,7 @@
return (TCL_OK);
}
if (strcmp(argv[1], "ismulticast") == 0) {
- u_int32_t addri = (IPAddress&)addr_;
+ u_int32_t addri = (IPAddress&)g_addr_;
tcl.result(IN_CLASSD(ntohl(addri))? "1" : "0");
return (TCL_OK);
}
@@ -218,11 +219,26 @@
int IPNetwork::open(const char * host, int port, int ttl)
{
- addr_ = host;
+ char *g_addr;
+ // Check for SSM src address: Src,Group
+ if ((g_addr=strchr(host,(int)','))!=NULL) {
+ char s_addr_ssm[MAXHOSTNAMELEN];
+ int i=0;
+ while (&host[i]<g_addr) {
+ s_addr_ssm[i]=host[i++];
+ }
+ s_addr_ssm[i]='\0';
+ g_addr_=++g_addr;
+ s_addr_ssm_=s_addr_ssm;
+ } else {
+ // No SSM address found - just use group host address
+ g_addr_=host;
+ }
port_ = port;
ttl_ = ttl;
- ssock_ = openssock(addr_, port, ttl);
+
+ ssock_ = openssock(g_addr_, port, ttl);
if (ssock_ < 0)
return (-1);
/*
@@ -235,7 +251,7 @@
return (-1);
}
(IPAddress&)local_ = local.sin_addr;
- rsock_ = openrsock(addr_, port, local_);
+ rsock_ = openrsock(g_addr_, s_addr_ssm_, port, local_);
if (rsock_ < 0) {
(void)::close(ssock_);
return (-1);
@@ -272,7 +288,7 @@
p->sin_port = 0;
}
// Use Local interface name if already set via command line
- if (((const char*)local_)[0]!='\0') {
+ if (local_.isset()) {
p->sin_addr.s_addr=(IPAddress&)local_;
return (0);
}
@@ -292,16 +308,17 @@
if (d > 3) {
last_reset_ = t;
(void)::close(ssock_);
- ssock_ = openssock(addr_, port_, ttl_);
+ ssock_ = openssock(g_addr_, port_, ttl_);
}
}
-int IPNetwork::openrsock(Address & addr, u_short port, Address & local)
+int IPNetwork::openrsock(Address & g_addr, Address & s_addr_ssm, u_short port, Address & local)
{
int fd;
struct sockaddr_in sin;
- u_int32_t addri = (IPAddress&)addr;
+ u_int32_t g_addri = (IPAddress&)g_addr;
+ u_int32_t g_addri_ssm = (IPAddress&)s_addr_ssm;
u_int32_t locali = (IPAddress&)local;
fd = socket(AF_INET, SOCK_DGRAM, 0);
@@ -327,14 +344,14 @@
sin.sin_family = AF_INET;
sin.sin_port = port;
#ifdef IP_ADD_MEMBERSHIP
- if (IN_CLASSD(ntohl(addri))) {
+ if (IN_CLASSD(ntohl(g_addri))) {
/*
* Try to bind the multicast address as the socket
* dest address. On many systems this won't work
* so fall back to a destination of INADDR_ANY if
* the first bind fails.
*/
- sin.sin_addr.s_addr = addri;
+ sin.sin_addr.s_addr = g_addri;
if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) {
@@ -342,25 +359,43 @@
exit(1);
}
}
- /*
- * XXX This is bogus multicast setup that really
- * shouldn't have to be done (group membership should be
- * implicit in the IP class D address, route should contain
- * ttl & no loopback flag, etc.). Steve Deering has promised
- * to fix this for the 4.4bsd release. We're all waiting
- * with bated breath.
- */
- struct ip_mreq mr;
-
- mr.imr_multiaddr.s_addr = addri;
- mr.imr_interface.s_addr = INADDR_ANY;
- if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- (char *)&mr, sizeof(mr)) < 0) {
- perror("IP_ADD_MEMBERSHIP");
- exit(1);
+ /* SSM code */
+#ifdef IP_ADD_SOURCE_MEMBERSHIP
+ struct ip_mreq_source mrs;
+ /* Check if an Src addr - as in S,G has been set */
+ if (s_addr_ssm.isset()) {
+ mrs.imr_sourceaddr.s_addr = g_addri_ssm;
+ mrs.imr_multiaddr.s_addr = g_addri;
+ mrs.imr_interface.s_addr = INADDR_ANY;
+ if (setsockopt(fd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
+ (char*)&mrs, sizeof(mrs)) < 0) {
+ perror("IP_ADD_SOURCE_MEMBERSHIP");
+ exit (1);
+ }
+ } else
+
+#endif /* IP_ADD_SOURCE_MEMBERSHIP */
+ {
+ /*
+ * XXX This is bogus multicast setup that really
+ * shouldn't have to be done (group membership should be
+ * implicit in the IP class D address, route should contain
+ * ttl & no loopback flag, etc.). Steve Deering has promised
+ * to fix this for the 4.4bsd release. We're all waiting
+ * with bated breath.
+ */
+ struct ip_mreq mr;
+
+ mr.imr_multiaddr.s_addr = g_addri;
+ mr.imr_interface.s_addr = INADDR_ANY;
+ if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (char *)&mr, sizeof(mr)) < 0) {
+ perror("IP_ADD_MEMBERSHIP");
+ exit(1);
+ }
}
} else
-#endif
+#endif /* IP_ADD_MEMBERSHIP */
{
/*
* bind the local host's address to this socket. If that
Modified: vic/trunk/net/net-ipv6.cpp
==============================================================================
--- vic/trunk/net/net-ipv6.cpp (original)
+++ vic/trunk/net/net-ipv6.cpp Wed Aug 23 14:57:55 2006
@@ -59,7 +59,7 @@
#include "config.h"
#include "net.h"
#include "vic_tcl.h"
-//#include "inet_ntop.h" //SV-XXX: FreeBSD
+#include "inet_ntop.h" //SV-XXX: FreeBSD
#include "inet6.h"
#include "net-addr.h"
@@ -80,6 +80,7 @@
#endif
#ifndef INET6_ADDRSTRLEN
+// Max IPv6 Address len = 8*4(addr hex)+7(semicolons)+1(null terminator)=40
#define INET6_ADDRSTRLEN (46)
#endif
@@ -120,7 +121,7 @@
class IP6Network : public Network {
public:
- IP6Network() : Network(*(new IP6Address), *(new IP6Address)) {;}
+ IP6Network() : Network(*(new IP6Address), *(new IP6Address), *(new IP6Address)) {;}
virtual int command(int argc, const char*const* argv);
virtual void reset();
virtual Address* alloc(const char* name) {
@@ -140,7 +141,7 @@
int close();
int localname(sockaddr_in6*);
int openssock(Address & addr, u_short port, int ttl);
- int openrsock(Address & addr, u_short port, Address & local);
+ int openrsock(Address & g_addr, Address & s_addr_ssm, u_short port, Address & local);
time_t last_reset_;
unsigned int flowLabel_; /* Flowlabel for all traffic */
int ifIndex_; /* Interface index to bind to on all layers */
@@ -191,7 +192,7 @@
char* cp = tcl.result();
if (strcmp(argv[1], "addr") == 0) {
/* __IPV6 use Address */
- strcpy(cp, addr_);
+ strcpy(cp, g_addr_);
return (TCL_OK);
}
if (strcmp(argv[1], "interface") == 0) {
@@ -213,7 +214,7 @@
}
/* __IPV6 use IN6_IS_ADDR */
if (strcmp(argv[1], "ismulticast") == 0) {
- const in6_addr & addr = (IP6Address&)addr_;
+ const in6_addr & addr = (IP6Address&)g_addr_;
tcl.result(IN6_IS_ADDR_MULTICAST(&addr)? "1" : "0");
return (TCL_OK);
/* __IPV6 user IPV6_MULTICAST_LOOP */
@@ -256,11 +257,26 @@
int IP6Network::open(const char * host, int port, int ttl)
{
- addr_ = host;
+ char *g_addr;
+ // Check for SSM src address: Src,Group
+ if ((g_addr=strchr(host,(int)','))!=NULL) {
+ char s_addr_ssm[MAXHOSTNAMELEN];
+ int i=0;
+ while (&host[i]<g_addr) {
+ s_addr_ssm[i]=host[i++];
+ }
+ s_addr_ssm[i]='\0';
+ g_addr_=++g_addr;
+ s_addr_ssm_=s_addr_ssm;
+ } else {
+ // No SSM address found - just use group host address
+ g_addr_=host;
+ }
+ g_addr_ = host;
port_ = port;
ttl_ = ttl;
- ssock_ = openssock(addr_, port, ttl);
+ ssock_ = openssock(g_addr_, port, ttl);
if (ssock_ < 0)
return (-1);
/*
@@ -274,7 +290,7 @@
}
(IP6Address&)local_ = local.sin6_addr;
- rsock_ = openrsock(addr_, port, local_);
+ rsock_ = openrsock(g_addr_, s_addr_ssm_, port, local_);
if (rsock_ < 0) {
(void)::close(ssock_);
return (-1);
@@ -313,7 +329,7 @@
// Use Local name if already set via command line
// But use port derived from getsockname
- if (((const char*)local_)[0]!='\0') {
+ if (local_.isset()) {
p->sin6_addr=(IP6Address&)local_;
return (result);
}
@@ -337,11 +353,11 @@
if (d > 3) {
last_reset_ = t;
(void)::close(ssock_);
- ssock_ = openssock(addr_, port_, ttl_);
+ ssock_ = openssock(g_addr_, port_, ttl_);
}
}
-int IP6Network::openrsock(Address & addr, u_short port, Address & local)
+int IP6Network::openrsock(Address & g_addr, Address & s_addr_ssm, u_short port, Address & local)
{
int fd;
struct sockaddr_in6 sin;
@@ -367,8 +383,9 @@
#endif
memset((char *)&sin, 0, sizeof(sin));
sin.sin6_family = AF_INET6;
- sin.sin6_addr = (IP6Address&)addr;
+ sin.sin6_addr = (IP6Address&)g_addr;
sin.sin6_port = port;
+
#ifdef IPV6_ADD_MEMBERSHIP
if (IN6_IS_ADDR_MULTICAST(&sin.sin6_addr)) {
/*
@@ -385,33 +402,54 @@
exit(1);
}
}
- /*
- * XXX This is bogus multicast setup that really
- * shouldn't have to be done (group membership should be
- * implicit in the IP class D address, route should contain
- * ttl & no loopback flag, etc.). Steve Deering has promised
- * to fix this for the 4.4bsd release. We're all waiting
- * with bated breath.
- */
- struct ipv6_mreq mr;
-/* __IPV6 memcopy address */
-#ifdef MUSICA_IPV6
- mr.i6mr_interface = (ifIndex_<0)?0:ifIndex_;
- mr.i6mr_multiaddr = (IP6Address&)addr;
-#else
- mr.ipv6mr_interface = (ifIndex_<0)?0:ifIndex_;
- mr.ipv6mr_multiaddr = (IP6Address&)addr;
-#endif
-
- int mreqsize = sizeof(mr);
-#ifdef WIN2K_IPV6
- mreqsize += 4;
-#endif
- if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
- (char *)&mr, mreqsize) < 0) {
- perror("IPV6_ADD_MEMBERSHIP");
- exit(1);
+#ifdef IPV6_ADD_SOURCE_MEMBERSHIP
+ struct ipv6_mreq_source mrs;
+ /* Check if an Src addr - as in S,G has been set */
+ if (s_addr_ssm.isset()) {
+ mrs.ipv6mr_sourceaddr = (IP6Address&)s_addr_ssm;
+ mrs.ipv6mr_interface = (ifIndex_<0)?0:ifIndex_;
+ mrs.ipv6mr_multiaddr = (IP6Address&)g_addr;
+
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_SOURCE_MEMBERSHIP,
+ (char*)&mrs, sizeof(mrs)) < 0) {
+ perror("IPV6_ADD_SOURCE_MEMBERSHIP");
+ exit (1);
+ }
+ } else
+
+#endif /* IPV6_ADD_SOURCE_MEMBERSHIP */
+ {
+ /*
+ * XXX This is bogus multicast setup that really
+ * shouldn't have to be done (group membership should be
+ * implicit in the IP class D address, route should contain
+ * ttl & no loopback flag, etc.). Steve Deering has promised
+ * to fix this for the 4.4bsd release. We're all waiting
+ * with bated breath.
+ */
+ struct ipv6_mreq mr;
+
+ /* __IPV6 memcopy address */
+ #ifdef MUSICA_IPV6
+ mr.i6mr_interface = (ifIndex_<0)?0:ifIndex_;
+ mr.i6mr_multiaddr = (IP6Address&)g_addr;
+ #else
+ mr.ipv6mr_interface = (ifIndex_<0)?0:ifIndex_;
+ mr.ipv6mr_multiaddr = (IP6Address&)g_addr;
+ #endif
+
+ int mreqsize = sizeof(mr);
+
+ // Fix for buggy header files in Win2k
+ #ifdef WIN2K_IPV6
+ mreqsize += 4;
+ #endif
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
+ (char *)&mr, mreqsize) < 0) {
+ perror("IPV6_ADD_MEMBERSHIP");
+ exit(1);
+ }
}
} else
#endif
@@ -480,10 +518,10 @@
sin.sin6_port = 0;
sin.sin6_flowinfo = flowLabel_;
/* __IPV6 memcopy address */
- // Use Local name if already set via command line
- if (((const char*)local_)[0]!='\0') {
+ // Use Local name if already set via command line
+ if (local_.isset()) {
sin.sin6_addr = (IP6Address&)local_;
- } else {
+ } else {
sin.sin6_addr = in6addr_any;
}
if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
@@ -502,6 +540,7 @@
exit(1);
}
if (IN6_IS_ADDR_MULTICAST(&sin.sin6_addr)) {
+
#ifdef IPV6_ADD_MEMBERSHIP
char c;
Modified: vic/trunk/net/net.cpp
==============================================================================
--- vic/trunk/net/net.cpp (original)
+++ vic/trunk/net/net.cpp Wed Aug 23 14:57:55 2006
@@ -110,10 +110,15 @@
Address * result = alloc(name);
return (result ? result : new Address());
}
-
+int Address::isset() {
+ if (text_!=0)
+ if (*text_!='\0') return 1;
+ return 0;
+}
Network::Network() :
- addr_(*(Address::default_alloc())),
+ g_addr_(*(Address::default_alloc())),
+ s_addr_ssm_(*(Address::default_alloc())),
local_(*(Address::default_alloc())),
lport_(0),
port_(0),
@@ -125,8 +130,9 @@
{
}
-Network::Network(Address & addr, Address & local) :
- addr_(addr),
+Network::Network(Address & g_addr, Address & s_addr_ssm, Address & local) :
+ g_addr_(g_addr),
+ s_addr_ssm_(s_addr_ssm),
local_(local),
lport_(0),
port_(0),
@@ -140,7 +146,8 @@
Network::~Network()
{
- if (&addr_) delete &addr_;
+ if (&g_addr_) delete &g_addr_;
+ if (&s_addr_ssm_) delete &s_addr_ssm_;
if (&local_) delete &local_;
}
Modified: vic/trunk/net/net.h
==============================================================================
--- vic/trunk/net/net.h (original)
+++ vic/trunk/net/net.h Wed Aug 23 14:57:55 2006
@@ -68,6 +68,7 @@
static Address * alloc(const char * name);
static Address * default_alloc();
+ int isset();
protected:
char *text_;
};
@@ -75,7 +76,7 @@
class Network : public TclObject {
public:
Network();
- Network(Address & addr, Address & local);
+ Network(Address & g_addr, Address & s_addr_ssm, Address & local);
virtual ~Network();
virtual int command(int argc, const char*const* argv);
virtual void send(u_char* buf, int len);
@@ -85,7 +86,7 @@
virtual int recv(u_char* buf, int len, Address &from);
inline int rchannel() const { return (rsock_); }
inline int schannel() const { return (ssock_); }
- inline const Address & addr() const { return (addr_); }
+ inline const Address & addr() const { return (g_addr_); }
inline const Address & interface() const { return (local_); }
inline int port() const { return (port_); }
inline int ttl() const { return (ttl_); }
@@ -100,7 +101,8 @@
virtual int dorecv(u_char* buf, int len, u_int32_t& from, int fd);
virtual int dorecv(u_char* buf, int len, Address &from, int fd) {UNUSED(buf); UNUSED(len); UNUSED(from); UNUSED(fd); return (0);}
- Address & addr_;
+ Address & g_addr_; // Group or host address
+ Address & s_addr_ssm_; // Src address (as in S,G) for SSM groups
Address & local_;
u_short lport_;
u_short port_;
More information about the Sumover-dev
mailing list