home *** CD-ROM | disk | FTP | other *** search
- #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 */
-