#if defined(MULTICAST) /* * Internet Group Management Protocol (IGMP) as per RFC 1112. * * This protocol is to allow multicast routers to establish group * membership on attached networks. Thus allowing the router to not send * data that is not needed. * * Jim Martin * Rutgers University - RUCS-TD/NS * jim@noc.rutgers.edu * 6/9/93 */ #include "wattcp.h" #include "stdlib.h" #include "copyright.h" typedef struct _pkt { in_Header in; IGMP_packet igmp; }; static int igmp_id = 0; /* * igmp_handler - handles the incoming IGMP packets * * void igmp_handler( in_Header *ip ) * Where: * ip is the IP packet in question * * Returns: None * */ void igmp_handler( ip ) in_Header *ip; { IGMP_packet *igmp; word len; byte i; longword host; len = in_GetHdrlenBytes(ip); igmp = (IGMP_packet *)((byte *)ip + len); /* If it doesn't check, drop it */ if ( checksum(igmp, 8) != 0xffff ){ return; } /* Get this out of the way right up front */ host = intel( igmp->address ); /* first determine whether this is a report or a query */ switch (igmp->type){ case( IGMP_Query ): for( i = 0 ; i < IPMULTI_SIZE ; i++){ if(_ipmulti[i].active && (_ipmulti[i].ina != ALL_SYSTEMS) && ( !_ipmulti[i].replytime )){ _ipmulti[i].replytime = time(NULL) + random(11); } } break; case( IGMP_Report ): for( i = 0 ; i < IPMULTI_SIZE ; i++){ if( _ipmulti[i].active && (_ipmulti[i].ina == host) && ( host != ALL_SYSTEMS )){ _ipmulti[i].replytime = 0; break; } } break; default: break; } } /* * igmp_report - send a IGMP Report packet * * int igmp_report( longword ina) * Where: * ina is the IP address to report. * * Returns: * 0 if unable to send report * 1 report was sent successfully */ int igmp_report( ina ) longword ina; { struct _pkt *pkt; in_Header *ip; IGMP_packet *igmp; eth_address ethaddr; /* get the ethernet addr of the destination */ multi_to_eth( (longword)ALL_SYSTEMS, ethaddr); /* format the packet with the request's hardware address */ pkt = (struct _pkt*)(_eth_formatpacket( ethaddr, 8)); /* make things a bit easier to work with */ ip = &pkt->in; igmp = &pkt->igmp; /* first fill in the igmp packet */ igmp->type = IGMP_Report; igmp->version = IGMP_Version; igmp->mbz = 0; igmp->checksum = 0; igmp->address = intel( ina ); /* then compute the IGMP checksum */ igmp->checksum = ~checksum(igmp, sizeof( IGMP_packet )); /* Now to stick it in an IP packet */ ip->ver = 4; ip->hdrlen = 5; ip->length = intel16( sizeof( in_Header ) + sizeof( IGMP_packet) ); ip->tos = 0; ip->identification = intel16 (igmp_id ++); /* ip->frag = 0; */ ip->ttl = 1; ip->proto = IGMP_PROTO; ip->checksum = 0; ip->source = intel( my_ip_addr ); ip->destination = intel( ina ); ip->checksum = ~checksum(ip, sizeof( in_Header )); _eth_send( intel16( ip->length )); return(1); } #endif /* MULTICAST */