#if defined(MULTICAST) /* * IP Multicasting extensions as per RFC 1112. * * These extensions include routines to detect multicast addresses, * transform Multicast IP addresses to Multicast Ethernet addresses, as * well as a mechanism to join and leave multicast groups. * * Jim Martin * Rutgers University - RUCS-TD/NS * jim@noc.rutgers.edu * 6/6/93 */ #include "wattcp.h" #include "copyright.h" multicast _ipmulti[IPMULTI_SIZE]; /* * is_multicast - determines if the given IP addr is Class D (Multicast) * * int is_multicast( longword ina ) * Where: * ina IP address in question * Returns: * 1 if ina is Class D * 0 if ina is not Class D */ int is_multicast( ina ) longword ina; { if ( (ina & CLASS_D_MASK) == CLASS_D_MASK ) return( 1 ); else return( 0 ); } /* * multi_to_eth - calculates the proper ethernet address for a given * IP Multicast address. * * int multi_to_eth( longword ina, eth_address *ethaddr ) * Where: * ina IP address to be converted * ethaddr Ethernet MAC address * Returns: * 1 if calculation is successful * 0 if calculation failed */ int multi_to_eth( ina, ethaddr ) longword ina; eth_address ethaddr; { longword top = ETH_MULTI; ina = ( ina & IPMULTI_MASK ); ethaddr[0] = ( top >> 16 ); ethaddr[1] = (( top >> 8 ) & 0xff); ethaddr[2] = ( top & 0xff ); ethaddr[3] = ( ina >> 16 ); ethaddr[4] = (( ina >> 8 ) & 0xff ); ethaddr[5] = ( ina & 0xff ); return( 1 ); } /* * join_mcast_group - joins a multicast group * * int join_mcast_group( longword ina ) * Where: * ina IP address of the group to be joined * Returns: * 1 if the group was joined successfully * 0 if attempt failed */ int join_mcast_group( ina ) longword ina; { byte i; int free = -1; /* first verify that it's a valid mcast address */ if ( ! is_multicast( ina )) return( 0 ); /* determine if the group has already been joined */ /* as well as what the first free slot is */ for( i = 0; i < IPMULTI_SIZE ; i++){ if( _ipmulti[i].active && (ina == _ipmulti[i].ina) ){ _ipmulti[i].processes++; return( 1 ); } if( ( free == -1 ) && ( ! _ipmulti[i].active ) ) free = i; } /* alas, no...we need to join it */ if( free == -1 ) /* out of slots! */ return( 0 ); _ipmulti[free].ina = ina; if ( ! _eth_join_mcast_group( free )) return( 0 ); return( 1 ); } /* * leave_mcast_group - leaves a multicast group * * int leave_mcast_group( longword ina ) * Where: * ina IP address of the group to be joined * Returns: * 1 if the group was left successfully * 0 if attempt failed */ int leave_mcast_group( ina ) longword ina; { byte i; int groupnum = -1; /* first verify that it's a valid mcast address */ if ( ! is_multicast( ina )) return( 0 ); /* determine if the group has more than one interested process. if so, then just decrement .processes and return */ for( i = 0; i < IPMULTI_SIZE ; i++){ if( _ipmulti[i].active && (ina == _ipmulti[i].ina)){ if (_ipmulti[i].processes > 1 ){ _ipmulti[i].processes--; return( 1 ); } else { groupnum = i; break; } } } /* did the ipaddr they gave match anything in _ipmulti ?? */ if ( groupnum == -1 ) return( 0 ); /* alas...we need to physically leave it */ if ( ! _eth_leave_mcast_group( groupnum )) return( 0 ); return( 1 ); } #endif /* MULTICAST */