⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 igmp.c

📁 用于嵌入式系统的TCP/IP协议栈及若干服务
💻 C
📖 第 1 页 / 共 3 页
字号:
    entry = (igmp_entry *) knewa (igmp_entry, (int)IGMP_CNT);    if (entry == (igmp_entry *)0)    {#ifdef DEBUG        os_printf("igmpinit: out of heap !!!!!\n");#endif        return FNS_ENOMEM;    }    OS_MEMSET ((char *)entry, 0, (unsigned long)(sizeof(igmp_entry)*IGMP_CNT));    igmp_tbl = entry;    igmp_entries = 0;    return 0;}/********************************************************************** ** igmp_no_v1_router ( void *vndp ) * *  PARAMETERS:     vndp - A *netdev passed as a void * *  DESCRIPTION:    Timer callback for when the IGMPv2 No V1 Router Present *                  timer expires.  When it does when can then start sending *                  v2 reports again. * *  RETURNS:    none * ***********************************************************************/int igmp_no_v1_router( void *vndp ){    netdev *ndp = (netdev *)vndp;    if( !ndp ) {        /* Its times like this that you just want to die */        os_printf( "igmp_no_v1_router: INTERNAL ERROR - NULL ndp\n");        return -1;    }    ndp->v1_router_present = false;    return 0;}/********************************************************************** ** igmp_report () * *  PARAMETERS:     m *mp - pointer to the received structure * *  DESCRIPTION:    Processes a received IGMP V1 or V2 report.  Note *                  that there isn't really any difference in processing. *                  There are two different report types soley for *                  the benefit of IGMPv2 Routers so they can tell when *                  there are IGMPv2 hosts present. * * *  RETURNS:    none * ***********************************************************************/voidigmp_report( m *mp ){    fast    IGMP_T  *igmphp;    int     i;    igmphp = (IGMP_T *)mp->m_cp;    switch( IGMP_TP(igmphp) ) {    case IGMP_V1_REPORT:#ifdef IGMP_TEST        os_printf("\n\tIGMP_V1_REPORT from %lX : ",mp->m_src.a_ipa.ip_nethost);#endif        break;    case IGMP_V2_REPORT:#ifdef IGMP_TEST        os_printf("\n\tIGMP_V2_REPORT from %lX : ", mp->m_src.a_ipa.ip_nethost);#endif        break;    default:#ifdef IGMP_TEST        os_printf("\n\n\t\tIGMP REPORT RECEIVED WITH UNKNOWN TYPE from %lX\n",                mp->m_src.a_ipa.ip_nethost);#endif        return;    }    if ((i = igmp_find (MemToHost32(&igmphp[IGMP_T_IP_ADDR]),mp->m_ndp)) >= 0 ) {        if( igmp_tbl[i].state == IGMP_DELAY )        {            if (igmp_tbl[i].timer != (tcb *)0)            {                t_stop(igmp_tbl[i].timer);                igmp_tbl[i].state = IGMP_IDLE;                igmp_tbl[i].last_2_report = false;            }        }    }#ifdef DEBUG    else {        os_printf("IGMP report received but not one of our interfaces\n");    }#endif#ifdef IGMP_TEST    /* Print the report */    os_printf("MRP %02x : ", igmphp[IGMP_T_MAX_RESP_TIME]);    os_printf("Group addr %u.%u.%u.%u\n",                             igmphp[IGMP_T_IP_ADDR+0],                             igmphp[IGMP_T_IP_ADDR+1],                             igmphp[IGMP_T_IP_ADDR+2],                             igmphp[IGMP_T_IP_ADDR+3]);#endif}/********************************************************************** ** igmp_query () * *  PARAMETERS:     m *mp - pointer to the received structure * *  DESCRIPTION:    Processes a received IGMP V1 or V2 general, or group-specific *                  query. * *  RETURNS:    none * ***********************************************************************//* Note:  a new requirement for IGMPv2 is that when a query is received          and a group is already in the delaying state then the timer          should be reset to the new Max Response Time if, and only if,          the Max Response Time is < the time remaining before the timer          expires.*/voidigmp_query( m *mp ){    fast    IGMP_T  *igmphp;    use_critical;    u8      max_resp_time;    netdev *ndp = mp->m_ndp;    igmphp = (IGMP_T *)mp->m_cp;    /* First validate */    if( MemToHost32(&igmphp[IGMP_T_IP_ADDR]) == 0 ) {        /* Should be a general query.  Verify that it is           being sent to the allhost address.        */        if( ntohl(mp->m_dest.a_ipa.ip_nethost) != IGMP_ALLHOST ) {#ifdef DEBUG            os_printf("IGMP general query not addressed to all hosts\n");#endif            return;        }    }else {        /* Must be a group-specific query.  See if its legit        */        if( MemToHost32(&igmphp[IGMP_T_IP_ADDR]) != mp->m_dest.a_ipa.ip_nethost) {            return;        }    }    /* For IGMPv2 if this is a v1 query we must not send any v2 reports       on this interface (for any group) until IGMP_V1_ROUTER_PRESENT_TIMEOUT       seconds have passed.  By definition it is a v1 query if the max       response time is zero.    */    if( igmphp[IGMP_T_MAX_RESP_TIME] == 0 ) {        ndp->v1_router_present = true;        if( ndp->v1_router_tcb ) {            /* Stop timer and restart with full timeout again */            critical;            t_stop(ndp->v1_router_tcb);            normal;        }        /* Note that t_new will work for an existing timer also */        if( !(ndp->v1_router_tcb = t_new ( ndp->v1_router_tcb,                                           igmp_no_v1_router,                                           (void *)ndp,                                           (u32)IGMP_V1_ROUTER_PRESENT_TIMEOUT*(u32)1000,                                           (u16)0 ))        ) {#ifdef DEBUG            os_printf("igmp_report: Out of heap!!\n");#endif            return;        }    }    /* Now start timers */    if( ndp->v1_router_present ) {        max_resp_time = 0;    }else {        max_resp_time = igmphp[IGMP_T_MAX_RESP_TIME];    }    if( MemToHost32(&igmphp[IGMP_T_IP_ADDR]) == 0 ) {        /* General Query */        igmp_start_t (mp->m_ndp, (a32 *)0, max_resp_time);    }else {        /* Call igmp_start_t with the group address so it only starts the           timer for that entry.        */        igmp_start_t ( mp->m_ndp, (a32 *)&igmphp[IGMP_T_IP_ADDR], max_resp_time);    }}/********************************************************************** ** igmp_leave () * *  PARAMETERS:     m *mp - pointer to the received structure * *  DESCRIPTION:    Processes a received IGMP V2 leave message (demo/test) * *  RETURNS:        none * ***********************************************************************/voidigmp_leave( m *mp ){#ifdef IGMP_TEST    fast    IGMP_T  *igmphp;    int i;    igmphp = (IGMP_T *)mp->m_cp;    /* Validate the leave meassage */    if( mp->m_dest.a_ipa.ip_nethost != IGMP_ALLROUTER ) {        os_printf("IGMP V2 Leave not addressed to all routers\n");    }    if( !is_D_class( &igmphp[IGMP_T_IP_ADDR] )) {        os_printf("IGMP V2 Leave with group address not class D\n");    }    /* Print the report */    os_printf("\n\n\t\tIGMP V2 Leave received from %lX\n", mp->m_src.a_ipa.ip_nethost);    os_printf("\t\tMax Reponse Time (unused) = %02x\n", igmphp[IGMP_T_MAX_RESP_TIME] );    os_printf("\t\tGroup address = %u.%u.%u.%u\n",                    igmphp[IGMP_T_IP_ADDR + 0],                    igmphp[IGMP_T_IP_ADDR + 1],                    igmphp[IGMP_T_IP_ADDR + 2],                    igmphp[IGMP_T_IP_ADDR + 3] );#else    return;#endif}/********************************************************************** ** igmp_dink () * *  PARAMETERS:     m *mp - pointer to the received structure * *  DESCRIPTION:    Allows IGMP to set the TTL to 1 as required by the RFC * *  RETURNS:    next function (always dispose since we're done). ************************************************************************/int igmp_dink( m *mp ){    IPH_T   * iphp;    iphp = m_ptr(mp, IPH_T);    iphp[IPH_TTL] = 1;    return 0;}/********************************************************************** ** igmp_up () * *  PARAMETERS:     m *mp - pointer to the received structure * *  DESCRIPTION:    Checks if the following: *                      - igmp packet length *                      - igmp version *                      - igmp checksum *                      - Dest ip address is the same as group ip *                  Based on igmp type processes the packet. * *  RETURNS:    next function (always dispose since we're done). ************************************************************************/export st  igmp_up (struct m *mp){    fast    IGMP_T  *igmphp;    igmphp = (IGMP_T *)mp->m_cp;    if (mp->m_tp - mp->m_cp != SIZEOF_IGMP_T)    {#ifdef DEBUG        os_printf("igmp_up: wrong size\n");#endif        return (st)mp->m_dispfn;    }    /* We save the checksum of each incoming packet for use in the       "random" number generator.    */    offset = NetToHost16(&igmphp[IGMP_T_IGMP_CHECKSUM]);    if (oc_sum((a16 *)igmphp, mp->m_tp - mp->m_cp))    {#ifdef DEBUG        os_printf("igmp_up: wrong checksum\n");#endif        return (st)mp->m_dispfn;    }    switch (IGMP_TP(igmphp))    {        case IGMP_QUERY:            igmp_query(mp);            break;        case IGMP_V1_REPORT:        case IGMP_V2_REPORT:            igmp_report(mp);            break;        case IGMP_V2_LEAVE:            igmp_leave(mp);            break;        default:#ifdef DEBUG          os_printf("IGMP - UNKNOWN TYPE %x RECEIVED\n", IGMP_TP(igmphp));#endif          break;    }    return (st)mp->m_dispfn;}/********************************************************************** ** igmp_start_t () * *  PARAMETERS: netdev *ndp - device driver pointer * *  DESCRIPTION:    Starts the timer for all IDLE multicast entries in *                  the igmp_tbl. The interval timer is set by igmp_num(). * *  RETURNS:      0 if OK *               -1 if problem. ************************************************************************//* For IGMPv2 we must accept an (optionally NULL) group   address for the case of a group-specific query, and a max response   time for the case of IGMPv2 queries.  Also, for IGMPv2 (max_resp_time > 0)   we must restart the timer with a new random value <= max_resp_time   if t_remaining is greater than max_resp_time.*/int igmp_start_t (netdev *ndp, a32 *groupaddr, u8 max_resp_time ){    int i;    int bFound = 0;    use_critical;    critical;    for (i=0; i < IGMP_CNT; i++)    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -