At 16:41 04.11.98 +0530, S.RadhaKrishna wrote:

>Hi,
>   Actually I'm looking for something that a user (not root) can do from an
>application program. It's not that I wanted to send always through en1
>and not en0. Like, when we send a unicast address, the kernel routes to the
>appropriate interface depending on the destination address. Can we say from
>an application program using socket interface to send a multicast packet
>through a particular interface ? I'm not sure whether it's possible using
>setsockopt, but this also needs "root" privileges I guess! Can't the kernel
>route the multicast packet on the interface to which the application has
>bound using the "bind" socket call?
>thanks

the following code snipped works for me...


  // check the interfaces and set the multicast network interface
  if (rMulticast) {
    struct ifreq ifr;

    ifr = getMulticastInterface(aMulticastInterface);
    memcpy ((char *)&rMulticastInterface, (char *)&ifr.ifr_addr,
sizeof(ifr.ifr_addr));

#ifdef __SUNOS__
    if (setsockopt(rSocket, IPPROTO_IP, IP_MULTICAST_IF,
(char*)&rMulticastInterface.sin_addr, sizeof(rMulticastInterface.sin_addr))
== -1) {
#else
    if (setsockopt(rSocket, IPPROTO_IP, IP_MULTICAST_IF,
&rMulticastInterface.sin_addr, sizeof(rMulticastInterface.sin_addr)) == -1) {
#endif
      ostrstream os;
      os << me << " setsockopt() failed: IP_MULTICAST_IF " <<
strerror(errno) << ends;
      char *msg = os.str();
      rLog->log(Log::ERROR, "%s", msg);
      throw data_sink_error (msg);
    }
    
    {
      ostrstream os;
      os << me << " interface " << ifr.ifr_name << ", inet " << inet_ntoa
(rMulticastInterface.sin_addr) << ends;
      char *msg = os.str();
      rLog->log(Log::NOTICE, "%s", msg);
      delete[] msg;
    }

  }


The getMulticastInterface() call:

struct ifreq TcpIpSinkThread::getMulticastInterface (const char*
aMulticastInterface) {
  char *me = "TcpIpSinkThread::getMulticastInterface()";
  
  // locals
  struct ifconf  ifc;
  char           buf[4096];
  string         multicastInterface;
  bool           interface = false;
  vector<string> interfaces;

  // set the string if not null
  if (aMulticastInterface != NULL)
    multicastInterface = aMulticastInterface;

  // retrieve the interfaces
  ifc.ifc_len = sizeof (buf);
  ifc.ifc_buf = buf;
  if (ioctl (rSocket, SIOCGIFCONF, (char *) &ifc) < 0) {
    ostrstream os;
    os << me << " ioctl() failed: SIOCGIFCONF " << strerror(errno) << ends;
    char *msg = os.str();
    rLog->log(Log::ERROR, "%s", msg);
    throw data_sink_error (msg);
  }

  // now retrieve the flags
  struct ifreq *ifr;

  // loop over all interfaces
  ifr = ifc.ifc_req;
  for (int n = ifc.ifc_len / sizeof (struct ifreq); --n >= 0; ifr++) {

    // check if this is the requested interface
    if ((!multicastInterface.empty()) &&
multicastInterface.compare(ifr->ifr_name))
      continue;

    // pushback the interface we are just checking
    interfaces.push_back(string(ifr->ifr_name));

    // check if it supports this protocol family
    if (ifr->ifr_addr.sa_family != AF_INET)
      continue;

    // now get the flags
    if (ioctl(rSocket, SIOCGIFFLAGS, (char *) ifr) < 0) {
      ostrstream os;
      os << me << " ioctl() failed: SIOCGIFFLAGS " << strerror(errno) << ends;
      char *msg = os.str();
      rLog->log(Log::ERROR, "%s", msg);
      throw data_sink_error (msg);
    }

    // now check if this is a valid, up, not loopback, and
multicast-supporting if
    if (((ifr->ifr_flags & IFF_UP) == 0) || (ifr->ifr_flags & IFF_LOOPBACK) ||
        ((ifr->ifr_flags & IFF_MULTICAST) == 0))
      continue;
        
    // this interface supports multicast
    interface = true;
    break;
  }

  // did we have a valid interface?
  if (!interface) {
    ostrstream os;
    os << me << " failed: (";

    // did we check some interfaces
    if (interfaces.size() > 0) {
      for (int i=0; i<interfaces.size()-1; i++)
        os << interfaces[i] << ", ";
      os << interfaces[interfaces.size()-1];
      os << ") not multicast enabled" << ends;
    }
    // else we did not find the selected interface
    else
      os << multicastInterface << ") unknown interface" << ends;

    // and throw the exception
    char *msg = os.str();
    rLog->log(Log::ERROR, "%s", msg);
    throw data_sink_error (msg);
  }

  return *ifr;
}


--
Christoph Moar ([EMAIL PROTECTED])  Tel. (++49) 89 636-44628
SIEMENS AG Corporate Technology                  Fax. (++49) 89 636-47457
Information and Media Technology
Office Adress:  SIEMENS AG  ZT IK 1,  Otto-Hahn-Ring  6,  D-81739  Munich
Postal Adress:  SIEMENS AG  ZT IK 1,  D-81730 Munich
pgpkey http://pgp5.ai.mit.edu:11371/pks/lookup?op=index&search=0xae81b9cc
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to [EMAIL PROTECTED]

Reply via email to