📄 in.c
字号:
#ifdef VIRTUAL_STACK pPtrInIfAddr = &_in_ifaddr; /* global variable */#else pPtrInIfAddr = &in_ifaddr; /* global variable */#endif /* VIRTUAL_STACK */ while (*pPtrInIfAddr != NULL) { if (*pPtrInIfAddr == (struct in_ifaddr *)pIfAddr) { pInIfAddr = *pPtrInIfAddr; *pPtrInIfAddr = (*pPtrInIfAddr)->ia_next; /* delete from list */ IFAFREE (&pInIfAddr->ia_ifa); /* free address */ break; } pPtrInIfAddr = &(*pPtrInIfAddr)->ia_next; } } /* * Return 1 if the address might be a local broadcast address. */intin_broadcast(in, ifp) struct in_addr in; struct ifnet *ifp;{ register struct ifaddr *ifa; u_long t; if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY) return 1; if ((ifp->if_flags & IFF_BROADCAST) == 0) return 0; t = ntohl(in.s_addr); /* * Look through the list of addresses for a match * with a broadcast address. */#define ia ((struct in_ifaddr *)ifa) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if (ifa->ifa_addr->sa_family == AF_INET && (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr || in.s_addr == ia->ia_netbroadcast.s_addr || /* * Check for old-style (host 0) broadcast. */ t == ia->ia_subnet || t == ia->ia_net)) return 1; return (0);#undef ia}/* * Add an address to the list of IP multicast addresses for a given interface. */struct mBlk *in_addmulti(ap, ifp, pInPcb) register struct in_addr *ap; register struct ifnet *ifp; register struct inpcb * pInPcb;{ register struct in_multi *inm; struct ifreq ifr; struct mBlk * pInPcbMblk = NULL; struct mBlk * pInmMblk = NULL; struct mBlk * pInmFirstMblk = NULL; int s = splnet();#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_VERBOSE, 58, 11, WV_NETEVENT_INADDMULT_START, ifp, ap->s_addr)#endif /* INCLUDE_WVNET */#endif /* * See if address already in list. */ IN_LOOKUP_MULTI(*ap, ifp, inm); if (inm != NULL) { /* * Found it; duplicate the mBlk, increment reference count. */ if ((pInmMblk = mBlkGet (_pNetSysPool, M_DONTWAIT, MT_IPMADDR)) == NULL) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 12, 3, WV_NETEVENT_INADDMULT_NOBUFS, ifp, ap->s_addr)#endif /* INCLUDE_WVNET */#endif goto inAddMultiError; } /* * XXX - The in_multi structures are stored in Mblk chains * instead of arrays like in BSD. Therefore when a second * socket joins a multicast group, the Mblk for the in_multi * structure is duplicated for this new member. The Mblk * address for the in_multi is obtained by using a pointer * to the start of the Mblk. This pointer is located just * before the structure and is retrieved using DATA_TO_MBLK. * This poses a problem when there is more than one Mblk * accessing the in_multi structure (like in this case) since * Mblk information for the second Mblk is lost. To fix this * (SPR #67536), we use the mNextPkt field of the first Mblk * to store the Mblk address for the second Mblk. When the * first Mblk is deleted (leaving group), the address of * second Mblk can be still be retrieved through the pointer. * Though this is not the best way to fix this problem, we * leave it this way since the entire design needs to be * rethought (using the Mblk back-ptr is not a good idea). */ pInmFirstMblk = DATA_TO_MBLK (inm); netMblkDup (pInmFirstMblk, pInmMblk); pInmFirstMblk->mBlkHdr.mNextPkt = pInmMblk; pInmMblk->mBlkHdr.mNextPkt = NULL; ++inm->inm_refcount; } else { /* * New address; allocate a new multicast record * and link it into the interface's multicast list. */ MALLOC(inm, struct in_multi *, sizeof(*inm), MT_IPMADDR, M_DONTWAIT); if (inm == NULL) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 12, 3, WV_NETEVENT_INADDMULT_NOBUFS, ifp, ap->s_addr)#endif /* INCLUDE_WVNET */#endif goto inAddMultiError; } pInmMblk = DATA_TO_MBLK (inm); pInmMblk->mBlkHdr.mNextPkt = NULL; bzero ((char *)inm, sizeof (*inm)); /* zero the structure */ inm->inm_addr = *ap; inm->inm_ifp = ifp; inm->inm_refcount = 1; /* insert the multicast address into the hash table */ if (mcastHashTblInsert (inm) != OK) goto inAddMultiError; /* * Ask the network driver to update its multicast reception * filter appropriately for the new address. */ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET; ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = *ap; if ((ifp->if_ioctl == NULL) || (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(caddr_t)&ifr) != 0) { mcastHashTblDelete (inm); goto inAddMultiError; } /* * Let IGMP know that we have joined a new IP multicast group. */ if (_igmpJoinGrpHook != NULL) (*_igmpJoinGrpHook) (inm); } /* * insert the protocol control block into inm pcb list * this is done to get to the list of pcbs which have joined a * multicast group. When the hash table is looked up the inm * returned should have a list of pcbs which the datagram * should be delivered to. refer udp_usrreq.c where the pcb * list is used. */ if (pInPcb != NULL) { if ((pInPcbMblk = mBlkGet (_pNetSysPool, M_DONTWAIT, MT_PCB)) == NULL) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 12, 3, WV_NETEVENT_INADDMULT_NOBUFS, ifp, ap->s_addr)#endif /* INCLUDE_WVNET */#endif goto inAddMultiError; } netMblkDup (DATA_TO_MBLK (pInPcb), pInPcbMblk); pInPcbMblk->mBlkHdr.mNext = inm->pInPcbMblk; inm->pInPcbMblk = pInPcbMblk; } splx(s); return (pInmMblk); /* return the mBlk pointing to the inm */inAddMultiError: splx (s); if (pInmMblk) m_free (pInmMblk); return (NULL);}/* * Delete a multicast address record. * deletes all pcbs if pInPcb is NULL. */intin_delmulti(pInmMblk, pInPcb) register struct mBlk * pInmMblk; register struct inpcb * pInPcb;{ register struct in_multi *inm; M_BLK_ID * ppMblk; M_BLK_ID pInPcbMblk; struct mBlk ** ppInmMblk; struct ifreq ifr; int s = splnet();#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 22, 12, WV_NETEVENT_INDELMULT_START)#endif /* INCLUDE_WVNET */#endif inm = mtod (pInmMblk, struct in_multi *); /* delete the pcb from the list */ ppMblk = &inm->pInPcbMblk; if (pInPcb != NULL) { while ((pInPcbMblk = *ppMblk)) { if (pInPcb == mtod (pInPcbMblk, struct inpcb *)) { *ppMblk = (*ppMblk)->mBlkHdr.mNext; m_free (pInPcbMblk); break; /* jump out of the while loop */ } ppMblk = &(*ppMblk)->mBlkHdr.mNext; } } else if (inm->pInPcbMblk != NULL) m_freem (inm->pInPcbMblk); /* free up all pcbs */ if (--inm->inm_refcount == 0) { /* * No remaining claims to this record; let IGMP know that * we are leaving the multicast group. */ if (_igmpLeaveGrpHook != NULL) (*_igmpLeaveGrpHook) (inm); /* * Notify the network driver to update its multicast reception * filter. */ ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_family = AF_INET; ((struct sockaddr_in *)&(ifr.ifr_addr))->sin_addr = inm->inm_addr; (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI, (caddr_t)&ifr); /* time to delete entry from hash table */ mcastHashTblDelete (inm); } /* * If there is another socket listening to this group, replace * inm's back-ptr to its Mblk (currently that of socket leaving * the group) with the pointer to the Mblk of the other socket */ if ((inm != NULL) && (pInmMblk->mBlkHdr.mNextPkt != NULL)) { ppInmMblk = (struct mbuf **)((char *)inm - sizeof (struct mbuf **)); *ppInmMblk = pInmMblk->mBlkHdr.mNextPkt; (*ppInmMblk)->mBlkHdr.mNextPkt = NULL; } /* free the mblk & inm, actual free only clRefCnt is 1 */ m_free (pInmMblk); splx(s); return (OK);}/* * Return address info for specified internet network. */struct in_ifaddr *in_iaonnetof(net) u_long net;{ register struct in_ifaddr *ia;#ifdef VIRTUAL_STACK for (ia = _in_ifaddr; ia; ia = ia->ia_next)#else for (ia = in_ifaddr; ia; ia = ia->ia_next)#endif /* VIRTUAL_STACK */ if (ia->ia_subnet == net) return (ia); return ((struct in_ifaddr *)0);}/* multicast hashing functions */void mcastHashInit () { /* initialize the mcast hash table */ mCastHashInfo.hashBase = hashinit (mCastHashTblSize, MT_IPMADDR, &mCastHashInfo.hashMask); }STATUS mcastHashTblInsert ( struct in_multi * pInMulti ) { IN_MULTI_HEAD * inMultiHead; int s; s = splnet(); inMultiHead = &mCastHashInfo.hashBase[MCAST_HASH(pInMulti->inm_addr.s_addr, pInMulti->inm_ifp, mCastHashInfo.hashMask)]; /* insert a multicast address structure into the hash table */ LIST_INSERT_HEAD(inMultiHead, pInMulti, inm_hash); splx(s); return (OK); }STATUS mcastHashTblDelete ( struct in_multi * pInMulti ) { int s; s = splnet(); LIST_REMOVE(pInMulti, inm_hash); splx(s); return (OK); }struct in_multi * mcastHashTblLookup ( int mcastAddr, /* multicast Address always in NBO */ struct ifnet * pIf /* interface pointer */ ) { IN_MULTI_HEAD * inMultiHead; IN_MULTI * pInMulti; int s; s = splnet(); /* search a hash table for the appropriate multicast address tied to a particular network interface */ inMultiHead = &mCastHashInfo.hashBase[MCAST_HASH(mcastAddr, pIf, mCastHashInfo.hashMask)]; for (pInMulti = inMultiHead->lh_first; pInMulti != NULL; pInMulti = pInMulti->inm_hash.le_next) { if (pInMulti->inm_addr.s_addr == mcastAddr && pInMulti->inm_ifp == pIf) goto found; } splx(s); return (NULL); found: /* * Move IN_MULTI to head of this hash chain so that it can be * found more quickly in the future. * XXX - this is a pessimization on machines with few * concurrent connections. */ if (pInMulti != inMultiHead->lh_first) { LIST_REMOVE(pInMulti, inm_hash); LIST_INSERT_HEAD(inMultiHead, pInMulti, inm_hash); } splx(s); return (pInMulti); }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -