📄 if_subr.c
字号:
int width /* width of the copy */ ) { FAST char * pBuf = (char *) (pIoBuf); FAST struct mbuf * pMbufHead = pMbuf; FAST char * adjBuf; FAST int adjLen; FAST int odd = 0; FAST int ix; char temp [4]; if (width == NONE) { for (; pMbuf != NULL; pBuf += pMbuf->m_len, pMbuf = pMbuf->m_next) bcopy (mtod (pMbuf, char *), pBuf, pMbuf->m_len); } else if (width == 1) { for (; pMbuf != NULL; pBuf += pMbuf->m_len, pMbuf = pMbuf->m_next) bcopyBytes (mtod (pMbuf, char *), pBuf, pMbuf->m_len); } else if (width == 2) { for (; pMbuf != NULL; pMbuf = pMbuf->m_next) { adjLen = pMbuf->m_len; adjBuf = mtod(pMbuf, char *); if (odd > 0) { --pBuf; *((UINT16 *) temp) = *((UINT16 *) pBuf); temp [1] = *adjBuf++; --adjLen; *((UINT16 *) pBuf) = *((UINT16 *) temp); pBuf += 2; } bcopyWords (adjBuf, pBuf, (adjLen + 1) >> 1); pBuf += adjLen; odd = adjLen & 0x1; } } else if (width == 4) { for (; pMbuf != NULL; pMbuf = pMbuf->m_next) { adjLen = pMbuf->m_len; adjBuf = mtod(pMbuf, char *); if (odd > 0) { pBuf -= odd; *((UINT32 *) temp) = *((UINT32 *) pBuf); for (ix = odd; ix < 4; ix++, adjBuf++, --adjLen) temp [ix] = *adjBuf; *((UINT32 *) pBuf) = *((UINT32 *) temp); pBuf += 4; } bcopyLongs (adjBuf, pBuf, (adjLen + 3) >> 2); pBuf += adjLen; odd = adjLen & 0x3; } } else { panic ("copyFromMbufs"); } m_freem (pMbufHead); /* free the mbuf chain */ return ((int) pBuf - (int) pIoBuf); /* return length copied */ }/********************************************************************************* build_cluster - encapsulate a passed buffer into a cluster mbuf.** This routine is used to surround the passed buffer <buf0> with a* mbuf header and make it a pseudo cluster. It is used primarily by the* network interface drivers to avoid copying large chunk of data incoming* from the network. Network interface device drivers typically call this* routine with a pointer to the memory location where the IP data reside.* This buffer pointer is used as a cluster buffer pointer and inserted* into mbuf along with other relevant pieces information such as the* index into the reference count array, pointer to the reference count* array and the driver level free routine.** RETURNS: NULL if unsuccessful, pointer to <struct mbuf> if successful.** SEE ALSO: do_protocol_with_type(), uipc_mbuf.c** NOMANUAL*/struct mbuf *build_cluster (buf0, totlen, ifp, ctype, pRefCnt, freeRtn, arg1, arg2, arg3) u_char *buf0; /* the buffer containing data */ int totlen; /* len of the buffer */ struct ifnet *ifp; /* network interface device pointer */ u_char ctype; /* type of this cluster being built */ u_char *pRefCnt; /* type-specific ref count array */ FUNCPTR freeRtn; /* driver level free callback routine */ int arg1; /* first argument to freeRtn() */ int arg2; /* second argument to freeRtn() */ int arg3; /* third argument to freeRtn() */ { FAST struct mbuf *m; CL_BLK_ID pClBlk; /* get an mbuf header, header will have ifp info in the packet header */ m = mBlkGet(_pNetDpool, M_DONTWAIT, MT_DATA); if (m == NULL) /* out of mbufs! */ return (NULL); pClBlk = clBlkGet (_pNetDpool, M_DONTWAIT); if (pClBlk == NULL) /* out of cl Blks */ { m_free (m); return (NULL); } /* intialize the header */ m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = totlen; m->m_data = (caddr_t) buf0; m->m_len = m->m_pkthdr.len; m->m_flags = (M_EXT | M_PKTHDR) ; m->pClBlk = pClBlk; m->m_extBuf = (caddr_t) buf0; m->m_extSize = m->m_pkthdr.len; m->m_extFreeRtn = freeRtn; m->m_extArg1 = arg1; m->m_extArg2 = arg2; m->m_extArg3 = arg3; m->m_extRefCnt = 1; return (m); }/********************************************************************************* do_protocol_with_type - demultiplex incoming packet to the protocol handlers** Demultiplexes the incoming packet to the associated protocol handler. This* version supports IP, ARP, and a generic mechanism via an external lookup* table.** This routine differs from do_protocol() in that the link-level frame type* is passed directly, instead of passing a pointer to an Ethernet header,* respectively.** This routine must not be called interrupt level.** NOMANUAL*/void do_protocol_with_type ( u_short type, /* the frame type field */ struct mbuf * pMbuf, /* the frame data, in mbuf chain */ struct arpcom * pArpcom, /* the source interface information */ int len /* length of the mbuf data */ ) { int s; FAST struct ifqueue * inq; FUNCPTR pInputFunc; /* message handler */ switch (type) { case ETHERTYPE_IP: ipintr(pMbuf); return; case ETHERTYPE_ARP: inq = &arpintrq; pInputFunc = (FUNCPTR) arpintr; break; default: { /* No protocol. Drop packet */ ((struct ifnet *) pArpcom)->if_noproto++; m_freem (pMbuf); /* free the mbuf chain */ return; } } s = splnet (); if (IF_QFULL(inq)) { IF_DROP (inq); m_freem (pMbuf); /* free the mbuf chain */ splx (s); } else { IF_ENQUEUE (inq, pMbuf); /* put the mbuf chain in the packet queue */ splx (s); /* Schedule a new job to finish the handling of the IP or ARP data. */#ifdef VIRTUAL_STACK netJobAdd (pInputFunc, pArpcom->ac_if.vsNum, 0, 0, 0, 0);#else arpintr();#endif /* VIRTUAL_STACK */ } }/********************************************************************************* set_if_addr - handle SIOCSIFADDR ioctl** Sets a protocol address associated with this network interface.* This function is called by various ioctl handlers in each of the network* interface drivers.** RETURNS: 0 or appropriate errno** NOMANUAL*/int set_if_addr (ifp, data, enaddr) struct ifnet *ifp; /* interface */ char *data; /* usually "struct ifaddr *" */ u_char *enaddr;/* ethernet address */ { int error = 0; FAST struct ifaddr *ifa = (struct ifaddr *) data; ifp->if_flags |= IFF_UP; if ((error = (*ifp->if_init) (ifp->if_unit)) != 0) return (error); switch (ifa->ifa_addr->sa_family) {#ifdef INET case AF_INET: ((struct arpcom *) ifp)->ac_ipaddr = IA_SIN (ifa)->sin_addr; arpwhohas ((struct arpcom *) ifp, &IA_SIN (ifa)->sin_addr); break;#endif /* INET */ default: logMsg ("eh: set_if_addr unknown family 0x%x\n", ifa->ifa_addr->sa_family,0,0,0,0,0); break; } return (0); }/********************************************************************************* ether_attach - attach a new network interface to the network layer.** Fill in the ifnet structure and pass it off to if_attach () routine* which will attach the network interface described in that structure* to the network layer software for future use in routing, packet reception,* and transmisison.** NOMANUAL*/STATUS ether_attach (ifp, unit, name, initRtn, ioctlRtn, outputRtn, resetRtn) struct ifnet *ifp; /* network interface data structure */ int unit; /* unit number */ char *name; /* name of the interface */ FUNCPTR initRtn; /* initialization routine */ FUNCPTR ioctlRtn; /* ioctl handler */ FUNCPTR outputRtn; /* output routine */ FUNCPTR resetRtn; /* reset routine */ {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 14, 17, WV_NETEVENT_ETHERATTACH_START, ifp)#endif /* INCLUDE_WVNET */#endif bzero ((char *) ifp, sizeof (*ifp)); ifp->if_unit = unit; ifp->if_name = name; ifp->if_mtu = ETHERMTU; ifp->if_init = initRtn; ifp->if_ioctl = ioctlRtn; ifp->if_output = outputRtn; ifp->if_reset = resetRtn; ifp->if_flags = IFF_BROADCAST; return (if_attach (ifp)); }/********************************************************************************* netTypeAdd - add a network type to list of network types.** RETURNS: OK if successful, otherwise ERROR.** NOMANUAL*/STATUS netTypeAdd (etherType, inputRtn) int etherType; /* ethernet type */ FUNCPTR inputRtn; /* input routine */ { NET_TYPE * pType; if ((pType = (NET_TYPE *) KHEAP_ALLOC(sizeof(NET_TYPE))) == NULL) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 7, 2, WV_NETEVENT_TYPEADD_FAIL, etherType)#endif /* INCLUDE_WVNET */#endif return (ERROR); } bzero((char *)pType, sizeof (NET_TYPE)); pType->etherType = etherType; pType->inputRtn = inputRtn; lstAdd (&netTypeList, &pType->node); return (OK); }/********************************************************************************* netTypeDelete - delete a network type from the list of network types.** RETURNS: OK if successful, otherwise ERROR.** NOMANUAL*/STATUS netTypeDelete (etherType) int etherType; /* ethernet type */ { NET_TYPE * pType; for (pType = (NET_TYPE *) lstFirst (&netTypeList); pType != NULL; pType = (NET_TYPE *) lstNext (&pType->node)) { if (etherType == pType->etherType) { lstDelete (&netTypeList, &pType->node); KHEAP_FREE((caddr_t)pType); return (OK); } } return (ERROR); }/********************************************************************************* netTypeInit - initialize list of network types.** RETURNS: N/A** NOMANUAL*/void netTypeInit () { lstInit (&netTypeList); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -