📄 in.c
字号:
logMsg("Didn't unlink inifadr from list\n", 0,0,0,0,0,0); } IFAFREE((&oia->ia_ifa)); break; default: if (ifp == 0 || ifp->if_ioctl == 0) return (EOPNOTSUPP); return ((*ifp->if_ioctl)(ifp, cmd, data)); } return (0);}/* * Delete any existing route for an interface. */voidin_ifscrub(ifp, ia) register struct ifnet *ifp; register struct in_ifaddr *ia;{ if ((ia->ia_flags & IFA_ROUTE) == 0) return; if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT)) rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST); else rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0); ia->ia_flags &= ~IFA_ROUTE;}/* * Initialize an interface's internet address * and routing table entry. */intin_ifinit(ifp, ia, sin, scrub) register struct ifnet *ifp; register struct in_ifaddr *ia; struct sockaddr_in *sin; int scrub;{ register u_long i = ntohl(sin->sin_addr.s_addr); struct sockaddr_in oldaddr; int s = splimp(), flags = RTF_UP, error, ether_output(); oldaddr = ia->ia_addr; ia->ia_addr = *sin; /* * Give the interface a chance to initialize * if this is its first address, * and to validate the address if necessary. */ if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia))) { splx(s); ia->ia_addr = oldaddr; return (error); } if (ifp->if_output == ether_output) { /* XXX: Another Kludge */ ia->ia_ifa.ifa_rtrequest = arp_rtrequest; ia->ia_ifa.ifa_flags |= RTF_CLONING; } splx(s); if (scrub) { ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr; in_ifscrub(ifp, ia); ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr; } if (IN_CLASSA(i)) ia->ia_netmask = IN_CLASSA_NET; else if (IN_CLASSB(i)) ia->ia_netmask = IN_CLASSB_NET; else ia->ia_netmask = IN_CLASSC_NET; /* * The subnet mask usually includes at least the standard network part, * but may may be smaller in the case of supernetting. * If it is set, we believe it. */ if (ia->ia_subnetmask == 0) { ia->ia_subnetmask = ia->ia_netmask; ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask); } else ia->ia_netmask &= ia->ia_subnetmask; ia->ia_net = i & ia->ia_netmask; ia->ia_subnet = i & ia->ia_subnetmask; in_socktrim(&ia->ia_sockmask); /* * Add route for the network. */ ia->ia_ifa.ifa_metric = ifp->if_metric; if (ifp->if_flags & IFF_BROADCAST) { ia->ia_broadaddr.sin_addr.s_addr = htonl(ia->ia_subnet | ~ia->ia_subnetmask); ia->ia_netbroadcast.s_addr = htonl(ia->ia_net | ~ ia->ia_netmask); } else if (ifp->if_flags & IFF_LOOPBACK) { ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr; flags |= RTF_HOST; } else if (ifp->if_flags & IFF_POINTOPOINT) { if (ia->ia_dstaddr.sin_family != AF_INET) return (0); flags |= RTF_HOST; } if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0) ia->ia_flags |= IFA_ROUTE; /* * If the interface supports multicast, join the "all hosts" * multicast group on that interface. */ if ( ifp->if_flags & IFF_MULTICAST ) { struct in_addr addr; addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); in_addmulti (&addr, ifp, NULL); ifp->pInmMblk = NULL; } return (error);}/********************************************************************************* in_ifaddr_remove - remove an interface from the in_ifaddr list** This function removes the internet interface address given as an input* parameter, from the global linked-list of internet interface addresses* pointed by in_ifaddr. This function is called before dettaching an interface* This function also removes all the internet multicast addresses hooked to * the in_ifaddr. It calls in_delmulti() which in turn calls the ioctl for the* driver to remove the ethernet multicast addresses.* * NOMANUAL* * RETURNS: N/A*/ void in_ifaddr_remove ( struct ifaddr * pIfAddr /* pointer to interface address */ ) { struct in_ifaddr ** pPtrInIfAddr; /* pointer to pointer to in_ifaddr */ struct in_ifaddr * pInIfAddr; /* pointer to in_ifaddr */ pPtrInIfAddr = &in_ifaddr; /* global variable */ 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; int s = splnet(); /* * See if address already in list. */ IN_LOOKUP_MULTI(*ap, ifp, inm); if (inm != NULL) {#if 0 /* * Found it; duplicate the mBlk, increment reference count. */ if ((pInmMblk = mBlkGet (_pNetSysPool, M_DONTWAIT, MT_IPMADDR)) == NULL) goto inAddMultiError; netMblkDup (DATA_TO_MBLK (inm), pInmMblk);#endif ++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) goto inAddMultiError; pInmMblk = DATA_TO_MBLK (inm); 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) 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 ifreq ifr; int s = splnet(); 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); } /* 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; for (ia = in_ifaddr; ia; ia = ia->ia_next) 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 + -