RE: Multicast: receiving my own streams

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There is socket option - IP_MULTICAST_LOOP which is probably what you
are looking for?

Regards,
Mayuresh. 


    >-----Original Message-----
    >From: linux-net-owner@xxxxxxxxxxxxxxx 
    >[mailto:linux-net-owner@xxxxxxxxxxxxxxx] On Behalf Of Alex Gonzalez
    >Sent: Friday, April 17, 2009 11:08 AM
    >To: linux-net@xxxxxxxxxxxxxxx
    >Subject: Multicast: receiving my own streams
    >
    >Hi,
    >
    >Please redirect me to another list if this is not the 
    >correct place to ask.
    >
    >I am seeing an issue with multicast routing which I didn't 
    >expect and
    >can't explain. Basically, I have an application which receives a
    >multicast stream and resends it to another multicast address.
    >
    >If the application then tries to listen on the new stream it just
    >generated, the kernel routes the stream back again to the 
    >application
    >layer. Note that the source ip address for this new stream 
    >is my own
    >ip address.
    >
    >Is this expected behaviour? Is there any way to avoid the 
    >kernel from
    >sending back packets which originated locally (apart from 
    >iptables or
    >source address filtering at the application layer).
    >
    >I enclose a short snippet which can reproduce it.
    >
    >Regards,
    >Alex
    >
    >------------------------------------------------------------------
    >
    >#define _GNU_SOURCE
    >#include <stdio.h>
    >#include <getopt.h>
    >#include <stdlib.h>
    >#include <errno.h>
    >#include <string.h>
    >#include <unistd.h>
    >#include "signal.h"
    >#include <sys/socket.h>
    >#include <resolv.h>
    >#include <arpa/inet.h>
    >#include <unistd.h>
    >#include <fcntl.h>
    >
    >#define TX_MC_IP "225.4.3.1"
    >#define TX_MC_PORT 5001
    >
    >#define RX_MC_IP "225.5.1.4"
    >#define RX_MC_PORT 5001
    >
    >int rx_sd;
    >int tx_sd;
    >
    >int sd;
    >
    >int skt_open( char * ip , int port  , int rx )
    > {
    >   int sd;
    >   char ipstr[strlen("xxx.yyy.zzz.yyy")];
    >        unsigned char * poctet = NULL;
    >   int ttl = 64;
    >   int ttl_size = sizeof(ttl);
    >   struct  sockaddr_in addr;
    >
    >       memset(&addr, 0, sizeof(addr));
    >
    >   sd = socket(AF_INET, SOCK_DGRAM, 0);
    >   if (sd >= 0)
    >   {
    >       int value = 1;
    >       setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &value, 
    >sizeof(value));
    >   }
    >   else
    >    {
    >       printf("Cannot open socket: %s\n",strerror(errno));
    >       return(errno);
    >    }
    >
    >   if( fcntl( sd , F_SETFL , O_NONBLOCK ) < 0 )
    >   {
    >       printf("Unable to make socket %d non blocking:
    >%s\n",sd,strerror(errno));
    >       return errno;
    >   }
    >
    >       addr.sin_family = AF_INET;
    >       addr.sin_port = htons(port);
    >       addr.sin_addr.s_addr = inet_addr(ip);
    >       printf("Binding skt %d to %s:%d\n",sd,ip,port);
    >
    >   if( bind(sd, (struct sockaddr *) &addr, sizeof(addr)) != 0 )
    >   {
    >       printf("Error binding socket %d: %s\n",sd,strerror(errno) );
    >       return(errno);
    >   }
    >
    >   if(rx)
    >   {
    >       poctet = (unsigned char *)&addr.sin_addr.s_addr;
    >       if( (*poctet > 0xE0) && (*poctet < 0xEF) )
    >       {
    >           struct ip_mreq mreq;
    >
    >           inet_aton(ip, &mreq.imr_multiaddr);
    >           mreq.imr_interface.s_addr = INADDR_ANY;
    >           if( setsockopt(sd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
    >sizeof(mreq)) == 0 )
    >               {
    >               printf("Joined multicast group for %s\n",ip);
    >               }
    >               else
    >               {
    >               printf("Unable to join multicast group for 
    >%s\n",ip);
    >               }
    >              }
    >        }
    >        else
    >       {
    >            int ttl_type = IP_TTL;
    >       poctet = (unsigned char *)&addr.sin_addr.s_addr;
    >           if( (*poctet > 0xE0) && (*poctet < 0xEF) )
    >               ttl_type = IP_MULTICAST_TTL;
    >           if( 0 != setsockopt( sd , SOL_IP , ttl_type , 
    >(void *)&ttl
    >, ttl_size ) )
    >           {
    >               ttl = -1;
    >               getsockopt( sd , SOL_IP , IP_TTL , (void *)&ttl ,
    >(socklen_t *)&ttl_size);
    >           printf("Unable to set ttl %s - default %d
    >hops\n",strerror(errno),ttl);
    >           }
    >           else
    >           {
    >                   ttl = -1;
    >                    getsockopt( sd , SOL_IP , IP_TTL , 
    >(void *)&ttl ,
    >(socklen_t *)&ttl_size);
    >           printf("Set ttl %d hops\n",ttl);
    >            }
    >        }
    >   printf("Opened socket %d for %s:%d\n",sd,ip,port);
    >   return sd;
    > }
    >
    > static void skt_print( int signo , siginfo_t *info , void 
    >*context )
    > {
    >    struct  sockaddr_in addr;
    >    int     addr_len = sizeof(addr);
    >    char    buffer[1400] = "";
    >    int     length = 0;
    >    static int      count = 0;
    >
    >    memset(&addr, 0, sizeof(addr));
    >
    >    if( info->si_code != POLL_IN )
    >    {
    >        printf("Unhandled event %d\r\n", (int)info->si_band);
    >        return;
    >    }
    >
    >    if ( length = recvfrom(info->si_fd, buffer, sizeof(buffer), 0,
    >(struct sockaddr *) &addr, (socklen_t*)&addr_len) )
    >    {
    >        if( count == 0 || count >= 10000 )
    >        {
    >            printf("Seeing packets from socket %d:
    >%08x:%d\n",info->si_fd,addr.sin_addr.s_addr,addr.sin_port);
    >           count = 0;
    >        }
    >        count ++;
    >    }
    >    return;
    > }
    >
    > static void skt_rx( int signo , siginfo_t *info , void *context )
    > {
    >    struct  sockaddr_in addr;
    >    int     addr_len = sizeof(addr);
    >    char    buffer[1400] = "";
    >    int     length = 0;
    >
    >    memset(&addr, 0, sizeof(addr));
    >
    >    if( info->si_code != POLL_IN )
    >    {
    >        printf("Unhandled event %d\r\n", (int)info->si_band);
    >        return;
    >    }
    >
    >    if ( length = recvfrom(info->si_fd, buffer, sizeof(buffer), 0,
    >(struct sockaddr *) &addr, (socklen_t*)&addr_len) )
    >    {
    >        addr.sin_family = AF_INET;
    >        addr.sin_port = htons(TX_MC_PORT);
    >        addr.sin_addr.s_addr = inet_addr(TX_MC_IP);
    >        if( length != sendto(tx_sd, buffer, length, MSG_DONTWAIT ,
    >(struct sockaddr *) &addr, sizeof(addr)) )
    >            printf("Send to %d failed\n",tx_sd);
    >    }
    >    return;
    > }
    >
    > int receivefrom( unsigned int skt , void(*fcn)(int, 
    >siginfo_t *, void
    >*) , int signo )
    > {
    >    struct sigaction signal_action;
    >    int flags;
    >
    >    /* Set socket flags to asynchronous */
    >    flags = fcntl(skt, F_GETFL);
    >    if( fcntl(skt, F_SETFL, flags | O_ASYNC) < 0 )
    >    {
    >        printf("Unable to make socket %d non blocking:
    >%s\n",skt,strerror(errno));
    >        return errno;
    >    }
    >
    >        // Request packet signal handler
    >    signal_action.sa_flags = SA_SIGINFO | SA_RESTART;
    >    signal_action.sa_sigaction = fcn;
    >    sigemptyset(&signal_action.sa_mask);
    >    sigaction(signo, &signal_action, NULL);
    >
    >    /* Set process id to send signal to */
    >    if( fcntl( skt , F_SETOWN , getpid() ) < 0 )
    >    {
    >        printf("Can't adquire SIGIO for skt %d: 
    >%s\n",skt,strerror(errno));
    >        return errno;
    >    }
    >
    >    /* Set signal number >= SIGRTMIN to send a RealTime signal */
    >    if( fcntl( skt, F_SETSIG, signo) < 0 )
    >    {
    >        printf("Can't assign signal to skt %d\n",skt);
    >        return errno;
    >    }
    >    printf("Receiving from socket %d in pid %d\n",skt,getpid());
    >    return 0;
    > }
    >
    > static void signal_handler( int sig_num )
    > {
    >   close(tx_sd);
    >   close(rx_sd);
    >   exit(1);
    > }
    >
    >int main(int argc, char *argv[])
    >{
    >   if(( signal(SIGTERM,&signal_handler) == SIG_ERR ) ||(
    >signal(SIGINT, &signal_handler) == SIG_ERR ) )
    >       printf("Error registering signal.\n");
    >
    >   // Open socket to send to
    >   tx_sd = skt_open( TX_MC_IP , TX_MC_PORT , 0 /*tx*/ );
    >   // Open socket to receive on
    >   rx_sd = skt_open( RX_MC_IP , RX_MC_PORT , 1 /*rx*/ );
    >   receivefrom(rx_sd , skt_rx , 38);
    >
    >   // Do I see the relay I'm outputting?
    >   sd = skt_open( TX_MC_IP , TX_MC_PORT , 1 /*rx*/ );
    >   receivefrom(sd , skt_print, 39);
    >
    >   //Wait for signals
    >   while (1)
    >   {
    >       sched_yield();
    >   }
    >   return 0;
    >}
    >--
    >To unsubscribe from this list: send the line "unsubscribe 
    >linux-net" in
    >the body of a message to majordomo@xxxxxxxxxxxxxxx
    >More majordomo info at  http://vger.kernel.org/majordomo-info.html
    >

--------------------------------------------------------------------------
NOTICE: If received in error, please destroy and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error.
--
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux