📄 if_subr.c
字号:
etype = ntohs(eh->ether_type); /* add code here to process IEEE802.3 LLC format, Hook!! */ /* demux the packet and hand off the ip layer */ do_protocol_with_type (etype, m , ac, m->m_pkthdr.len); }/* * Perform common duties while attaching to interface list */voidether_ifattach(ifp) register struct ifnet *ifp;{ register struct ifaddr *ifa; register struct sockaddr_dl *sdl;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 11, 14, WV_NETEVENT_ETHERIFATTACH_START, ifp)#endif /* INCLUDE_WVNET */#endif ifp->if_type = IFT_ETHER; ifp->if_addrlen = 6; ifp->if_hdrlen = 14; ifp->if_mtu = ETHERMTU; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && sdl->sdl_family == AF_LINK) { sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ifp->if_addrlen; bcopy((caddr_t)((struct arpcom *)ifp)->ac_enaddr, LLADDR(sdl), ifp->if_addrlen); break; }}/* * Add an Ethernet multicast address or range of addresses to the list for a * given interface. */intether_addmulti(ifr, ac) struct ifreq *ifr; register struct arpcom *ac;{ register struct ether_multi *enm; struct sockaddr_in *sin; u_char addrlo[6]; u_char addrhi[6]; int s = splimp();/* * XXX - This event cannot currently occur: the ether_addmulti() routine * provides multicasting support which is not available for VxWorks * BSD Ethernet drivers.#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /@ WV_NET_VERBOSE event @/ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 12, 15, WV_NETEVENT_ADDMULT_START, ac->ac_if)#endif /@ INCLUDE_WVNET @/#endif * XXX - end of unused event */ switch (ifr->ifr_addr.sa_family) { case AF_UNSPEC: bcopy((char *)ifr->ifr_addr.sa_data, (char *)addrlo, 6); bcopy((char *) addrlo, (char *)addrhi, 6); break;#ifdef INET case AF_INET: sin = (struct sockaddr_in *)&(ifr->ifr_addr); if (sin->sin_addr.s_addr == INADDR_ANY) { /* * An IP address of INADDR_ANY means listen to all * of the Ethernet multicast addresses used for IP. * (This is for the sake of IP multicast routers.) */ bcopy((char *)ether_ipmulticast_min, (char *)addrlo, 6); bcopy((char *)ether_ipmulticast_max, (char *)addrhi, 6); } else { ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); bcopy((char *)addrlo, (char *)addrhi, 6); } break;#endif default: splx(s);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 4, 8, WV_NETEVENT_ADDMULT_AFNOTSUPP, ifr->ifr_addr.sa_family) #endif /* INCLUDE_WVNET */#endif return (EAFNOSUPPORT); } /* * Verify that we have valid Ethernet multicast addresses. */ if ((addrlo[0] & 0x01) != 1 || (addrhi[0] & 0x01) != 1) { splx(s);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 5, 9, WV_NETEVENT_ADDMULT_BADADDR, ac->ac_if) #endif /* INCLUDE_WVNET */#endif return (EINVAL); } /* * See if the address range is already in the list. */ ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); if (enm != NULL) { /* * Found it; just increment the reference count. */ ++enm->enm_refcount; splx(s); return (0); } /* * New address or range; malloc a new multicast record * and link it into the interface's multicast list. */ MALLOC (enm, struct ether_multi *, sizeof(*enm), MT_IFMADDR, M_DONTWAIT); if (enm == NULL) { splx(s);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 6, 1, WV_NETEVENT_ADDMULT_NOBUFS)#endif /* INCLUDE_WVNET */#endif return (ENOBUFS); } bcopy((char *)addrlo, (char *)enm->enm_addrlo, 6); bcopy((char *)addrhi, (char *)enm->enm_addrhi, 6); enm->enm_ac = ac; enm->enm_refcount = 1; enm->enm_next = ac->ac_multiaddrs; ac->ac_multiaddrs = enm; ac->ac_multicnt++; splx(s); /* * Return ENETRESET to inform the driver that the list has changed * and its reception filter should be adjusted accordingly. */ return (ENETRESET);}/* * Delete a multicast address record. */intether_delmulti(ifr, ac) struct ifreq *ifr; register struct arpcom *ac;{ register struct ether_multi *enm; register struct ether_multi **p; struct sockaddr_in *sin; u_char addrlo[6]; u_char addrhi[6]; int s = splimp();/* * XXX - This event cannot currently occur: the ether_delmulti() routine * provides multicasting support which is not available for VxWorks * BSD Ethernet drivers.#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /@ WV_NET_VERBOSE event @/ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 13, 16, WV_NETEVENT_DELMULT_START, ac->ac_if)#endif /@ INCLUDE_WVNET @/#endif * XXX - end of unused event */ switch (ifr->ifr_addr.sa_family) { case AF_UNSPEC: bcopy((char *)ifr->ifr_addr.sa_data, (char *)addrlo, 6); bcopy((char *)addrlo, (char *)addrhi, 6); break;#ifdef INET case AF_INET: sin = (struct sockaddr_in *)&(ifr->ifr_addr); if (sin->sin_addr.s_addr == INADDR_ANY) { /* * An IP address of INADDR_ANY means stop listening * to the range of Ethernet multicast addresses used * for IP. */ bcopy((char *)ether_ipmulticast_min, (char *)addrlo, 6); bcopy((char *)ether_ipmulticast_max, (char *)addrhi, 6); } else { ETHER_MAP_IP_MULTICAST(&sin->sin_addr, addrlo); bcopy((char *)addrlo, (char *)addrhi, 6); } break;#endif default: splx(s);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 6, 10, WV_NETEVENT_DELMULT_AFNOTSUPP, ifr->ifr_addr.sa_family)#endif /* INCLUDE_WVNET */#endif return (EAFNOSUPPORT); } /* * Look up the address in our list. */ ETHER_LOOKUP_MULTI(addrlo, addrhi, ac, enm); if (enm == NULL) { splx(s);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_ERROR event */ WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_ERROR, 7, 11, WV_NETEVENT_DELMULT_BADADDR, ac->ac_if)#endif /* INCLUDE_WVNET */#endif return (ENXIO); } if (--enm->enm_refcount != 0) { /* * Still some claims to this record. */ splx(s); return (0); } /* * No remaining claims to this record; unlink and free it. */ for (p = &enm->enm_ac->ac_multiaddrs; *p != enm; p = &(*p)->enm_next) continue; *p = (*p)->enm_next; FREE(enm, MT_IFMADDR); ac->ac_multicnt--; splx(s); /* * Return ENETRESET to inform the driver that the list has changed * and its reception filter should be adjusted accordingly. */ return (ENETRESET);}/********************************************************************************* check_trailer - check ethernet frames that have trailers following them** Decypher the ethernet frames that are encoded via trailer protocol which* has a link level type field that contains a value which is an encoding of* the size of the data portion. The original BSD 4.2 and 4.3 TCP/IP* implementations use the trailer protocol to accomplish more efficient* copying of data. Basically the idea was to put the variable lenght protocol* headers (TCP, UDP, IP headers) at the end of a page aligned data and use* the link-level type field (ethernet type) to indicate both the use of a* specialized framing protocol as well as the length of the data following* the ethernet header. The original link-level type field and the length* of the protocol headers following the data portion are attached between* the data portion (which should be of length multiple of 512 bytes) and* protocol headers. (size of data portion == (type - 0x1000) * 415)** Upon return, 'pOff' will contain NULL if trailer protocol is not being* used. Otherwise, 'pOff' points to the trailer header and 'pLen'* will contain the size of the frame.** NOMANUAL*/void check_trailer (eh, pData, pLen, pOff, ifp) FAST struct ether_header *eh; /* ethernet header */ FAST unsigned char *pData; /* data immediately after 'eh' */ FAST int *pLen; /* value/result input data length */ FAST int *pOff; /* result -- points to trailer header */ FAST struct ifnet *ifp; /* network interface */ {#if 0 /* XXX No support for trailers in BSD44 vxWorks */ FAST int resid; eh->ether_type = ntohs((u_short)eh->ether_type); if ((eh->ether_type >= ETHERTYPE_TRAIL) && (eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)) { *pOff = (eh->ether_type - ETHERTYPE_TRAIL) * 512; if (*pOff >= ifp->if_mtu) return; /* sanity */ eh->ether_type = ntohs (*(u_short *) (pData + *pOff)); resid = ntohs (*(u_short *) (pData + *pOff + 2)); if ((*pOff + resid) > *pLen) return; /* sanity */ *pLen = *pOff + resid; } else *pOff = 0;#endif /* XXX No trailer support in BSD44 */ }/********************************************************************************* bcopy_to_mbufs - copy data into mbuf chain** Copies up to <totlen> bytes of data from <buf0> into a freshly allocated* mbuf. The <off0> parameter indicates the amount of trailer encapsulation,* which was formerly handled according to the trailer protocol described in* check_trailer(). Since trailer encapsulation is not supported in BSD 4.4,* that parameter is unused. The <width> argument supports machines which * have special byte alignment requirements when copying data from device * I/O buffers to main memory. A macro function called 'copy_to_mbufs' is * provided in the "mbuf.h" file for compatability with SunOS, which doesn't * support the <width> parameter. This function uses mbuf clusters when possible* to enhance network throughput.** RETURNS: first mbuf or 0 if error** NOMANUAL*/struct mbuf *bcopy_to_mbufs (buf0, totlen, off0, ifp, width) u_char *buf0; /* buffer to be copied into mbufs */ int totlen; /* number of bytes to be copied */ int off0; /* trailer protocol indicative */ struct ifnet *ifp; /* network interface */ int width; /* copy data by this unit width */ { return (m_devget ((char *) buf0, totlen, width, ifp, NULL)); }/******************************************************************************** copyFromMbufs - copy data from an mbuf chain** This routine copies data from an mbuf chain into a given buffer.* The length of the data copied from the mbuf chain is returned.* The argument width is provided for machines that have special byte alignment* requirements when copying data to an I/O buffer of the device from main* memory. This routine frees the mbuf chain passed to it. ** This routine should not be used since it can cause unaligned memory accesses* resulting in target crashes.* * RETURNS: length of data copied.** NOMANUAL*/int copyFromMbufs ( char * pIoBuf, /* buffer to copy mbufs into */ struct mbuf * pMbuf, /* pointer to an mbuf chain */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -