📄 ipproto.c
字号:
else IF_PREPEND (&pDrvCtrl->idr.ac_if.if_snd, pMblk); break; } else ++pDrvCtrl->idr.ac_if.if_opackets; #ifdef IP_DEBUG if (ipDebug) logMsg("ipTxStartup done!\n", 1, 2, 3, 4, 5, 6);#endif /* IP_DEBUG */ } }/********************************************************************************* 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; int error; /* return error status */ int count; IMPORT int ipMaxUnits; int limit = ipMaxUnits; /* 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 && pDrvCtrl->pIpCookie == pEnd) break; } if (count == limit) { /* Device not attached. */ return (ERROR); } error = ipShutdownRtn (pDrvCtrl->pIpCookie, pDrvCtrl); 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; struct sockaddr_in* addr; register struct in_ifaddr* pIa = 0; char address[6]; M2_INTERFACETBL mib2Tbl; 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; END_OBJ * pEnd; pDrvCtrl = (IP_DRV_CTRL *)(ifp->ac_if.pCookie); pEnd = pDrvCtrl->pIpCookie; if (pEnd == NULL) return (EINVAL); switch (cmd) { case SIOCSIFADDR: for (pIa = in_ifaddr; pIa; pIa = pIa->ia_next) if ((pIa->ia_ifp == (struct ifnet *)ifp) && (pIa->ia_addr.sin_addr.s_addr == dt_saddr)) break; pIa->ia_ifa.ifa_rtrequest = arp_rtrequest; pIa->ia_ifa.ifa_flags |= RTF_CLONING; ifp->ac_ipaddr = IA_SIN (data)->sin_addr; arpwhohas (ifp, &IA_SIN (data)->sin_addr); break; case SIOCGMIB2CNFG: error = muxIoctl (pEnd, EIOCGMIB2, (caddr_t)&mib2Tbl); if (error != OK) return (EINVAL); pm2DrvCnfg->ifType = mib2Tbl.ifType; /* ppp type */ pm2DrvCnfg->ifSpecific.idLength = 0; /* use default */ break; case SIOCGMIB2CNTRS: /* fill in counters */ error = muxIoctl (pEnd, EIOCGMIB2, (caddr_t)&mib2Tbl); if (error != OK) return (EINVAL); pm2DrvCntr->ifSpeed = mib2Tbl.ifSpeed; pm2DrvCntr->ifInOctets = mib2Tbl.ifInOctets; pm2DrvCntr->ifInNUcastPkts = mib2Tbl.ifInNUcastPkts; pm2DrvCntr->ifInDiscards = mib2Tbl.ifInDiscards; pm2DrvCntr->ifInUnknownProtos = mib2Tbl.ifInUnknownProtos; pm2DrvCntr->ifOutOctets = mib2Tbl.ifOutOctets; pm2DrvCntr->ifOutNUcastPkts = mib2Tbl.ifOutNUcastPkts; pm2DrvCntr->ifOutDiscards = mib2Tbl.ifOutDiscards; break; case SIOCADDMULTI: 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: ifr = (struct ifreq *)data; addr = ((struct sockaddr_in *)&ifr->ifr_addr); pMblk= (struct mBlk*) malloc(sizeof(M_BLK)); pMblk->mBlkHdr.mFlags |= M_MCAST; ifp->ac_if.if_resolve(NULL,NULL,pMblk,addr,&address); free(pMblk); error = muxMCastAddrAdd (pEnd, (char *)&address); break; default: error = EINVAL; break; } break; case SIOCDELMULTI: 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: ifr = (struct ifreq *)data; addr = ((struct sockaddr_in *)&ifr->ifr_addr); pMblk= (struct mBlk*) malloc(sizeof(M_BLK)); pMblk->mBlkHdr.mFlags |= M_MCAST; ifp->ac_if.if_resolve(NULL,NULL,pMblk,addr,&address); free(pMblk); error = muxMCastAddrDel (pEnd, (char *)&address); break; default: error = EINVAL; break; } break; case SIOCGETMULTI: break; case SIOCSIFFLAGS: ifr = (struct ifreq *) data; /* * Turn off all flags that are disabled in the request * correcting for the conversion from short to long */ flagsMask = (unsigned short) (~ ifr->ifr_flags); /* Two's complement used to disable flags by muxIoctl () */ flagsMask = -flagsMask - 1; error = muxIoctl (pEnd, EIOCSFLAGS, (caddr_t) flagsMask); /* * Next set all flags that are set in request correcting for * the conversion from short to long. */ flagsMask = (unsigned short) ifr->ifr_flags; error |= muxIoctl (pEnd, EIOCSFLAGS, (caddr_t) flagsMask); break; default: error = muxIoctl (pEnd, cmd, data); break; } return (error); }/******************************************************************************** ipOutput - routine to encapsulate an IP packet.** This routine encapsulates a packet in the link-level frame. It* is roughly equivalent to the Ethernet output routine, but uses* the MUX routines to acheive some link-layer independence for* packets of family AF_INET. The precise behavior depends on* the underlying END driver. This routine will generate Ethernet* frames unless the driver provides a routine to form the appropriate* frame header.* * NOTE: It assumes that ifp is actually a pointer to an arpcom structure.** NOMANUAL*/int ipOutput ( register struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst, struct rtentry *rt0 ) { u_short etype; int s, error = 0; u_char edst[6]; register struct mbuf *m = m0; register struct rtentry *rt; struct mbuf *mcopy = (struct mbuf *)0; int off; struct arpcom *ac = (struct arpcom *)ifp; struct ether_header* eh; IP_DRV_CTRL* pDrvCtrl; END_OBJ* pEnd; pDrvCtrl = (IP_DRV_CTRL *)ifp->pCookie; pEnd = pDrvCtrl->pIpCookie; if (pEnd == NULL) senderr (EINVAL); if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) senderr(ENETDOWN); ifp->if_lastchange = tickGet(); if ((rt = rt0)) { if ((rt->rt_flags & RTF_UP) == 0) { if ((rt0 = rt = rtalloc1(dst, 1))) rt->rt_refcnt--; else senderr(EHOSTUNREACH); } if (rt->rt_flags & RTF_GATEWAY) { if (rt->rt_gwroute == 0) goto lookup; if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { rtfree(rt); rt = rt0; lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1); if ((rt = rt->rt_gwroute) == 0) senderr(EHOSTUNREACH); } } if (rt->rt_flags & RTF_REJECT) if (rt->rt_rmx.rmx_expire == 0 || tickGet() < rt->rt_rmx.rmx_expire) senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); } switch (dst->sa_family) { case AF_INET: if (ifp->if_resolve != NULL) if (!ifp->if_resolve(ac, rt, m, dst, edst)) return (0); /* if not yet resolved */ /* If broadcasting on a simplex interface, loopback a copy */ if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) mcopy = m_copy(m, 0, (int)M_COPYALL); off = m->m_pkthdr.len - m->m_len; etype = ETHERTYPE_IP; break; case AF_UNSPEC: /* * WARNING: At the moment this code ONLY handles 14 byte * headers of the type like Ethernet. */ eh = (struct ether_header *)dst->sa_data; bcopy((caddr_t)eh->ether_dhost, (caddr_t)edst, sizeof (edst)); etype = eh->ether_type; break; default: logMsg ("%s%d: can't handle af%d\n", (int)ifp->if_name, ifp->if_unit, dst->sa_family, 0, 0, 0); senderr(EAFNOSUPPORT); } if (mcopy) (void) looutput(ifp, mcopy, dst, rt); etype = htons(etype); pDrvCtrl->pDst->m_data = (char *)&edst; pDrvCtrl->pSrc->m_data = (char *)&ac->ac_enaddr; pDrvCtrl->pDst->mBlkHdr.reserved = etype; pDrvCtrl->pSrc->mBlkHdr.reserved = etype; if ((m = muxAddressForm (pEnd, m, pDrvCtrl->pSrc, pDrvCtrl->pDst)) == NULL) senderr(ENOBUFS); s = splimp(); /* * Queue message on interface, and start output if interface * not yet active. */ if (IF_QFULL(&ifp->if_snd)) { IF_DROP(&ifp->if_snd); splx(s); senderr(ENOBUFS); } IF_ENQUEUE(&ifp->if_snd, m); if ((ifp->if_flags & IFF_OACTIVE) == 0) (*ifp->if_start)(ifp); splx(s); ifp->if_obytes += m->mBlkHdr.mLen; if (m->m_flags & M_MCAST || m->m_flags & M_BCAST) ifp->if_omcasts++; return (error); bad: if (m) netMblkClChainFree(m); return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -