📄 igmp.c
字号:
if( (igmp_tbl[i].state != IGMP_FREE) && igmp_tbl[i].ndp == ndp ) { if( groupaddr ) { /* Must be a group-specific query. Only send reports for that specific group. */ if( MemToHost32(*groupaddr) != igmp_tbl[i].ip_multi ) continue; } /* local multicast does not have timer */ if (igmp_tbl[i].timer != (tcb *)0) { if ( igmp_tbl[i].state == IGMP_IDLE ) { igmp_tbl[i].state = IGMP_DELAY; t_start (igmp_tbl[i].timer, igmp_num(i, max_resp_time )); bFound = 1; }#ifdef IGMP_VERSION_2 else if( igmp_tbl[i].state == IGMP_DELAY ) { /* max_resp_time == 0 implies this is a V1 query */ if( max_resp_time != 0 ) { if( t_remaining(igmp_tbl[i].timer) > (u32)max_resp_time*(u32)100 ) { /* Per IGMPv2 spec we must restart the timer with a new random value bounded by the smaller Max Response Time */ t_stop(igmp_tbl[i].timer); igmp_tbl[i].state = IGMP_DELAY; t_start (igmp_tbl[i].timer, igmp_num(i, max_resp_time )); bFound = 1; } } }#endif } } } normal; return 0;}/********************************************************************** ** igmp_find () * * PARAMETERS: a32 *ip - Pointer to the ip multicast address * OL: netdev * ndp - pointer to the netdev structure * * DESCRIPTION: Searches the igmp_tbl for the IP multicast address * OL: on a given interface. If ndp is nil, search on all ndp's * The assumption is that there is only one IP in the * table. * * RETURNS: >= 0 - index in the igmp_tbl * -1 - no entry found ************************************************************************/int igmp_find (u32 ip, netdev * ndp){ int i; for (i=0; i < IGMP_CNT; i++) { if (igmp_tbl[i].state != IGMP_FREE) { if ( igmp_tbl[i].ip_multi == ip ) { /* OL: if ndp is nil same code as before */ if ((ndp == (netdev *)0) /* if ndp is non nil only returns if ndp's match too */ || (ndp == igmp_tbl[i].ndp)) return i; } } } return -1;}/********************************************************************** ** igmp_update () * * PARAMETERS: void *uarg - pointer to entry in igmp table as void. * * DESCRIPTION: Timer callback to send an IGMPv1 or IGMPv2 report. * We can only send v2 report if doing IGMP version 2 * and we have not seen a v1 router query in the last * IGMP_V1_ROUTER_PRESENT_TIMEOUT seconds on the corresponding * interface as determined by a flag * * RETURNS: 0 ************************************************************************/int igmp_update (void *uarg){ igmp_entry *entry; entry = (igmp_entry *) uarg; if (entry->state == IGMP_DELAY) { entry->state = IGMP_IDLE; igmp_send_report(entry); } return 0;}/********************************************************************** ** igmp_do_send () * * PARAMETERS: packet - pointer to a filled in IGMP IGMP_T structure * except for checksum which is taken care of. * ndp - device to send on. * ipdest - destination address to send to. * * DESCRIPTION: Creates IGMP packet and sends it through the * state machine. Takes care of IGMP checksum for caller. * * RETURNS: 0 - OK * 1 - error ************************************************************************/int igmp_do_send ( IGMP_T *packet, netdev *ndp, u32 ipdest ){ m *mp; int err; int size; size = (int)(SIZEOF_ENH + SIZEOF_IPH_T + SIZEOF_IGMP_T#ifdef IGMP_VERSION_2 + 4 /* This is for the IP router alert option */#endif ); if ((mp = m_new( size, (int *)&err, 0)) == (m *)0) {#ifdef DEBUG os_printf("igmp_do_send: out of heap !!!!!\n");#endif return FNS_ENOMEM; } mp->m_hp -= SIZEOF_IGMP_T; mp->m_flags = F_COMM_MASK; HostToNet16(&packet[IGMP_T_IGMP_CHECKSUM], 0); HostToNet16(&packet[IGMP_T_IGMP_CHECKSUM], (u16)~oc_sum((a16 *)packet, (int)SIZEOF_IGMP_T)); OS_MOVE_N((char *)mp->m_hp, (char *)packet, SIZEOF_IGMP_T); mp->m_dest.a_len = sizeof(ipa); mp->m_dest.a_type = AF_INET; mp->m_dest.a_ipa.ip_nethost = ipdest; mp->m_ndp = ndp; mp->m_type = IP_IGMP; mp->m_pflags |= F_M_ORIGIN; msm(mp, ip_send); return 0;}/*************** IGMP message-specific send routines ******************//********************************************************************** ** igmp_send_report * * PARAMETERS: entry - the igmp table entry we're reporting on * * DESCRIPTION: Sends Host Membership Report, either V1 or V2. If we're * running V2 looks to see if there is a V1 router present * on the interface before sending the V2 report. If so it * sends a V1 report. * * * RETURNS: 0 * ***********************************************************************/int igmp_send_report( igmp_entry *entry ){ IGMP_T packet[SIZEOF_IGMP_T]; netdev *ndp; u8 ptype = IGMP_V1_REPORT; ndp = entry->ndp;#ifdef IGMP_VERSION_2 if( !ndp->v1_router_present ) { /* Send a v2 report */ ptype = IGMP_V2_REPORT; }#endif /* Fill in the packet fields */ packet[IGMP_T_IGMP_TYPE] = ptype; /* unused field for reports */ packet[IGMP_T_MAX_RESP_TIME] = 0; /* 2 10ths sec */ HostToMem32(&packet[IGMP_T_IP_ADDR], entry->ip_multi); /* Set the last2report flag for the entry */ entry->last_2_report = true; igmp_do_send ( packet, entry->ndp, entry->ip_multi ); return 0;}/********************************************************************** ** igmp_send_general_query * * PARAMETERS: * * DESCRIPTION: Sends Host Membership General Query request * (for demo\test purposes). * * RETURNS: ************************************************************************/int igmp_send_general_query (char *devname, u8 max_resp_time ){ IGMP_T packet[SIZEOF_IGMP_T]; netdev *ndp; if ((ndp = ll_dev_2_ndp(devname)) == (netdev *)0) return FNS_ENODEV; /* Fill in the packet fields */ packet[IGMP_T_IGMP_TYPE] = IGMP_QUERY;#ifndef IGMP_VERSION_2 max_resp_time = 0;#endif packet[IGMP_T_MAX_RESP_TIME] = max_resp_time; /* Address is zero for general query */ HostToMem32(&packet[IGMP_T_IP_ADDR], 0x0 ); /* General query is sent to the all multicast hosts address */ igmp_do_send ( packet, ndp, IGMP_ALLHOST ); return 0;}/********************************************************************** ** igmp_send_group_query * * PARAMETERS: * * DESCRIPTION: Sends Host Membership Group-Specific Query request * (for demo\test purposes). * * RETURNS: ************************************************************************/int igmp_send_group_query ( igmp_entry *entry, u8 max_response_time ){ IGMP_T packet[SIZEOF_IGMP_T]; /* Fill in the packet fields */ packet[IGMP_T_IGMP_TYPE] = IGMP_QUERY; packet[IGMP_T_MAX_RESP_TIME] = max_response_time; /* 10ths of a sec */ /* Group specific query has IGMP address field set to group address */ HostToMem32(&packet[IGMP_T_IP_ADDR], entry->ip_multi); /* Group specific query has destination IP address set to group address */ igmp_do_send ( packet, entry->ndp, entry->ip_multi ); return 0;}/********************************************************************** ** igmp_num () * * PARAMETERS: int i - index into igmp table * u8 max_response_time - upper bound on time * * DESCRIPTION: Generates a 'random' time in the range of (0,max_response_time] * where max_response_time is in 10ths of a second. * If max_response_time is 0 then 100 10ths (10 secs) is used. * * * RETURNS: The time in milliseconds for the Fusion timer functions. * ***********************************************************************/u32igmp_num (int i, u8 max_response_time ){ u32 rv; u32 mod = modulus; if( max_response_time > 0 ) { /* max_response_time is in 10ths of a second and modulus must be in msecs. */ mod = ((u32)max_response_time * (u32)100); } rv = (igmp_tbl[i].seed + (i+1)*t_time) % mod; igmp_tbl[i].seed = rv; return rv;}/********************************************************************** ** igmp_attach () * * PARAMETERS: * * DESCRIPTION: Dummy function. * * RETURNS: ************************************************************************/export int igmp_attach (struct so_t * sop){ return 0;}/********************************************************************** * igmp_start * * PARAMETERS: added ndp parameter * * DESCRIPTION: Adds Multicast Broadcast addres to a device * that is supporting the IGMP. * * RETURNS: 0 - OK * ***********************************************************************/export int igmp_start (netdev * ndp){ int err; a32 ip_all; HostToNet32(ip_all, IGMP_ALLHOST); /* local multicast */ if (ndp->nd_xflags & F_X_MULTI_ENBL) { err = ip_add_multi_route ((char *)ndp->nd_name , (char *)&ip_all, 1 ); if (err) {#ifdef DEBUG os_printf("igmp_start: ip_add_multi_route returns %d\n",err);#endif return err; } } return 0;}/****************************************************************************** * * igmpFindNdp * * Given an IP multicast address return the associated ndp */netdev *igmpFindNdp (a32 * a32p){ int i; u32 ip; ip = MemToHost32((u8 *)a32p); i = igmp_find(ip, (netdev *)0); if (i >= 0) return igmp_tbl[i].ndp; else return (netdev *)0;}#endif /* IGMP_PROTOCOL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -