📄 ipproto.c
字号:
* ipError - a routine to deal with device errors** This routines is called by the lower layer when a device error occurs.** RETURNS: N/A** NOMANUAL*/void ipError ( END_OBJ* pEnd, END_ERR* pError, IP_DRV_CTRL* pDrvCtrl ) { if (ipDebug) { switch (pError->errCode) { case END_ERR_INFO: if (pError->pMesg != NULL) logMsg ("INFO: Device: %s Unit: %d Msg: %s\n", (int)pEnd->devObject.name, pEnd->devObject.unit, (int)pError->pMesg, 4, 5, 6); break; case END_ERR_WARN: if (pError->pMesg != NULL) logMsg ("WARN: Device: %s Unit: %d Msg: %s\n", (int)pEnd->devObject.name, pEnd->devObject.unit, (int)pError->pMesg, 4, 5, 6); break; case END_ERR_RESET: if (pError->pMesg != NULL) logMsg ("RESET: Device: %s Unit: %d Msg: %s\n", (int)pEnd->devObject.name, pEnd->devObject.unit, (int)pError->pMesg, 4, 5, 6); pDrvCtrl->idr.ac_if.if_lastchange = tickGet(); break; case END_ERR_UP: if (pError->pMesg != NULL) logMsg ("UP: Device: %s Unit: %d Msg: %s\n", (int)pEnd->devObject.name, pEnd->devObject.unit, (int)pError->pMesg, 4, 5, 6); break; case END_ERR_DOWN: if (pError->pMesg != NULL) logMsg ("DOWN: Device: %s Unit: %d Msg: %s\n", (int)pEnd->devObject.name, pEnd->devObject.unit, (int)pError->pMesg, 4, 5, 6); pDrvCtrl->idr.ac_if.if_lastchange = tickGet(); ((IFNET *)&pDrvCtrl->idr)->if_flags &= ~(IFF_UP| IFF_RUNNING); break; default: } } }/******************************************************************************** ipAttach - a generic attach routine for the TCP/IP network stack** This routine takes the unit number and device name of an END driver* (e.g., "ln0", "ei0", etc.) and attaches the TCP/IP stack to the MUX. * If completed successfully, the IP protocol will begin receiving packets* from that driver.** RETURNS: OK or ERROR*/int ipAttach ( int unit, /* Unit number */ char *pDevice /* Device name (i.e. ln, ei etc.). */ ) { int flags; M2_INTERFACETBL mib2Tbl; IP_DRV_CTRL* pDrvCtrl; IMPORT int ipMaxUnits; struct ifnet* pIfp = NULL; char *pName; END_OBJ* pEnd; struct ifaddr *pIfa; struct sockaddr_dl *pSdl; int ifHdrLen; struct ifreq ifr; int count; int limit = ipMaxUnits; int freeslot = -1; pEnd = endFindByName (pDevice, unit); if (pEnd == NULL) { logMsg ("Can't attach unknown device %s (unit %d).\n", pDevice, unit, 0, 0, 0, 0); return (ERROR); } for (count = 0; count < limit; count++) { pDrvCtrl = &ipDrvCtrl [count]; if (pDrvCtrl->attached) { if (pDrvCtrl->pIpCookie == pEnd) /* Already attached? */ return (OK); } else if (freeslot == -1) freeslot = count; } if (freeslot == -1) { /* Too many attach attempts. */ logMsg ("Protocol is out of space. Increase IP_MAX_UNITS.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } pDrvCtrl = &ipDrvCtrl [freeslot]; bzero ( (char *)pDrvCtrl, sizeof (IP_DRV_CTRL)); if ((pDrvCtrl->pIpCookie = muxBind(pDevice, unit, (FUNCPTR) ipReceiveRtn, (FUNCPTR) ipShutdownRtn, (FUNCPTR) ipTxRestart, (VOIDFUNCPTR) ipError, 0x800, "IP 4.4 TCP/IP", (void *) pDrvCtrl)) == NULL) { logMsg("TCP/IP could not bind to the MUX! %s", (int)pDevice, 2, 3, 4, 5, 6); return (ERROR); } if ((pDrvCtrl->pArpCookie = muxBind(pDevice, unit, (FUNCPTR) ipReceiveRtn, (FUNCPTR) arpShutdownRtn, (FUNCPTR) ipTxRestart, NULL, 0x806, "IP 4.4 ARP", pDrvCtrl)) == NULL) { logMsg("ARP could not bind to the MUX! %s", (int)pDevice, 2, 3, 4, 5, 6); return (ERROR); } pEnd = (END_OBJ*)pDrvCtrl->pIpCookie; if ((pDrvCtrl->pSrc = netMblkGet (pEnd->pNetPool, M_DONTWAIT, MT_DATA)) == NULL) return (ERROR); if ((pDrvCtrl->pDst = netMblkGet (pEnd->pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netMblkFree (pEnd->pNetPool, pDrvCtrl->pSrc); return (ERROR); } pName = malloc (strlen (pDevice) + 1); /* +1 is for EOS character */ if (pName == NULL) { netMblkFree (pEnd->pNetPool, pDrvCtrl->pSrc); netMblkFree (pEnd->pNetPool, pDrvCtrl->pDst); return (ERROR); } strcpy(pName, pDevice); /* Get lower level info that we need. */ muxIoctl(pDrvCtrl->pIpCookie, EIOCGADDR, (caddr_t)&pDrvCtrl->idr.ac_enaddr); muxIoctl(pDrvCtrl->pIpCookie, EIOCGFLAGS, (caddr_t)&flags); muxIoctl(pDrvCtrl->pIpCookie, EIOCGMIB2, (caddr_t)&mib2Tbl); pIfp = (IFNET *)&pDrvCtrl->idr; /* Hook up the interface pointers etc. */ bzero ((char *) pIfp, sizeof (*pIfp)); pIfp->if_unit = unit; pIfp->if_name = pName; pIfp->if_mtu = mib2Tbl.ifMtu; pIfp->if_baudrate = mib2Tbl.ifSpeed; /* interface speed */ pIfp->if_init = NULL; pIfp->if_ioctl = (FUNCPTR) ipIoctl; pIfp->if_output = ipOutput; pIfp->if_reset = NULL; pIfp->if_resolve = muxAddrResFuncGet(mib2Tbl.ifType, 0x800); pIfp->if_flags |= IFF_BROADCAST; pIfp->if_type = mib2Tbl.ifType; pIfp->if_addrlen = mib2Tbl.ifPhysAddress.addrLength; pIfp->pCookie = (void *)pDrvCtrl; pDrvCtrl->pSrc->mBlkHdr.mLen = pIfp->if_addrlen; pDrvCtrl->pDst->mBlkHdr.mLen = pIfp->if_addrlen; /* Get the length of the header. */ if (muxIoctl (pDrvCtrl->pIpCookie, EIOCGHDRLEN, (caddr_t) &ifHdrLen) != OK) pIfp->if_hdrlen = 0; else pIfp->if_hdrlen = (short) ifHdrLen; /* * Perform common duties while attaching to interface list */ for (pIfa = pIfp->if_addrlist; pIfa; pIfa = pIfa->ifa_next) { if ((pSdl = (struct sockaddr_dl *)pIfa->ifa_addr) && pSdl->sdl_family == AF_LINK) { pSdl->sdl_type = pIfp->if_type; pSdl->sdl_alen = pIfp->if_addrlen; bcopy((caddr_t)((struct arpcom *)pIfp)->ac_enaddr, LLADDR(pSdl), pIfp->if_addrlen); break; } } pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)ipTxStartup; if (muxIoctl(pDrvCtrl->pIpCookie, EIOCGMWIDTH, (caddr_t)&pDrvCtrl->memWidth) != OK) { pDrvCtrl->memWidth = NONE; } /* Find out the size for the first buffer chunk. */ muxIoctl(pDrvCtrl->pIpCookie, EIOCGFBUF, (caddr_t)&pDrvCtrl->minFirstBuf); pDrvCtrl->idr.ac_if.if_flags = flags; pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); /* Attach the interface. */ if_attach (pIfp); ifr.ifr_flags=pIfp->if_flags; /* Update the driver flag status */ ipIoctl(pIfp, SIOCSIFFLAGS, &ifr); pDrvCtrl->idr.ac_if.if_type = mib2Tbl.ifType; pDrvCtrl->attached = TRUE; return (OK); }/********************************************************************************* ipTxReStart - restart routine ** NOMANUAL*/LOCAL int ipTxRestart ( void * pCookie, /* given by muxRestart */ IP_DRV_CTRL * pDrvCtrl ) { 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().** Note that this function is ALWAYS called between an splnet() and an splx().* This is true because netTask(), and ether_output() take care of* this when calling this function. Therefore, no calls to these spl functions* are needed anywhere in this output thread.** NOMANUAL*/void ipTxStartup ( IP_DRV_CTRL * pDrvCtrl /* pointer to the drv control */ ) { M_BLK_ID pMblk; STATUS status = OK; if (!pDrvCtrl->attached) {#ifdef IP_DEBUG if (ipDebug) logMsg("ipTxStartup not attached!\n", 1, 2, 3, 4, 5, 6);#endif /* IP_DEBUG */ return; } /* * Loop until there are no more packets ready to send or we * have insufficient resources left to send another one. */ while (pDrvCtrl->idr.ac_if.if_snd.ifq_head) { /* dequeue a packet */ IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMblk); if ((etherOutputHookRtn != NULL) && (* etherOutputHookRtn) (&pDrvCtrl->idr, (struct ether_header *)pMblk->m_data, pMblk->m_len)) { continue; }#ifdef IP_DEBUG if (ipDebug) logMsg("ipTxStartup Transmiting!\n", 1, 2, 3, 4, 5, 6);#endif /* IP_DEBUG */ /* place a transmit request */ status = muxSend (pDrvCtrl->pIpCookie, pMblk); if (status == END_ERR_BLOCK) {#ifdef IP_DEBUG if (ipDebug) logMsg("Transmit error!\n", 1, 2, 3, 4, 5, 6);#endif /* IP_DEBUG */ /* If we are transmit 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -