📄 igmp.c
字号:
/** Copyright (c) 1998-2001 by NETsilicon Inc.** This software is copyrighted by and is the sole property of* NETsilicon. All rights, title, ownership, or other interests* in the software remain the property of NETsilicon. This* software may only be used in accordance with the corresponding* license agreement. Any unauthorized use, duplication, transmission,* distribution, or disclosure of this software is expressly forbidden.** This Copyright notice may not be removed or modified without prior* written consent of NETsilicon.** NETsilicon, reserves the right to modify this software* without notice.** NETsilicon* 411 Waverley Oaks Road USA 781.647.1234* Suite 227 http://www.netsilicon.com* Waltham, MA 02452 AmericaSales@netsilicon.com*************************************************************************** $Name: Fusion 6.52 Fusion 6.51 $* $Date: 2001/11/28 17:57:03 $* $Source: M:/psisrc/stack/mcast/rcs/igmp.c $* $Revision: 1.24 $*************************************************************************** - Revision Log - ** Who When Why** FND 09/28/01 Rename t_start/t_delete to fns_t_start/fns_t_delete* to fix conflict with pSOS.**************************************************************************** File Description: IGMP V2**************************************************************************/#include "std.h"#ifdef IGMP_PROTOCOL#include "flags.h"#include "fr.h"#include "netdev.h"#include "netioc.h"#include "fns_mem.h"#include "fnsproto.h"#include "igmp.h"#include "enet.h"#include "nerrno.h"#include "debug.h"#include "fns_heap.h"#define t_start fns_t_start#define t_delete fns_t_delete/** external functions **/import netdev *ll_dev_2_ndp (char * devname);export igmp_entry *igmp_tbl;export u32 igmp_entries;/** internal functions **/u32 igmp_num (int i, u8 max_response_time );int igmp_do_send ( IGMP_T *packet, netdev *ndp, u32 ipdest );int igmp_send_report( igmp_entry *igmp_tab_entry );export int igmp_send_general_query (char *devname, u8 max_response_time );export int igmp_send_group_query ( igmp_entry *entry, u8 max_response_time );int igmp_update (void *uarg);int igmp_start_t (netdev *ndp, a32 *ipaddr, u8 max_response_time );static u32 modulus = 9997;static u32 offset;/********************************************************************* * * igmp_is_v2(void) * * DESCRIPTION: For any external code which wants to know if we are * configured for IGMP V2 operation via the IGMP_VERSION_2 * switch but doesn't want to include igmp.h * * RETURNS: 1 if we are v2, 0 if not * **/int igmp_is_v2(void){#ifdef IGMP_VERSION_2 return 1;#else return 0;#endif}/********************************************************************* ** ip_add_multi_route() * * PARAMETERS: 1. IP multicast address. * 2. Device name as in ncdev.c. * 3. local_mc is a boolean set to 1 if we don't * want this address to participate in IGMP * * DESCRIPTION: 1. Check if it is proper Multicast IP address. * 2. Adds Multi. IP address to the routing table on * the selected device. * 3. Allocates the entry in the igmp_tbl. * 4. Sets the state of new entry to DELAY so it is * sent at least twice. * 5. Sends igmp report of the new entry. * * RETURNS: 0 - OK * > 1 - error**********************************************************************/int ip_add_multi_route (char *devname, char *ip_address, int is_localmc ){ netdev *ndp; int err; int i = 0; u32 ip_address_u32; use_critical; err = 0; ip_address_u32 = MemToHost32((u8 *)ip_address); if ( !(is_D_class((u8 *)ip_address)) ) return FNS_EDESTADDRREQ; if ((ndp = ll_dev_2_ndp(devname)) == (netdev *)0) return FNS_ENODEV; /* Is this interface already a member of the specified multicast group? If so, all we need to do here is to increment the reference count for the interface. */ if ( (i = igmp_find (ip_address_u32, ndp)) >= 0 ) { /* This interface already a member of this multicast group */ igmp_tbl[i].refs++; return 0; } /* if */ /* If we get down here, then this is the first membership of the specified interface in the specified multicast group. So we need to create a new membership entry, provided we have room for it in our membership table */ if (igmp_entries >= IGMP_CNT) {#ifdef DEBUG os_printf("ip_add_multi_route: IGMP reference table full\n");#endif return FNS_ETOOMANYREFS; } /* If this is an ethernet interface, invoke the processing to take advantage of ethernet hardware's ethernet layer multicasting capability */ ndp->nd_xflags |= F_X_MULTI_ADDR; if (IS_LAN_TYPE((int)ndp->nd_lladdr.a_type)) { err = arp_multi_add (ndp, ip_address); if (err) { return(err); } } /* The IGMP_ALLHOSTS group doesn't need an entry */ if ( ip_address_u32 == IGMP_ALLHOST ) { return(0); } /* Well, all the condtions are met, we are going to add an entry to the IGMP table. */ /* go critical while manipulating the IGMP membership table */ critical; /* Look for a free entry in the IGMP table to use for this new membership */ for (i = 0; i < IGMP_CNT; i++) { if (igmp_tbl[i].state == IGMP_FREE) { break; } /* if */ } /* for */ if (i >= IGMP_CNT) { /* Something is seriously wrong -- earlier we decided that our IGMP table isn't full, yet we just looked for a free entry and didn't find one. */ normal;#ifdef DEBUG os_printf("ip_add_multi_route: IGMP reference table full (inconsistent)\n");#endif return FNS_ETOOMANYREFS; } igmp_entries++; igmp_tbl[i].state = IGMP_IDLE; igmp_tbl[i].ndp = ndp; igmp_tbl[i].ip_multi = ip_address_u32; igmp_tbl[i].seed = (int)ip_address_u32; igmp_tbl[i].refs = 1; if ( is_localmc ) { /* OL: Local Multicast does not need timers*/ igmp_tbl[i].timer = (tcb *)0; } else { if ( (igmp_tbl[i].timer = t_new((tcb *)0 , igmp_update, &igmp_tbl[i], igmp_num(i, 100), F_T_STOPPED)) == (tcb *)0) { normal;#ifdef DEBUG os_printf("ip_add_multi_route: out of heap for timer creation !!!!!\n");#endif return FNS_ENOMEM; } } /* Finished manipulating the membership table */ normal; /* JPP locals do not participate in reports */ if( !is_localmc ) { igmp_send_report( &igmp_tbl[i] ); igmp_tbl[i].state = IGMP_DELAY; igmp_tbl[i].last_2_report = true; t_start (igmp_tbl[i].timer, igmp_num(i, 100)); } else igmp_tbl[i].state = IGMP_STATIC; return err;}/********************************************************************* ** igmp_send_leave( igmpentry *entry ) * * PARAMETERS: entry - entry in igmp table. * * DESCRIPTION: Send a v2 leave message if conditions are OK. * * RETURNS: 0 - OK * 1 - error***********************************************************************/void igmp_send_leave( igmp_entry *entry ){#ifdef IGMP_VERSION_2 netdev *ndp = entry->ndp; IGMP_T packet[SIZEOF_IGMP_T]; /* Only can send if: 1. Built for V2 2. We have are sending IGMPv2 reports (we haven't heard an IGMPv1 Query in IGMP_V1_ROUTER_PRESENT_TIMEOUT seconds). 3. We were the last host to send a membership report for this group. */ if( ndp->v1_router_present || !entry->last_2_report ) { return; } /* Fill in the packet fields */ packet[IGMP_T_IGMP_TYPE] = IGMP_V2_LEAVE; /* unused field for reports */ packet[IGMP_T_MAX_RESP_TIME] = 0; HostToMem32(&packet[IGMP_T_IP_ADDR], entry->ip_multi); igmp_do_send ( packet, entry->ndp, IGMP_ALLROUTER );#else return;#endif}/********************************************************************* ** ip_del_multi_route() * * PARAMETERS: 1. Device name as in ncdev.c * 2. IP multicast address. * * DESCRIPTION: 1. Check if it is proper Multicast IP address. * 2. Deletes Multi. IP address from the routing table of * the selected device. * 3. Changes the sate of the igmp_tbl entry. * 4. Deletes the allocated time queue. * * RETURNS: 0 - OK * 1 - error***********************************************************************/int ip_del_multi_route (char * devname, char *ip_address){ netdev *ndp; int err; int i = 0; u32 ip_address_u32; use_critical; err = 0; if ( !(is_D_class((u8 *)ip_address)) ) {#ifdef DEBUG os_printf("ip_del_multi_route: wrong address\n");#endif return FNS_EADDRNOTAVAIL; } if ((ndp = ll_dev_2_ndp(devname)) == (netdev *)0) return FNS_ENODEV; ip_address_u32 = MemToHost32((u8 *)ip_address); if ((i = igmp_find (ip_address_u32, ndp)) >= 0) { /* refs is the number of references to the address on this interface. If it is non-zero there is nothing more to be done. If zero see below - we must remove it from the interface. */ if (--igmp_tbl[i].refs) { return 0; } } else {#ifdef DEBUG os_printf("ip_del_multi_route: address not in igmp table\n");#endif return FNS_EADDRNOTAVAIL; } /* For IGMPv2 send a leave message */ igmp_send_leave( &igmp_tbl[i] ); critical; igmp_tbl[i].state = IGMP_FREE; igmp_tbl[i].last_2_report = false; igmp_entries--; /* OL: local multicast does not have a timer */ if (igmp_tbl[i].timer != (tcb *)0) t_delete (igmp_tbl[i].timer); normal; /* OL: deleted interface to old router */ /* OL: replaced comparison to AF_ETHER with macro */ if (IS_LAN_TYPE((int)ndp->nd_lladdr.a_type)) err = arp_multi_del (ndp, ip_address); return err;}/* * dummy timer callback * */int igmpdummy( void *dummy ){ return 0;}/********************************************************************* ** igmpinit () * * PARAMETERS: prp - protocol structure * * DESCRIPTION: 1. Allocates IGMP_CNT entries in the igm_tbl and * initialize them to 0. * * RETURNS: 0 - OK * 1 - error ************************************************************************/export int igmpinit (pr_t * prp){ igmp_entry *entry;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -