📄 m2iflib.c
字号:
default: return ERROR; } return OK; }/***************************************************************************** m2IfPktCountRtnInstall - install an interface packet counter routine** This function installs a routine in the M2_ID. This routine is a packet* counter which is able to update all the interface counters.** RETURNS: ERROR if the M2_ID is NULL, OK if the routine was installed.*/STATUS m2IfPktCountRtnInstall ( M2_ID * pId, M2_PKT_COUNT_RTN pRtn ) { if (pId == NULL) return ERROR; pId->m2PktCountRtn = pRtn; return OK; }/***************************************************************************** m2IfCtrUpdateRtnInstall - install an interface counter update routine** This function installs a routine in the M2_ID. This routine is able to* update a single specified interface counter.** RETURNS: ERROR if the M2_ID is NULL, OK if the routine was installed.*/STATUS m2IfCtrUpdateRtnInstall ( M2_ID * pId, M2_CTR_UPDATE_RTN pRtn ) { if (pId == NULL) return ERROR; pId->m2CtrUpdateRtn = pRtn; return OK; }/***************************************************************************** m2IfVarUpdateRtnInstall - install an interface variable update routine** This function installs a routine in the M2_ID. This routine is able to* update a single specified interface variable.** RETURNS: ERROR if the M2_ID is NULL, OK if the routine was installed.*/STATUS m2IfVarUpdateRtnInstall ( M2_ID * pId, M2_VAR_UPDATE_RTN pRtn ) { if (pId == NULL) return ERROR; pId->m2VarUpdateRtn = pRtn; return OK; }/******************************************************************************** centiSecsGet - get hundreds of a second** The number of hundreds of a second that have passed since this routine was* first called.** RETURNS: Hundreds of a second since the group was initialized.** SEE ALSO: N/A*/LOCAL unsigned long centiSecsGet (void) { unsigned long currCentiSecs; unsigned long clkRate = sysClkRateGet (); if (startCentiSecs == 0) startCentiSecs = (tickGet () * 100) / clkRate; currCentiSecs = (tickGet () * 100) / clkRate; return (currCentiSecs - startCentiSecs); }/******************************************************************************** m2IfInit - initialize MIB-II interface-group routines** This routine allocates the resources needed to allow access to the * MIB-II interface-group variables. This routine must be called before any * interface variables can be accessed. The input parameter <pTrapRtn> is an* optional pointer to a user-supplied SNMP trap generator. The input parameter* <pTrapArg> is an optional argument to the trap generator. Only one trap* generator is supported.** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call m2IfInit() from within the kernel * protection domain only, and the data referenced in the <pTrapRtn> and * <pTrapArg> parameters must reside in the kernel protection domain. * This restriction does not apply to non-AE versions of VxWorks. ** RETURNS: OK, if successful; ERROR, if an error occurred.** ERRNO:* S_m2Lib_CANT_CREATE_IF_SEM** SEE ALSO: * m2IfGroupInfoGet(), m2IfTblEntryGet(), m2IfTblEntrySet(), m2IfDelete()*/STATUS m2IfInit ( FUNCPTR pTrapRtn, /* pointer to user trap generator */ void * pTrapArg /* pointer to user trap generator argument */ ) { /* add hooks for if.c */ _m2SetIfLastChange = (FUNCPTR) m2SetIfLastChange; _m2IfTableUpdate = (FUNCPTR) m2IfTableUpdate; /* Create the Interface semaphore */ if (m2InterfaceSem == NULL) { m2InterfaceSem = semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); if (m2InterfaceSem == NULL) { errnoSet (S_m2Lib_CANT_CREATE_IF_SEM); return (ERROR); } } /* Take the interface semaphore, and initialize group global variables */ semTake (m2InterfaceSem, WAIT_FOREVER); pM2TrapRtn = pTrapRtn; pM2TrapRtnArg = pTrapArg;#ifdef VIRTUAL_STACK _ifTableLastChange = 0; _ifStackLastChange = 0;#else /* VIRTUAL_STACK */ ifTableLastChange = 0; ifStackLastChange = 0;#endif /* VIRTUAL_STACK */ semGive (m2InterfaceSem); (void) centiSecsGet (); /* Initialize group time reference */ return (OK); }/***************************************************************************** m2IfTableUpdate - insert or remove an entry in the ifTable** This routine is called by if_attach and if_detach to insert/remove* an entry from the local m2IfLib ifTable. The status can be either* M2_IF_TABLE_INSERT or M2_IF_TABLE_REMOVE. The ifIndex that is searched* for in the AVL tree is specified in given the ifnet struct.* <if_ioctl> is a function pointer to change the flags on the interface.* <addr_get> is a function pointer to add the interface's addresses to* ifRcvAddressTable. Ethernet interfaces can use NULL for both function* pointers, other interfaces will need to pass an appropriate function.** RETURNS: ERROR if entry does not exist, OK if the entry was deleted*/STATUS m2IfTableUpdate ( struct ifnet * pIfNet, UINT status, /* attaching or detaching */ int (*if_ioctl) /* protocol specific ioctl or null for default (ethernet) */ (struct socket*,u_long,caddr_t), STATUS (*addr_get) /* func to grab the interface's addrs, null for default (ethernet) */ (struct ifnet*, M2_IFINDEX*) ) { UINT index; M2_IFINDEX * pIfIndex; M2_IFSTACKTBL * pIfStackTbl; M2_IFSTACKTBL * pTempS; M2_IFRCVADDRTBL * pIfRcvAddrTbl; M2_IFRCVADDRTBL * pTempR; M2_ID * pM2Id = NULL; long * pFlags = NULL; index = pIfNet->if_index; switch (status) { case M2_IF_TABLE_INSERT: { pIfIndex = KHEAP_ALLOC(sizeof(M2_IFINDEX)); if (!pIfIndex) return ERROR; memset(pIfIndex, 0, sizeof(M2_IFINDEX)); pIfIndex->ifIndex = index; pIfIndex->pIfStats = pIfNet; /* Set the MIB style flag */ pFlags = (long *) ifnetToEndFieldsGet (pIfNet, END_OBJ_FLAGS); if (pFlags) { if (*pFlags & END_MIB_2233) pIfIndex->mibStyle = TRUE; else pIfIndex->mibStyle = FALSE; } if (if_ioctl) /* use supplied ioctl */ { pIfIndex->ifIoctl = if_ioctl; } else /* default */ { pIfIndex->ifIoctl = ifioctl; } if (addr_get) { pIfIndex->rcvAddrGet = addr_get; } else { pIfIndex->rcvAddrGet = rcvEtherAddrGet; } /* Set Interface OID to default */ memcpy(pIfIndex->ifOid.idArray, ifZeroObjectId.idArray, ifZeroObjectId.idLength * sizeof(long)); pIfIndex->ifOid.idLength = ifZeroObjectId.idLength; /* Fill in the unicast and the multicast addresses */ (*pIfIndex->rcvAddrGet)(pIfNet, pIfIndex); semTake (m2InterfaceSem, WAIT_FOREVER); /* Insert the node in the tree */ if (avlInsert(pM2IfRootPtr, pIfIndex, (GENERIC_ARGUMENT)index, nextIndex) != OK) { semGive (m2InterfaceSem); KHEAP_FREE((char *)pIfIndex); return ERROR; } m2IfCount++; ifsInList = index;#ifdef VIRTUAL_STACK _ifTableLastChange = centiSecsGet();#else /* VIRTUAL_STACK */ ifTableLastChange = centiSecsGet();#endif /* VIRTUAL_STACK */ semGive (m2InterfaceSem); if (pM2TrapRtn != NULL) { (*pM2TrapRtn)(M2_LINK_UP_TRAP, pIfIndex->ifIndex, pM2TrapRtnArg); } return OK; } case M2_IF_TABLE_REMOVE: { semTake (m2InterfaceSem, WAIT_FOREVER); /* Remove the node from the tree */ if ((pIfIndex = (M2_IFINDEX *)avlDelete(pM2IfRootPtr, (GENERIC_ARGUMENT)index, nextIndex)) == NULL) { semGive (m2InterfaceSem); return ERROR; } pIfStackTbl = pIfIndex->pNextLower; while (pIfStackTbl != NULL) { pTempS = pIfStackTbl; pIfStackTbl = pIfStackTbl->pNextLower; KHEAP_FREE((char *)pTempS); } pIfRcvAddrTbl = pIfIndex->pRcvAddr; while (pIfRcvAddrTbl != NULL) { pTempR = pIfRcvAddrTbl; pIfRcvAddrTbl = pIfRcvAddrTbl->pNextEntry; KHEAP_FREE((char *)pTempR); } KHEAP_FREE((char *)pIfIndex); m2IfCount--;#ifdef VIRTUAL_STACK _ifTableLastChange = centiSecsGet();#else /* VIRTUAL_STACK */ ifTableLastChange = centiSecsGet();#endif /* VIRTUAL_STACK */ semGive (m2InterfaceSem); if ( (pM2TrapRtn != NULL) && (pIfNet->if_ioctl != NULL) && ((*pIfNet->if_ioctl)(pIfNet, SIOCGMIB2233, (caddr_t)&pM2Id) == 0) ) { if (pM2Id->m2Data.mibXIfTbl.ifLinkUpDownTrapEnable == M2_LINK_UP_DOWN_TRAP_ENABLED) { (*pM2TrapRtn)(M2_LINK_DOWN_TRAP, pIfIndex->ifIndex, pM2TrapRtnArg); } } return OK; } default: return ERROR; } }/******************************************************************************** rcvEtherAddrGet - populate the rcvAddr fields for the ifRcvAddressTable** This function needs to be called to add all physical addresses for which an* interface may receive or send packets. This includes unicast and multicast* addresses. The address is inserted into the linked list maintained in the* AVL node corresponding to the interface. Given the ifnet struct and the* AVL node corresponding to the interface, this function goes through all the* physical addresses associated with this interface and adds them into the* linked list.** RETURNS: OK, if successful; ERROR, otherwise. */STATUS rcvEtherAddrGet ( struct ifnet * pIfNet, /* pointer to the interface's ifnet */ M2_IFINDEX * pIfIndexEntry /* avl node */ ) { struct arpcom * pIfArpcom = (struct arpcom*) pIfNet; unsigned char * pEnetAddr = pIfArpcom->ac_enaddr; LIST * pMCastList = NULL; ETHER_MULTI * pEtherMulti = NULL; /* Copy the list of mcast addresses */ if ( (pIfArpcom->ac_if.if_ioctl != NULL) && ((*pIfArpcom->ac_if.if_ioctl)((struct ifnet *)pIfArpcom, SIOCGMCASTLIST, (caddr_t)&pMCastList) != 0) ) { return (ERROR); } /* First create the entry for the unicast address */ rcvEtherAddrAdd (pIfIndexEntry, pEnetAddr); /* Loop thru the mcast linked list and add the addresses */ for ( pEtherMulti = (ETHER_MULTI *) lstFirst (pMCastList); pEtherMulti != NULL; pEtherMulti = (ETHER_MULTI *) lstNext ((NODE *)pEtherMulti) ) { rcvEtherAddrAdd (pIfIndexEntry, (unsigned char *)pEtherMulti->addr); } return (OK); }/****************************************************************************** rcvEtherAddrAdd - add a physical address into the linked list** This function is a helper function for rcvEtherAddrGet. It is called to* add a single physical address into the linked list of addresses maintained* by the AVL node.** RETURNS: OK, if successful; ERROR, otherwise.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -