📄 ipproto.c
字号:
}/********************************************************************************* ipTkTxRestart - restart routine registered with a toolkit driver. ** NOMANUAL*/LOCAL int ipTkTxRestart ( void * ipCallbackId /* Sent down in muxTkBind call. */ ) { IP_DRV_CTRL * pDrvCtrl = (IP_DRV_CTRL *)ipCallbackId; if (pDrvCtrl == NULL) return (ERROR); ipTxStartup (pDrvCtrl); return (OK); }/********************************************************************************* ipTxStartup - start output on the lower layer** Looks for any action on the queue, and begins output if there is anything* there. This routine is called from several possible threads. Each will be* described below.** The first, and most common thread, is when a user task requests the* transmission of data. This will cause muxSend() to be called, which will* cause ether_output() to be called, which will cause this routine to be* called (usually). This routine will not be called if ether_output() finds* that our interface output queue is full. In this case, the outgoing data* will be thrown out.** The second, and most obscure thread, is when the reception of certain* packets causes an immediate (attempted) response. For example, ICMP echo* packets (ping), and ICMP "no listener on that port" notifications. All* functions in this driver that handle the reception side are executed in the* context of netTask(). Always. So, in the case being discussed, netTask() * will receive these certain packets, cause IP to be stimulated, and cause the* generation of a response to be sent. We then find ourselves following the* thread explained in the second example, with the important distinction that* the context is that of netTask().** This routine is also called from ipTxRestart() and ipTkTxRestart().** NOMANUAL*/void ipTxStartup ( IP_DRV_CTRL * pDrvCtrl /* pointer to the drv control */ ) { M_BLK_ID pMblk; STATUS status = OK; struct ifnet * pIf; BOOL nptFlag; USHORT netType = 0; char dstAddrBuf [MAX_ADDRLEN]; M_BLK_ID pNetPkt = NULL; int s; if (pDrvCtrl == NULL) return; if (!pDrvCtrl->attached) {#ifdef IP_DEBUG if (ipDebug) logMsg ("ipTxStartup not attached!\n", 0, 0, 0, 0, 0, 0);#endif /* IP_DEBUG */ return; } s = splnet(); nptFlag = pDrvCtrl->nptFlag; pIf = (struct ifnet *)&pDrvCtrl->idr; /* * Loop until there are no more packets ready to send or we * have insufficient resources left to send another one. */ while (pIf->if_snd.ifq_head) { /* Dequeue a packet. */ IF_DEQUEUE (&pIf->if_snd, pMblk); #ifdef ETHER_OUTPUT_HOOKS if ((etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&pDrvCtrl->idr, (struct ether_header *)pMblk->m_data,pMblk->m_len)) { continue; }#endif /* ETHER_OUTPUT_HOOKS */ if (nptFlag) { /* * For NPT devices, the output processing adds the network packet * type (and the link-level destination address, if any) to the * start of the packet. Retrieve that information and pass it to * the NPT transmit routine. */ netType = pMblk->mBlkHdr.reserved; bzero (dstAddrBuf, MAX_ADDRLEN); pNetPkt = pMblk; if (pIf->if_addrlen) { /* Save the dest. address to protect it from driver changes. */ bcopy (pMblk->mBlkHdr.mData, dstAddrBuf, pIf->if_addrlen); /* Restore original network packet data pointers and length. */ m_adj (pMblk, pIf->if_addrlen); if (pMblk->mBlkHdr.mLen == 0) { /* * The destination address used a new mBlk in the chain. * Access the next entry containing the network packet * and restore the header flag setting. */ pNetPkt = pMblk->mBlkHdr.mNext; if (pMblk->mBlkHdr.mFlags & M_PKTHDR) { pNetPkt->mBlkHdr.mFlags |= M_PKTHDR; } } } /* Attempt to send the packet. */ status = muxTkSend (pDrvCtrl->pIpCookie, pNetPkt, dstAddrBuf, netType, NULL); } else { /* * For END devices, the transmit queue contains a complete * link-level frame. Attempt to send that data. */ status = muxSend (pDrvCtrl->pIpCookie, pMblk); } if (status == END_ERR_BLOCK) { /* * The device is currently unable to transmit. Return the * packet or frame to the queue to retry later. */#ifdef IP_DEBUG if (ipDebug) logMsg ("Transmit error!\n", 0, 0, 0, 0, 0, 0);#endif /* IP_DEBUG */ if (nptFlag && pIf->if_addrlen) { /* * For NPT devices, restore the link-level destination * address, in case the driver processing altered it. */ if (pMblk == pNetPkt) { /* * The destination address used the initial mBlk in the * chain. Change the data pointer to provide copy space. */ pMblk->mBlkHdr.mData -= pIf->if_addrlen; } bcopy (dstAddrBuf, pMblk->mBlkHdr.mData, pIf->if_addrlen); pMblk->mBlkHdr.mLen += pIf->if_addrlen; if (pMblk->mBlkHdr.mFlags & M_PKTHDR) pMblk->mBlkPktHdr.len += pIf->if_addrlen; } /* If we are transmitting make a new copy and PREPEND it. */ if (IF_QFULL(&pDrvCtrl->idr.ac_if.if_snd)) { IF_DROP(&pDrvCtrl->idr.ac_if.if_snd); netMblkClChainFree (pMblk); ++pDrvCtrl->idr.ac_if.if_oerrors; } else IF_PREPEND (&pDrvCtrl->idr.ac_if.if_snd, pMblk); break; } else /* Successful handoff to driver for transmission. */ { ++pDrvCtrl->idr.ac_if.if_opackets; /* For NPT devices, free any Mblk prepended for the link-level * destination address. */ if (nptFlag && (pMblk != pNetPkt)) { netMblkClFree(pMblk); } } #ifdef IP_DEBUG if (ipDebug) logMsg("ipTxStartup done!\n", 0, 0, 0, 0, 0, 0);#endif /* IP_DEBUG */ } splx(s); }/********************************************************************************* ipDetach - a generic detach routine for the TCP/IP network stack** This routine removes the TCP/IP stack from the MUX. If completed* successfully, the IP protocol will no longer receive packets* from the named END driver. ** RETURNS: OK or ERROR*/STATUS ipDetach ( int unit, /* Unit number */ char *pDevice /* Device name (i.e. ln, ei etc.). */ ) { END_OBJ * pEnd; IP_DRV_CTRL* pDrvCtrl = NULL; int error; /* return error status */ int count;#ifndef VIRTUAL_STACK IMPORT int ipMaxUnits;#endif int limit = ipMaxUnits; char ifName[IFNAMSIZ]; /* if name, e.g. "en0" */ /* Check if device is valid. */ pEnd = endFindByName (pDevice, unit); if (pEnd == NULL) return (ERROR); for (count = 0; count < limit; count++) { pDrvCtrl = &ipDrvCtrl [count]; if (pDrvCtrl->attached && PCOOKIE_TO_ENDOBJ (pDrvCtrl->pIpCookie) == pEnd) break; } if (count == limit) { /* Device not attached. */ return (ERROR); } /* Now bring down the interface */ sprintf (ifName,"%s%d",pDevice, unit); ifFlagChange(ifName, IFF_UP, 0); /* Now remove the interface route */ ifRouteDelete(pDevice, unit); if (pDrvCtrl->nptFlag) /* npt device, call npt routines */ { error = ipTkShutdownRtn (pDrvCtrl); if (pDrvCtrl->pArpCookie) error |= arpTkShutdownRtn (pDrvCtrl); } else { error = ipShutdownRtn (pDrvCtrl->pIpCookie, pDrvCtrl); if (pDrvCtrl->pArpCookie) error |= arpShutdownRtn (pDrvCtrl->pArpCookie, pDrvCtrl); } return (error); }/********************************************************************************* ipIoctl - the IP I/O control routine** Process an ioctl request.** NOMANUAL*/LOCAL int ipIoctl ( IDR *ifp, int cmd, caddr_t data ) { int error = OK; struct ifreq *ifr; IP_DRV_CTRL* pDrvCtrl; register struct in_ifaddr* pIa = 0; M2_INTERFACETBL mib2Tbl; struct sockaddr* inetaddr; char mapMCastBuff[128]; long flagsMask; register M2_NETDRVCNFG *pm2DrvCnfg = (M2_NETDRVCNFG *)data; register M2_NETDRVCNTRS *pm2DrvCntr = (M2_NETDRVCNTRS *)data; u_long dt_saddr = ((struct in_ifaddr *)data)->ia_addr.sin_addr.s_addr; struct mBlk* pMblk; pDrvCtrl = (IP_DRV_CTRL *)(ifp->ac_if.pCookie); if (pDrvCtrl->pIpCookie == NULL) return (EINVAL); switch ((u_int) cmd) { case SIOCSIFADDR:#ifdef VIRTUAL_STACK for (pIa = _in_ifaddr; pIa; pIa = pIa->ia_next)#else for (pIa = in_ifaddr; pIa; pIa = pIa->ia_next)#endif /* VIRTUAL_STACK */ if ((pIa->ia_ifp == (struct ifnet *)ifp) && (pIa->ia_addr.sin_addr.s_addr == dt_saddr)) break; /* * For devices with 802.x addressing, setup ARP processing * for the IP address. */ switch (ifp->ac_if.if_type) { case M2_ifType_ethernet_csmacd: case M2_ifType_iso88023_csmacd: case M2_ifType_iso88024_tokenBus: case M2_ifType_iso88025_tokenRing: case M2_ifType_iso88026_man: case M2_ifType_fddi:#ifdef ROUTER_STACK /* UNNUMBERED_SUPPORT */ if (pIa->ia_ifp->if_flags & IFF_UNNUMBERED) { pIa->ia_ifa.ifa_rtrequest = NULL; pIa->ia_ifa.ifa_flags &= ~RTF_CLONING; ifp->ac_ipaddr = IA_SIN (data)->sin_addr; break; }#endif /* ROUTER_STACK */ pIa->ia_ifa.ifa_rtrequest = arp_rtrequest; pIa->ia_ifa.ifa_flags |= RTF_CLONING; ifp->ac_ipaddr = IA_SIN (data)->sin_addr; /* Generate gratuitous ARP requests only for ethernet devices. */ arpwhohas ((struct arpcom*) ifp, &IA_SIN (data)->sin_addr); break; default: break; } break; case SIOCGMIB2CNFG: error = muxIoctl (pDrvCtrl->pIpCookie, EIOCGMIB2, (caddr_t)&mib2Tbl); if (error != OK) return (EINVAL); pm2DrvCnfg->ifType = mib2Tbl.ifType; /* ppp type */ if (mib2Tbl.ifSpecific.idLength) { pm2DrvCnfg->ifSpecific.idLength = mib2Tbl.ifSpecific.idLength; memcpy (&pm2DrvCnfg->ifSpecific.idArray[0], &mib2Tbl.ifSpecific.idArray[0], mib2Tbl.ifSpecific.idLength * sizeof (long)); } else pm2DrvCnfg->ifSpecific.idLength = 0; break; case SIOCGMIB2CNTRS: /* fill in counters */ error = muxIoctl (pDrvCtrl->pIpCookie, EIOCGMIB2, (caddr_t)&mib2Tbl); if (error != OK) return (EINVAL); pm2DrvCntr->ifSpeed = mib2Tbl.ifSpeed;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -