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