//============================================================================= // Copyright (c) 1997 Microsoft Corporation // // File Name: macros.h // // Abstract: // This file contains many macros and #defines. // // Author: K.S.Lokesh (lokeshs@) 11-1-97 // // Revision History: // //============================================================================= #ifndef _MACROS_H_ #define _MACROS_H //------------------------------------------------------------------------------ // DEBUG FLAGS //------------------------------------------------------------------------------ //kslksl #define SET_MOST_DEBUG 0 // check for memory leaks #define DEBUG_FLAGS_MEM_ALLOC (1 | SET_MOST_DEBUG) //#define DEBUG_FLAGS_MEM_LEAK (DBG | DEBUG_FLAGS_MEM_ALLOC) // set it to above #define DEBUG_FLAGS_MEM_LEAK 0 // assert on error //deldel replace 1 with 0 #define DEBUG_FLAGS_ASSERT_ON_ERRORS (0 | SET_MOST_DEBUG) // DebugCheck #define CALL_MSG(str) {\ DbgPrint("\nCall Lokeshs with this stack. dont hit go. " str ,__FILE__,__LINE__,NULL);\ IgmpDbgBreakPoint();\ DbgPrint("\nCall Lokeshs with this stack. dont hit go. " str ,__FILE__,__LINE__,NULL);\ } //------------------------------------------------------------------------------ // TMP DEBUGGING //DebugCheck //------------------------------------------------------------------------------ extern DWORD DEBUG_CHECK_LOW_INDEX_ARRAY[100][2]; extern DWORD DebugIgmpIndex; #define DEBUG_CHECK_LOW_INDEX(i) {\ DebugIgmpIndex = (++DebugIgmpIndex) % 100; \ DEBUG_CHECK_LOW_INDEX_ARRAY[DebugIgmpIndex][0] = i;\ DEBUG_CHECK_LOW_INDEX_ARRAY[DebugIgmpIndex][1] = g_TimerStruct.TableLowIndex;\ if (g_TimerStruct.TableLowIndex>64 && g_TimerStruct.TableLowIndex!=~0) IgmpDbgBreakPoint();\ if (g_TimerStruct.TableLowIndex>64 && g_TimerStruct.NumTimers!=0) IgmpDbgBreakPoint();\ } // Trace2(ENTER, "%%%%%%LowIndex:(%d) %0x:%d", i, g_TimerStruct.TableLowIndex); \ //------------------------------------------------------------------------------ // some global definitions //------------------------------------------------------------------------------ #ifndef IPADDR typedef DWORD IPADDR; #endif #define PROTO_IP_IGMP_PROXY 11 #define INTERSECTION 3 #define RULE5 5 //------------------------------------------------------------------------------ // interface table macros //------------------------------------------------------------------------------ #define IF_HASH_VALUE(_index) ((_index) % g_pIfTable->NumBuckets) #define ACQUIRE_IF_LOCK_EXCLUSIVE(_IfIndex, _proc) \ AcquireDynamicRWLock(&g_pIfTable->aIfBucketDRWL[IF_HASH_VALUE(_IfIndex)],\ LOCK_MODE_WRITE, \ &g_DynamicRWLStore) #define RELEASE_IF_LOCK_EXCLUSIVE(_IfIndex, _proc) \ ReleaseDynamicRWLock(&g_pIfTable->aIfBucketDRWL[IF_HASH_VALUE(_IfIndex)], \ LOCK_MODE_WRITE, \ &g_DynamicRWLStore) #define ACQUIRE_IF_LOCK_SHARED(_IfIndex, _proc) \ AcquireDynamicRWLock(&g_pIfTable->aIfBucketDRWL[IF_HASH_VALUE(_IfIndex)], \ LOCK_MODE_READ, \ &g_DynamicRWLStore) #define RELEASE_IF_LOCK_SHARED(_IfIndex, _proc) \ ReleaseDynamicRWLock(&g_pIfTable->aIfBucketDRWL[IF_HASH_VALUE(_IfIndex)], \ LOCK_MODE_READ, \ &g_DynamicRWLStore) #define ACQUIRE_IF_LIST_LOCK(_proc) \ ENTER_CRITICAL_SECTION(&g_pIfTable->IfLists_CS, "g_IfListsCS", _proc); #define RELEASE_IF_LIST_LOCK(_proc) \ LEAVE_CRITICAL_SECTION(&g_pIfTable->IfLists_CS, "g_IfListsCS", _proc); #define ACQUIRE_IF_GROUP_LIST_LOCK(_IfIndex, _proc) \ AcquireDynamicCSLock(&g_pIfTable->aIfBucketDCS[IF_HASH_VALUE(_IfIndex)],\ &g_DynamicCSStore) #define RELEASE_IF_GROUP_LIST_LOCK(_IfIndex, _proc) \ ReleaseDynamicCSLock(&g_pIfTable->aIfBucketDCS[IF_HASH_VALUE(_IfIndex)],\ &g_DynamicCSStore) //------------------------------------------------------------------------------ // Proxy table macros //------------------------------------------------------------------------------ #define PROXY_HASH_VALUE(_group) \ (( ((_group)&0xFF000000)+((_group)&0xFF)) % (PROXY_HASH_TABLE_SZ)) //------------------------------------------------------------------------------ // protocol type macros/interface type macros //------------------------------------------------------------------------------ #define IS_PROTOCOL_TYPE_PROXY(_pite) \ ((_pite)->Config.IgmpProtocolType==IGMP_PROXY \ ||(_pite)->Config.IgmpProtocolType==IGMP_PROXY_V3) #define IS_PROTOCOL_TYPE_PROXY_V2(_pite) \ ((_pite)->Config.IgmpProtocolType==IGMP_PROXY) #define IS_PROTOCOL_TYPE_PROXY_V3(_pite) \ ((_pite)->Config.IgmpProtocolType==IGMP_PROXY_V3) #define IS_PROTOCOL_TYPE_IGMPV1(_pite) \ ((_pite)->Config.IgmpProtocolType==IGMP_ROUTER_V1) #define IS_PROTOCOL_TYPE_IGMPV2(_pite) \ ((_pite)->Config.IgmpProtocolType==IGMP_ROUTER_V2) #define IS_PROTOCOL_TYPE_IGMPV3(_pite) \ ((_pite)->Config.IgmpProtocolType==IGMP_ROUTER_V3) #define IS_PROTOCOL_TYPE_ROUTER(_pite) \ (!IS_PROTOCOL_TYPE_PROXY(_pite)) #define IGMP_MIB_IF_CONFIG_SIZE_V3(pConfig) \ IgmpMibIfConfigSize(pConfig) // internally, FfType does not have protocol type, but when I expose it outside, // I have to add proxy type if it is a proxy interface. #define GET_EXTERNAL_IF_TYPE(_pite) \ IS_PROTOCOL_TYPE_PROXY(_pite) ? ((_pite->IfType)|IGMP_IF_PROXY) \ : (_pite)->IfType #define ACQUIRE_PROXY_ALERT_LOCK(proc) \ ENTER_CRITICAL_SECTION(&g_ProxyAlertCS, "g_ProxyAlertCS", proc) #define RELEASE_PROXY_ALERT_LOCK(proc) \ LEAVE_CRITICAL_SECTION(&g_ProxyAlertCS, "g_ProxyAlertCS", proc) //------------------------------------------------------------------- // ENUM MACROS //------------------------------------------------------------------- #define ACQUIRE_ENUM_LOCK_EXCLUSIVE(_proc) \ ACQUIRE_WRITE_LOCK(&g_EnumRWLock, "g_EnumRWLock", _proc); #define RELEASE_ENUM_LOCK_EXCLUSIVE(_proc) \ RELEASE_WRITE_LOCK(&g_EnumRWLock, "g_EnumRWLock", _proc); #define ACQUIRE_ENUM_LOCK_SHARED(_proc) \ ACQUIRE_READ_LOCK(&g_EnumRWLock, "g_EnumRWLock", _proc); #define RELEASE_ENUM_LOCK_SHARED(_proc) \ RELEASE_READ_LOCK(&g_EnumRWLock, "g_EnumRWLock", _proc); //------------------------------------------------------------------------------ // group table macros //------------------------------------------------------------------------------ #define GROUP_HASH_VALUE(_group) \ (((_group) & 0xFF)%GROUP_HASH_TABLE_SZ) #define ACQUIRE_GROUP_LOCK(_group, _proc) {\ ACQUIRE_ENUM_LOCK_SHARED(_proc);\ AcquireDynamicCSLockedList( \ &g_pGroupTable->HashTableByGroup[GROUP_HASH_VALUE(_group)],\ &g_DynamicCSStore);\ } #define RELEASE_GROUP_LOCK(_group, _proc) {\ ReleaseDynamicCSLockedList( \ &g_pGroupTable->HashTableByGroup[GROUP_HASH_VALUE(_group)],\ &g_DynamicCSStore);\ RELEASE_ENUM_LOCK_SHARED(_proc);\ } #define ACQUIRE_GROUP_LIST_LOCK(_proc) { \ ACQUIRE_LIST_LOCK(&g_pGroupTable->ListByGroup, \ "g_pGroupTable->ListByGroup", _proc);\ } #define RELEASE_GROUP_LIST_LOCK(_proc) { \ RELEASE_LIST_LOCK(&g_pGroupTable->ListByGroup, \ "g_pGroupTable->ListByGroup", _proc);\ } // // merge the groups list if the number of entries in the new list is more than 50 // or if the size of new list is greater than 4 times the size of actual list // but in any case not smaller than 10 // #define MERGE_GROUP_LISTS_REQUIRED() \ ( (g_pGroupTable->NumGroupsInNewList > 50) \ || ( (g_pGroupTable->NumGroupsInNewList > \ g_Info.CurrentGroupMemberships/4) \ && (g_pGroupTable->NumGroupsInNewList>10) )) // insert all elements in l2 at the end of l1, and reinitialize l2 #define CONCATENATE_LISTS(l1, l2) { \ l2.Flink->Blink = l1.Blink; \ l1.Blink->Flink = l2.Flink; \ l2.Blink->Flink = &l1; \ l1.Blink = l2.Blink; \ InitializeListHead(&l2); \ } #define MERGE_IF_GROUPS_LISTS_REQUIRED(_pite) \ (_pite->NumGIEntriesInNewList > 20) #define MERGE_PROXY_LISTS_REQUIRED(_pite) \ (_pite->NumGIEntriesInNewList > 20) //------------------------------------------------------------------------------ // SOCKETS MACROS //------------------------------------------------------------------------------ #define ACQUIRE_SOCKETS_LOCK_EXCLUSIVE(_proc) \ ACQUIRE_WRITE_LOCK(&g_SocketsRWLock, "g_SocketsRWLock", _proc); #define RELEASE_SOCKETS_LOCK_EXCLUSIVE(_proc) \ RELEASE_WRITE_LOCK(&g_SocketsRWLock, "g_SocketsRWLock", _proc); #define ACQUIRE_SOCKETS_LOCK_SHARED(_proc) \ ACQUIRE_READ_LOCK(&g_SocketsRWLock, "g_SocketsRWLock", _proc); #define RELEASE_SOCKETS_LOCK_SHARED(_proc) \ RELEASE_READ_LOCK(&g_SocketsRWLock, "g_SocketsRWLock", _proc); //------------------------------------------------------------------------------ // RAS MACROS //------------------------------------------------------------------------------ #define IS_NOT_RAS_IF(flag) ((flag) == IGMP_IF_NOT_RAS) #define IS_RAS_SERVER_IF(flag) ((flag) == IGMP_IF_RAS_SERVER) #define IS_RAS_CLIENT_IF(flag) ((flag) == IGMP_IF_RAS_CLIENT) #define IS_RAS_ROUTER_IF(flag) ((flag) == IGMP_IF_RAS_ROUTER) #define RAS_HASH_VALUE(ClientAddr) \ (((ClientAddr) & 0xFF)%(RAS_HASH_TABLE_SZ)) //------------------------------------------------------------------------------ // PACKET MACROS //------------------------------------------------------------------------------ // This macro compares two IP addresses in network order by // masking off each pair of octets and doing a subtraction; // the result of the final subtraction is stored in the third argument. // #define INET_CMP(a,b,c) \ (((c) = (((a) & 0x000000ff) - ((b) & 0x000000ff))) ? (c) : \ (((c) = (((a) & 0x0000ff00) - ((b) & 0x0000ff00))) ? (c) : \ (((c) = (((a) & 0x00ff0000) - ((b) & 0x00ff0000))) ? (c) : \ (((c) = ((((a)>>8) & 0x00ff0000) - (((b)>>8) & 0x00ff0000))))))) #define PRINT_IPADDR(x) \ ((x)&0x000000ff),(((x)&0x0000ff00)>>8),(((x)&0x00ff0000)>>16),(((x)&0xff000000)>>24) //------------------------------------------------------------------------------ // Interface #defines and Macros //------------------------------------------------------------------------------ // // status flags // #define IF_CREATED_FLAG 0x00000001 #define CREATED_FLAG 0x00000001 #define IF_BOUND_FLAG 0x00000002 #define IF_ENABLED_FLAG 0x00000004 #define IF_DELETED_FLAG 0x80000000 #define DELETED_FLAG 0x80000000 #define MGM_ENABLED_IGMPRTR_FLAG 0x00001000 #define IGMPRTR_MPROTOCOL_PRESENT_FLAG 0x00002000 // interface timers etc have not been set. socket not activated. so enumeration // might not be correct. Further, if deleting the entry, timers/sockets can // be ignored #define IF_ACTIVATED_FLAG 0x00000008 #define IF_DEACTIVATE_DELETE_FLAG 0x00000010 // // macros for status flags // #define IS_IGMPRTR_ENABLED_BY_MGM(pite) \ (pite->Status & MGM_ENABLED_IGMPRTR_FLAG) #define MGM_ENABLE_IGMPRTR(pite) \ (pite->Status |= MGM_ENABLED_IGMPRTR_FLAG) #define MGM_DISABLE_IGMPRTR(pite) {\ (pite->Status &= ~MGM_ENABLED_IGMPRTR_FLAG); \ (pite->Status &= ~IGMPRTR_MPROTOCOL_PRESENT_FLAG);\ } #define IS_MPROTOCOL_PRESENT_ON_IGMPRTR(pite) \ (pite->Status & IGMPRTR_MPROTOCOL_PRESENT_FLAG) #define SET_MPROTOCOL_PRESENT_ON_IGMPRTR(pite) \ (pite->Status |= IGMPRTR_MPROTOCOL_PRESENT_FLAG) #define SET_MPROTOCOL_ABSENT_ON_IGMPRTR(pite) \ (pite->Status &= ~IGMPRTR_MPROTOCOL_PRESENT_FLAG) #define IS_IF_BOUND(pite) \ ((pite)->Status&IF_BOUND_FLAG) #define IS_IF_ENABLED_BY_RTRMGR(pite) \ ((pite)->Status&IF_ENABLED_FLAG) #define IS_IF_ENABLED_IN_CONFIG(pite) \ (IGMP_ENABLED_FLAG_SET((pite)->Config.Flags)) #define IS_IF_ENABLED(pite) \ ( IS_IF_ENABLED_BY_RTRMGR(pite) && IS_IF_ENABLED_IN_CONFIG(pite) ) #define IS_IF_ENABLED_BOUND(pite) \ (IS_IF_ENABLED(pite)&&IS_IF_BOUND(pite)) #define IS_IF_DELETED(pite) \ ((pite)->Status&IF_DELETED_FLAG) #define IS_IF_NOT_DELETED(pite) \ (!((pite)->Status&IF_DELETED_FLAG)) #define IS_IF_ACTIVATED(pite) \ ( !((pite)->Status&IF_DELETED_FLAG) && ((pite)->Status&IF_ACTIVATED_FLAG) ) //------------------------------- // QUERIER STATES 0x<0> //------------------------------- #define QUERIER 0x10 #define IS_IF_VER2(pite) IS_PROTOCOL_TYPE_IGMPV2(pite) #define IS_IF_VER1(pite) IS_PROTOCOL_TYPE_IGMPV1(pite) #define IS_IF_VER3(pite) IS_PROTOCOL_TYPE_IGMPV3(pite) #define GET_IF_VERSION(_pite) (_pite)->Config.IgmpProtocolType #define IS_QUERIER(pite) ((pite)->Info.QuerierState & QUERIER) // // interlocked operations not required, as state is of type uchar // #define SET_QUERIER_STATE_QUERIER(state) (state |= 0x10) #define SET_QUERIER_STATE_NON_QUERIER(state) (state &= 0x01) #define IF_PROCESS_GRPQUERY(pite) \ ( (IS_IF_VER2(pite)||IS_IF_VER3(pite)) && !IS_RAS_SERVER_IF(pite->IfType) ) #define IF_PROCESS_LEAVES(pite) \ ( IS_IF_VER2(pite) && (IS_QUERIER(pite)) && !IS_RAS_SERVER_IF(pite->IfType)) #define GI_PROCESS_GRPQUERY(pite, pgie) \ ( IF_PROCESS_GRPQUERY(pite)&& ((pgie->Version==2)||(pgie->Version==3)) ) #define CAN_ADD_GROUPS_TO_MGM(pite) \ ( (IS_IGMPRTR_ENABLED_BY_MGM(pite)) \ && (IS_MPROTOCOL_PRESENT_ON_IGMPRTR(pite) || (IS_QUERIER(pite))) \ ) // // INTERFACE STATE // #define GET_EXTERNAL_IF_STATE(pite, State) {\ State = 0;\ if (IS_IF_ENABLED_BY_RTRMGR(pite)) \ State |= IGMP_STATE_ENABLED_BY_RTRMGR; \ if (IS_IF_ENABLED_IN_CONFIG(pite))\ State |= IGMP_STATE_ENABLED_IN_CONFIG; \ if (IS_PROTOCOL_TYPE_ROUTER(pite)) {\ if (IS_IGMPRTR_ENABLED_BY_MGM(pite)) \ State |= IGMP_STATE_ENABLED_BY_MGM; \ if (CAN_ADD_GROUPS_TO_MGM(pite)) \ State |= IGMP_STATE_MGM_JOINS_ENABLED; \ } \ else \ State |= IGMP_STATE_ENABLED_BY_MGM; \ \ if (IS_IF_BOUND(pite)) \ State |= IGMP_STATE_BOUND;\ } // //filter macros // #define GMI TRUE #define LMI FALSE #define STATIC 0xff #define MGM_YES TRUE #define MGM_NO FALSE //------------------------------------------------------------------------------ // other locking macros //------------------------------------------------------------------------------ #define ACQUIRE_GLOBAL_LOCK(proc) ENTER_CRITICAL_SECTION(&g_CS, "g_CS", proc) #define RELEASE_GLOBAL_LOCK(proc) LEAVE_CRITICAL_SECTION(&g_CS, "g_CS", proc) // // instead of using goto:end to go to the end of the block, use the following // #define BEGIN_BREAKOUT_BLOCK1 do #define GOTO_END_BLOCK1 goto END_BREAKOUT_BLOCK_1 #define END_BREAKOUT_BLOCK1 while(FALSE); END_BREAKOUT_BLOCK_1: #define BEGIN_BREAKOUT_BLOCK2 do #define GOTO_END_BLOCK2 goto END_BREAKOUT_BLOCK_2 #define END_BREAKOUT_BLOCK2 while(FALSE); END_BREAKOUT_BLOCK_2: //------------------------------------------------------------------------------ // memory allocation/deallocation macros //------------------------------------------------------------------------------ #if DEBUG_FLAGS_MEM_ALLOC typedef struct _MEM_HDR { LIST_ENTRY Link; ULONG Signature; ULONG Id; ULONG IfIndex; PDWORD Tail; } MEM_HDR, *PMEM_HDR; PVOID IgmpDebugAlloc( DWORD sz, DWORD Flags, DWORD Id, DWORD IfIndex ); VOID IgmpDebugFree( PVOID mem ); VOID DebugScanMemory( ); VOID DebugScanMemoryInterface( DWORD IfIndex ); #define IGMP_ALLOC(sz,Id,If) IgmpDebugAlloc((sz),0,Id,If) #define IGMP_ALLOC_AND_ZERO(sz,Id,If) IgmpDebugAlloc((sz),HEAP_ZERO_MEMORY,Id,If) #define IGMP_FREE(p) {\ IgmpDebugFree(p);\ } #define IGMP_FREE_NOT_NULL(p) if (p) IGMP_FREE(p) #else #define IGMP_ALLOC(sz,Id,If) HeapAlloc(g_Heap,0,(sz)) #define IGMP_ALLOC_AND_ZERO(sz,Id,If) HeapAlloc(g_Heap,HEAP_ZERO_MEMORY,(sz)) //deldel //#define IGMP_FREE(p) HeapFree(g_Heap, 0, (p)) //#define IGMP_FREE_NOT_NULL(p) ((p) ? IGMP_FREE(p) : TRUE) #define IGMP_FREE(p) {\ HeapFree(g_Heap, 0, (p));\ } // Trace1(ENTER1, "Freed heap:%0x", PtrToUlong(p));\ #define IGMP_FREE_NOT_NULL(p) if (p)IGMP_FREE(p) #define IgmpDebugAlloc(sz,Flags,Id,IfIndex) #define IgmpDebugFree(mem) #define DebugScanMemoryInterface(IfIndex) #define DebugScanMemory() #endif #define PROCESS_ALLOC_FAILURE2(ptr, TraceMsg, Error,arg2, GotoStmt) \ if (ptr==NULL) {\ Error = ERROR_NOT_ENOUGH_MEMORY;\ Trace2(ERR, TraceMsg, Error, arg2); \ GotoStmt;\ } #define PROCESS_ALLOC_FAILURE3(ptr, TraceMsg, Error,arg2,arg3, GotoStmt) \ if (ptr==NULL) {\ Error = ERROR_NOT_ENOUGH_MEMORY;\ Trace3(ERR, TraceMsg, Error, arg2, arg3); \ GotoStmt;\ } // // assert macros // #if DBG #define IgmpAssert(exp){ \ if(!(exp)) \ { \ TracePrintf(TRACEID, \ "Assertion failed in %s : %d \n",__FILE__,__LINE__);\ RouterAssert(#exp,__FILE__,__LINE__,NULL); \ } \ } #if DEBUG_FLAGS_ASSERT_ON_ERRORS #define IgmpAssertOnError(exp) IgmpAssert(exp) #define IgmpDbgBreakPoint() DbgBreakPoint() #else #define IgmpAssertOnError(exp) ; #define IgmpDbgBreakPoint() ; #endif // if not DBG #else #define IgmpAssert(exp) ; #define IgmpAssertOnError(exp) ; #define IgmpDbgBreakPoint() /*deldel*/ #endif #define INSERT_IN_SORTED_LIST(_pInsertList, _pEntry, _Field, _STRUCT, _Link) {\ \ _STRUCT *pTmp;\ PLIST_ENTRY pHead, ple;\ \ pHead = _pInsertList;\ for (ple=pHead->Flink; ple!=pHead; ple=ple->Flink) {\ \ pTmp = CONTAINING_RECORD(ple, _STRUCT, _Link);\ if (pTmp->_Field > _pEntry->_Field)\ break;\ }\ \ InsertTailList(ple, &_pEntry->_Link);\ } #define SEARCH_IN_SORTED_LIST(_pList,_Value,_Field,_STRUCT,_Link,_pEntry) {\ PLIST_ENTRY ple;\ _pEntry = NULL;\ \ for (ple=(_pList)->Flink; ple!=_pList; ple=ple->Flink) {\ _pEntry = CONTAINING_RECORD(ple, _STRUCT, _Link);\ if ((_Value >= _pEntry)->_Field) {\ if ((_pEntry)->_Field != _Value) \ _pEntry = NULL;\ break;\ }\ }\ } // // NETWORK_TO_LITTLE_ENDIAN macro // #define NETWORK_TO_LITTLE_ENDIAN(Group) ( (((Group)&0x000000ff)<<24) \ +(((Group)&0x0000ff00)<<8) \ +(((Group)&0x00ff0000)>>8) \ +(((Group)&0xff000000)>>24) ) #define MIN(a,b) ((a)<(b) ? (a) : (b)) #define MAX(a,b) ((a)>(b) ? (a) : (b)) #define IS_NOT_EQ_ANY2(a, A,B) ((a!=A)&&(a!=B)) #define IS_EQ_ANY(a,A,B) ((a==A)||(a==B)) // // signature macros for Interface-Group lists enumeration // #define GET_NEXT_SIGNATURE() (g_GlobalIfGroupEnumSignature++ | 0x10 ) //#define SET_SIGNATURE(a,b) ((a) = ((b)<<16) | (a&0x00FF)) #define SET_SIGNATURE(a,b) (a = (b)) // // define enum values // #define ADD_FLAG 1 #define DELETE_FLAG 0 #define NON_QUERIER_FLAG 1 #define QUERIER_FLAG 2 #define QUERIER_CHANGE_V1_ONLY 4 #define STATIC_GROUP 1 #define NOT_STATIC_GROUP 0 #define ANY_GROUP_TYPE 2 #define NOT_RAS_CLIENT 0 #define RAS_CLIENT 1 #endif