void slirp_input(const uint8_t *pkt, int pkt_len) { struct mbuf *m; int proto; if (pkt_len < ETH_HLEN) return; proto = (pkt[12] << 8) | pkt[13]; switch(proto) { case ETH_P_ARP: arp_input(pkt, pkt_len); break; case ETH_P_IP: m = m_get(); if (!m) return; /* Note: we add to align the IP header */ m->m_len = pkt_len + 2; memcpy(m->m_data + 2, pkt, pkt_len); m->m_data += 2 + ETH_HLEN; m->m_len -= 2 + ETH_HLEN; ip_input(m); break; default: break; } }
void slirp_input(const uint8_t *pkt, int pkt_len) { struct mbuf *m; int proto; if (pkt_len < ETH_HLEN) return; proto = ntohs(*(uint16_t *)(pkt + 12)); switch(proto) { case ETH_P_ARP: arp_input(pkt, pkt_len); break; case ETH_P_IP: m = m_get(); if (!m) return; if (M_FREEROOM(m) < pkt_len + 2) { m_inc(m, pkt_len + 2); } m->m_len = pkt_len + 2; memcpy(m->m_data + 2, pkt, pkt_len); m->m_data += 2 + ETH_HLEN; m->m_len -= 2 + ETH_HLEN; ip_input(m); break; default: break; } }
int ethernet_input(cbuf *buf, ifnet *i) { int err; ethernet2_header *e2_head; uint16 type; if(cbuf_get_len(buf) < MIN_ETHERNET2_LEN) { cbuf_free_chain(buf); return -1; } e2_head = cbuf_get_ptr(buf, 0); type = ntohs(e2_head->type); dump_ethernet_header(e2_head); // strip out the ethernet header buf = cbuf_truncate_head(buf, sizeof(ethernet2_header), true); switch(type) { case PROT_TYPE_IPV4: err = ipv4_input(buf, i); break; case PROT_TYPE_ARP: err = arp_input(buf, i); break; default: dprintf("ethernet_receive: unknown ethernet type 0x%x\n", type); err = -1; } return err; }
int ether_input(struct nm_if *nmif, int ring, char *buf, int len) { int err; struct ether_header *eh; struct ether_vlan_header *evl; struct nm_if_vlan *vlan; if (len < ETHER_HDR_LEN) { DPRINTF("%s: discarding packet, too short.\n", __func__); pktcnt.rx_drop++; return (-1); } err = 0; eh = (struct ether_header *)buf; switch (ntohs(eh->ether_type)) { case ETHERTYPE_ARP: pktcnt.rx_arp++; err = arp_input(nmif, ring, buf + ETHER_HDR_LEN, len - ETHER_HDR_LEN); break; case ETHERTYPE_IP: pktcnt.rx_ip++; err = ip_input(nmif, ring, buf + ETHER_HDR_LEN, len - ETHER_HDR_LEN); break; case ETHERTYPE_VLAN: //pktcnt.rx_vlan++; if (len < ETHER_VLAN_ENCAP_LEN) { DPRINTF("%s: discarding vlan packet, too short.\n", __func__); pktcnt.rx_drop++; return (-1); } evl = (struct ether_vlan_header *)buf; vlan = if_find_vlan(nmif, ntohs(evl->evl_tag)); if (vlan == NULL) { pktcnt.rx_drop++; DPRINTF("%s: unknown vlan tag %d, discanding packet.\n", __func__, ntohs(evl->evl_tag)); return (-1); } memmove(buf + ETHER_VLAN_ENCAP_LEN, buf, ETHER_ADDR_LEN * 2); err = ether_input(vlan->nmif, ring, buf + ETHER_VLAN_ENCAP_LEN, len - ETHER_VLAN_ENCAP_LEN); if (!nohostring && err == 1) { memmove(buf, buf + ETHER_VLAN_ENCAP_LEN, ETHER_ADDR_LEN * 2); evl = (struct ether_vlan_header *)buf; evl->evl_encap_proto = htons(ETHERTYPE_VLAN); evl->evl_tag = htons(vlan->nmif->nm_if_vtag); ether_bridge(vlan->nmif, ring, buf, len); return (0); } break; default: pktcnt.rx_drop++; DPRINTF("%s: protocol %#04x not supported, discanding packet.\n", __func__, ntohs(eh->ether_type)); err = -1; } return (err); }