📄 if_ether.c
字号:
} /* Announce a new entry if requested. */ if (rt->rt_flags & RTF_ANNOUNCE) arprequest((struct arpcom *)rt->rt_ifp, &SIN(rt_key(rt))->sin_addr.s_addr, &SIN(rt_key(rt))->sin_addr.s_addr, (u_char *)LLADDR(SDL(gate))); /*FALLTHROUGH*/ case RTM_RESOLVE: if (gate->sa_family != AF_LINK || gate->sa_len < sizeof(null_sdl)) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_WARNING, 1, 8, WV_NETEVENT_ARPRTREQ_BADGATE, gate->sa_family, gate->sa_len)#endif /* INCLUDE_WVNET */#endif logMsg("arp_rtrequest: bad gateway value",0,0,0,0,0,0); break; } SDL(gate)->sdl_type = rt->rt_ifp->if_type; SDL(gate)->sdl_index = rt->rt_ifp->if_index; if (la != 0) break; /* This happens on a route change */ /* * Case 2: This route may come from cloning, or a manual route * add with a LL address. */ if (arp_inuse >= arpMaxEntries) arpEntryDelete (); R_Malloc(la, struct llinfo_arp *, sizeof(*la)); rt->rt_llinfo = (caddr_t)la; if (la == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 1, 1, WV_NETEVENT_ARPRTREQ_FAIL)#endif /* INCLUDE_WVNET */#endif logMsg("arp_rtrequest: malloc failed\n",0,0,0,0,0,0); break; } arp_inuse++, arp_allocated++; Bzero(la, sizeof(*la)); la->la_rt = rt; rt->rt_flags |= RTF_LLINFO;#ifdef VIRTUAL_STACK insque(la, &_llinfo_arp);#else insque(la, &llinfo_arp);#endif /* VIRTUAL_STACK */ ifAddr = rt->rt_ifp->if_addrlist; /* * Find destination address in list of addresses assigned to * interface. */ while (ifAddr) { if (SIN(rt_key(rt))->sin_addr.s_addr == (IA_SIN(ifAddr))->sin_addr.s_addr) { /* * This test used to be * if (loif.if_flags & IFF_UP) * It allowed local traffic to be forced * through the hardware by configuring the loopback down. * However, it causes problems during network configuration * for boards that can't receive packets they send. * It is now necessary to clear "useloopback" and remove * the route to force traffic out to the hardware. */ rt->rt_expire = 0; Bcopy(((struct arpcom *)rt->rt_ifp)->ac_enaddr, LLADDR(SDL(gate)), SDL(gate)->sdl_alen = 6); if (useloopback) rt->rt_ifp = loif; break; } ifAddr = ifAddr->ifa_next; } break; case RTM_DELETE: if (la == 0) break; arp_inuse--; remque(la); rt->rt_llinfo = 0; rt->rt_flags &= ~RTF_LLINFO; if (la->la_hold) m_freem(la->la_hold); Free((caddr_t)la); }}/* * Broadcast an ARP packet, asking who has addr on interface ac. */voidarpwhohas(ac, addr) register struct arpcom *ac; register struct in_addr *addr;{ arprequest(ac, &ac->ac_ipaddr.s_addr, &addr->s_addr, ac->ac_enaddr);}/* * Broadcast an ARP request. Caller specifies: * - arp header source ip address * - arp header target ip address * - arp header source ethernet address */static voidarprequest(ac, sip, tip, enaddr) register struct arpcom *ac; register u_long *sip, *tip; register u_char *enaddr;{ register struct mbuf *m; register struct ether_header *eh; register struct ether_arp *ea; struct sockaddr sa; if ((m = mHdrClGet(M_DONTWAIT, MT_DATA, sizeof(*ea), TRUE)) == NULL) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 2, 2, WV_NETEVENT_ARPREQ_FAIL)#endif /* INCLUDE_WVNET */#endif return; } m->m_len = sizeof(*ea); m->m_pkthdr.len = sizeof(*ea); MH_ALIGN(m, sizeof(*ea)); ea = mtod(m, struct ether_arp *); eh = (struct ether_header *)sa.sa_data; bzero((caddr_t)ea, sizeof (*ea)); bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, sizeof(eh->ether_dhost)); eh->ether_type = ETHERTYPE_ARP; /* if_output will swap */ ea->arp_hrd = htons(ARPHRD_ETHER); ea->arp_pro = htons(ETHERTYPE_IP); ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */ ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */ ea->arp_op = htons(ARPOP_REQUEST); bcopy((caddr_t)enaddr, (caddr_t)ea->arp_sha, sizeof(ea->arp_sha)); bcopy((caddr_t)sip, (caddr_t)ea->arp_spa, sizeof(ea->arp_spa)); bcopy((caddr_t)tip, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa)); sa.sa_family = AF_UNSPEC; sa.sa_len = sizeof(sa); (*ac->ac_if.if_output)(&ac->ac_if, m, &sa, (struct rtentry *)0);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 8, 18, WV_NETEVENT_ARPREQ_SEND)#endif /* INCLUDE_WVNET */#endif}/* * Resolve an IP address into an ethernet address. If success, * desten is filled in. If there is no entry in arptab, * set one up and broadcast a request for the IP address. * Hold onto this mbuf and resend it once the address * is finally resolved. A return value of 1 indicates * that desten has been filled in and the packet should be sent * normally; a 0 return indicates that the packet has been * taken over here, either now or for later transmission. */intarpresolve(ac, rt, m, dst, desten) register struct arpcom *ac; register struct rtentry *rt; struct mbuf *m; register struct sockaddr *dst; register u_char *desten;{ register struct llinfo_arp *la; struct sockaddr_dl *sdl; int alen; /* Length of MAC address */ u_long lna; /* Host portion if IP address */ struct ifnet *pIf = &ac->ac_if; USHORT *pSrc = NULL; USHORT *pDst = NULL;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_DSTADDROUT_MARKER_1 (NET_AUX_EVENT, WV_NET_VERBOSE, 9, 19, ((struct sockaddr_in *)dst)->sin_addr.s_addr, WV_NETEVENT_ARPRESOLV_START, ((struct sockaddr_in *)dst)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif if (m != NULL) /* check if mbuf is not null */ { if (m->m_flags & M_BCAST) { /* broadcast */ pDst = (USHORT *)desten; pDst[0] = 0xFFFF; pDst[1] = 0xFFFF; pDst[2] = 0xFFFF; return (1); } if (m->m_flags & M_MCAST) { /* multicast */ ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); return(1); } } if (rt) la = (struct llinfo_arp *)rt->rt_llinfo; else { if ((la = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0))) rt = la->la_rt; } if (la == 0 || rt == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_DSTADDROUT_EVENT_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 3, 3, ((struct sockaddr_in *)dst)->sin_addr.s_addr, WV_NETEVENT_ARPLOOK_FAIL, WV_NET_SEND, ((struct sockaddr_in *)dst)->sin_addr.s_addr)#endif /* INCLUDE_WVNET */#endif logMsg ("arpresolve: lookup failed (resource shortage or \n \network configuration error -- check netmask)\n",0,0,0,0,0,0); m_freem(m); return (0); } sdl = SDL(rt->rt_gateway); /* * Check the address family and length is valid, the address * is resolved; otherwise, try to resolve. */ if ((rt->rt_expire == 0 || !TICK_GEQ (tickGet(), rt->rt_expire)) && sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { pSrc = (USHORT *)LLADDR(sdl); pDst = (USHORT *)desten; pDst[0] = pSrc[0]; pDst[1] = pSrc[1]; pDst[2] = pSrc[2]; return 1; } /* * For shared memory interface using a BSD driver, resolve using * smNetAddrResolve. All other BSD drivers will have if_resolve * equal to NULL. */ if ((pIf->pCookie == NULL) && (pIf->if_resolve) && ((*pIf->if_resolve) (pIf, (struct in_addr *) &(SIN(dst)->sin_addr), desten, NULL) == 0)) return (1); /* If IFF_NOARP then make LL addr from IP host addr */ if (ac->ac_if.if_flags & IFF_NOARP) { /* Set expiration of Route/ARP entry */ if (rt->rt_expire == 0) { rt->rt_expire = tickGet (); } /* Set length of MAC address. Default to Ethernet length. */ alen = (sdl->sdl_alen > 0 ? sdl->sdl_alen : sizeof (struct ether_addr)); if (alen < 3) { return (0); } bcopy((caddr_t)ac->ac_enaddr, (char *)desten, alen - 3); lna = in_lnaof(SIN(dst)->sin_addr); desten[alen - 1] = lna & 0xff; desten[alen - 1 - 1] = (lna >> 8) & 0xff; desten[alen - 1 - 2] = (lna >> 16) & 0x7f; return (1); } /* * There is an arptab entry, but no ethernet address * response yet. Replace the held mbuf with this * latest one. */ if (la->la_hold) m_freem(la->la_hold); la->la_hold = m; if (rt->rt_expire) { rt->rt_flags &= ~RTF_REJECT; if (arpRxmitTicks < 0) arpRxmitTicks = ARP_RXMIT_TICKS_DFLT; if (la->la_asked == 0 || (tickGet () - rt->rt_expire >= arpRxmitTicks)) { rt->rt_expire = tickGet(); if (la->la_asked++ < arp_maxtries) arpwhohas(ac, &(SIN(dst)->sin_addr)); else { rt->rt_flags |= RTF_REJECT; rt->rt_expire += (sysClkRateGet() * arpt_down); la->la_asked = 0; } } } return (0);}/* * Common length and type checks are done here, * then the protocol-specific routine is called. */#ifdef VIRTUAL_STACKvoid arpintr ( int stackNum )#elsevoid arpintr()#endif /* VIRTUAL_STACK */ { register struct mbuf *m; register struct arphdr *ar; int s;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_VERBOSE, 10, 20, WV_NETEVENT_ARPINTR_START)#endif /* INCLUDE_WVNET */#endif#ifdef VIRTUAL_STACK /* Set the correct virtual stack context for the input processing. */ virtualStackNumTaskIdSet (stackNum);#endif /* VIRTUAL_STACK */ s = splnet (); while (arpintrq.ifq_head) { IF_DEQUEUE (&arpintrq, m); if (m == 0 || (m->m_flags & M_PKTHDR) == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_EMERGENCY event */ WV_NET_EVENT_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 4, 4, WV_NETEVENT_ARPINTR_FAIL, WV_NET_RECV)#endif /* INCLUDE_WVNET */#endif panic("arpintr"); }#ifdef VIRTUAL_STACK /* * (tNetTask) Set the virtual stack ID so the received * packet will be processed by the correct stack. */ virtualStackNumTaskIdSet(m->m_pkthdr.rcvif->vsNum);#endif /* VIRTUAL_STACK */ if (m->m_len >= sizeof(struct arphdr) && (ar = mtod(m, struct arphdr *)) && ntohs(ar->ar_hrd) == ARPHRD_ETHER && m->m_len >= sizeof(struct arphdr) + 2 * (ar->ar_hln + ar->ar_pln)) { switch (ntohs(ar->ar_pro)) { case ETHERTYPE_IP: case ETHERTYPE_IPTRAILERS:#ifdef PROXY_HOOK if (proxyArpHook == NULL || (* proxyArpHook) ( (struct arpcom *)m->m_pkthdr.rcvif, m) == FALSE)#endif in_arpinput(m); continue; } } m_freem(m); } splx (s); }/* * ARP for Internet protocols on 10 Mb/s Ethernet. * Algorithm is that given in RFC 826.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -