if_ethersubr.c
来自「eCos操作系统源码」· C语言 代码 · 共 954 行 · 第 1/2 页
C
954 行
} if (bif != BDG_LOCAL) { struct mbuf *oldm = m ; save_eh = *eh ; /* because it might change */ m = bdg_forward(m, eh, bif); /* needs forwarding */ /* * Do not continue if bdg_forward() processed our * packet (and cleared the mbuf pointer m) or if * it dropped (m_free'd) the packet itself. */ if (m == NULL) { if (bif == BDG_BCAST || bif == BDG_MCAST) printf("bdg_forward drop MULTICAST PKT\n"); return; } if (m != oldm) /* m changed! */ eh = &save_eh ; } if (bif == BDG_LOCAL || bif == BDG_BCAST || bif == BDG_MCAST) goto recvLocal; /* receive locally */ /* If not local and not multicast, just drop it */ if (m != NULL) m_freem(m); return; }#endif#ifdef BRIDGErecvLocal:#endif /* Continue with upper layer processing */ ether_demux(ifp, eh, m);}/* * Upper layer processing for a received Ethernet packet. */voidether_demux(ifp, eh, m) struct ifnet *ifp; struct ether_header *eh; struct mbuf *m;{ struct ifqueue *inq; u_short ether_type; int s;#if defined(NETATALK) register struct llc *l;#endif#ifdef BRIDGE if (! (do_bridge && BDG_USED(ifp) ) )#endif /* Discard packet if upper layers shouldn't see it because it was unicast to a different Ethernet address. If the driver is working properly, then this situation can only happen when the interface is in promiscuous mode. */ if ((ifp->if_flags & IFF_PROMISC) != 0 && (eh->ether_dhost[0] & 1) == 0 && bcmp(eh->ether_dhost, IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0) { m_freem(m); return; } /* Discard packet if interface is not up */ if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return; } if (eh->ether_dhost[0] & 1) { /* * If this is not a simplex interface, drop the packet * if it came from us. */ if ((ifp->if_flags & IFF_SIMPLEX) == 0) { struct ifaddr *ifa; struct sockaddr_dl *sdl = NULL; /* find link-layer address */ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && sdl->sdl_family == AF_LINK) break; if (sdl && bcmp(LLADDR(sdl), eh->ether_shost, ETHER_ADDR_LEN) == 0) { m_freem(m); return; } } if (bcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, sizeof(etherbroadcastaddr)) == 0) m->m_flags |= M_BCAST; else m->m_flags |= M_MCAST; } if (m->m_flags & (M_BCAST|M_MCAST)) ifp->if_imcasts++; ifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); ether_type = ntohs(eh->ether_type);#if NVLAN > 0 if (ether_type == vlan_proto) { if (vlan_input(eh, m) < 0) ifp->if_data.ifi_noproto++; return; }#endif /* NVLAN > 0 */ switch (ether_type) {#ifdef INET case ETHERTYPE_IP: if (ipflow_fastforward(m)) return; schednetisr(NETISR_IP); inq = &ipintrq; break; case ETHERTYPE_ARP: if (ifp->if_flags & IFF_NOARP) { /* Discard packet if ARP is disabled on interface */ m_freem(m); return; } schednetisr(NETISR_ARP); inq = &arpintrq; break;#endif#ifdef IPX case ETHERTYPE_IPX: if (ef_inputp && ef_inputp(ifp, eh, m) == 0) return; schednetisr(NETISR_IPX); inq = &ipxintrq; break;#endif#ifdef INET6 case ETHERTYPE_IPV6: schednetisr(NETISR_IPV6); inq = &ip6intrq; break;#endif#ifdef NS case 0x8137: /* Novell Ethernet_II Ethernet TYPE II */ schednetisr(NETISR_NS); inq = &nsintrq; break;#endif /* NS */#ifdef NETATALK case ETHERTYPE_AT: schednetisr(NETISR_ATALK); inq = &atintrq1; break; case ETHERTYPE_AARP: /* probably this should be done with a NETISR as well */ aarpinput(IFP2AC(ifp), m); /* XXX */ return;#endif /* NETATALK */ default:#ifdef IPX if (ef_inputp && ef_inputp(ifp, eh, m) == 0) return;#endif /* IPX */#ifdef NS checksum = mtod(m, ushort *); /* Novell 802.3 */ if ((ether_type <= ETHERMTU) && ((*checksum == 0xffff) || (*checksum == 0xE0E0))){ if(*checksum == 0xE0E0) { m->m_pkthdr.len -= 3; m->m_len -= 3; m->m_data += 3; } schednetisr(NETISR_NS); inq = &nsintrq; break; }#endif /* NS */#if defined(NETATALK) if (ether_type > ETHERMTU) goto dropanyway; l = mtod(m, struct llc *); switch (l->llc_dsap) { case LLC_SNAP_LSAP: switch (l->llc_control) { case LLC_UI: if (l->llc_ssap != LLC_SNAP_LSAP) goto dropanyway; if (Bcmp(&(l->llc_snap_org_code)[0], at_org_code, sizeof(at_org_code)) == 0 && ntohs(l->llc_snap_ether_type) == ETHERTYPE_AT) { inq = &atintrq2; m_adj( m, sizeof( struct llc )); schednetisr(NETISR_ATALK); break; } if (Bcmp(&(l->llc_snap_org_code)[0], aarp_org_code, sizeof(aarp_org_code)) == 0 && ntohs(l->llc_snap_ether_type) == ETHERTYPE_AARP) { m_adj( m, sizeof( struct llc )); aarpinput(IFP2AC(ifp), m); /* XXX */ return; } default: goto dropanyway; } break; dropanyway: default: if (ng_ether_input_orphan_p != NULL) (*ng_ether_input_orphan_p)(ifp, m, eh); else m_freem(m); return; }#else /* NETATALK */ if (ng_ether_input_orphan_p != NULL) (*ng_ether_input_orphan_p)(ifp, m, eh); else m_freem(m); return;#endif /* NETATALK */ } s = splimp(); if (IF_QFULL(inq)) { IF_DROP(inq); m_freem(m); } else IF_ENQUEUE(inq, m); splx(s);}/* * Perform common duties while attaching to interface list */voidether_ifattach(ifp, bpf) register struct ifnet *ifp; int bpf;{ register struct ifaddr *ifa; register struct sockaddr_dl *sdl; if_attach(ifp); ifp->if_type = IFT_ETHER; ifp->if_addrlen = 6; ifp->if_hdrlen = 14; ifp->if_mtu = ETHERMTU; ifp->if_resolvemulti = ether_resolvemulti; if (ifp->if_baudrate == 0) ifp->if_baudrate = 10000000; ifa = ifnet_addrs[ifp->if_index - 1]; sdl = (struct sockaddr_dl *)ifa->ifa_addr; sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ifp->if_addrlen; bcopy((IFP2AC(ifp))->ac_enaddr, LLADDR(sdl), ifp->if_addrlen);#ifdef BPF if (bpf) bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));#endif if (ng_ether_attach_p != NULL) (*ng_ether_attach_p)(ifp);}/* * Perform common duties while detaching an Ethernet interface */voidether_ifdetach(ifp, bpf) struct ifnet *ifp; int bpf;{ if (ng_ether_detach_p != NULL) (*ng_ether_detach_p)(ifp);#ifdef BPF if (bpf) bpfdetach(ifp);#endif if_detach(ifp);}SYSCTL_DECL(_net_link);SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");intether_ioctl(ifp, command, data) struct ifnet *ifp; int command; caddr_t data;{ struct ifaddr *ifa = (struct ifaddr *) data; struct ifreq *ifr = (struct ifreq *) data; int error = 0; switch (command) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) {#ifdef INET case AF_INET: ifp->if_init(ifp->if_softc); /* before arpwhohas */ arp_ifinit(IFP2AC(ifp), ifa); break;#endif#ifdef IPX /* * XXX - This code is probably wrong */ case AF_IPX: { register struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); struct arpcom *ac = IFP2AC(ifp); if (ipx_nullhost(*ina)) ina->x_host = *(union ipx_host *) ac->ac_enaddr; else { bcopy((caddr_t) ina->x_host.c_host, (caddr_t) ac->ac_enaddr, sizeof(ac->ac_enaddr)); } /* * Set new address */ ifp->if_init(ifp->if_softc); break; }#endif#ifdef NS /* * XXX - This code is probably wrong */ case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); struct arpcom *ac = IFP2AC(ifp); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *) (ac->ac_enaddr); else { bcopy((caddr_t) ina->x_host.c_host, (caddr_t) ac->ac_enaddr, sizeof(ac->ac_enaddr)); } /* * Set new address */ ifp->if_init(ifp->if_softc); break; }#endif default: ifp->if_init(ifp->if_softc); break; } break; case SIOCGIFADDR: { struct sockaddr *sa; sa = (struct sockaddr *) & ifr->ifr_data; bcopy(IFP2AC(ifp)->ac_enaddr, (caddr_t) sa->sa_data, ETHER_ADDR_LEN); } break; case SIOCSIFMTU: /* * Set the interface MTU. */ if (ifr->ifr_mtu > ETHERMTU) { error = EINVAL; } else { ifp->if_mtu = ifr->ifr_mtu; } break; } return (error);}intether_resolvemulti(ifp, llsa, sa) struct ifnet *ifp; struct sockaddr **llsa; struct sockaddr *sa;{ struct sockaddr_dl *sdl; struct sockaddr_in *sin;#ifdef INET6 struct sockaddr_in6 *sin6;#endif u_char *e_addr; switch(sa->sa_family) { case AF_LINK: /* * No mapping needed. Just check that it's a valid MC address. */ sdl = (struct sockaddr_dl *)sa; e_addr = LLADDR(sdl); if ((e_addr[0] & 1) != 1) return EADDRNOTAVAIL; *llsa = 0; return 0;#ifdef INET case AF_INET: sin = (struct sockaddr_in *)sa; if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) return EADDRNOTAVAIL; MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, M_WAITOK|M_ZERO); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ETHER_ADDR_LEN; e_addr = LLADDR(sdl); ETHER_MAP_IP_MULTICAST(&sin->sin_addr, e_addr); *llsa = (struct sockaddr *)sdl; return 0;#endif#ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)sa; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { /* * An IP6 address of 0 means listen to all * of the Ethernet multicast address used for IP6. * (This is used for multicast routers.) */ ifp->if_flags |= IFF_ALLMULTI; *llsa = 0; return 0; } if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) return EADDRNOTAVAIL; MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, M_WAITOK|M_ZERO); sdl->sdl_len = sizeof *sdl; sdl->sdl_family = AF_LINK; sdl->sdl_index = ifp->if_index; sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ETHER_ADDR_LEN; e_addr = LLADDR(sdl); ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, e_addr); *llsa = (struct sockaddr *)sdl; return 0;#endif default: /* * Well, the text isn't quite right, but it's the name * that counts... */ return EAFNOSUPPORT; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?