/* Rebuild the MyriNet MAC header. This is called after an ARP * (or in future other address resolution) has completed on this * sk_buff. We now let ARP fill in the other fields. */ static int myri_rebuild_header(struct sk_buff *skb) { unsigned char *pad = (unsigned char *) skb->data; struct ethhdr *eth = (struct ethhdr *) (pad + MYRI_PAD_LEN); struct net_device *dev = skb->dev; #ifdef DEBUG_HEADER DHDR(("myri_rebuild_header: pad[%02x,%02x] ", pad[0], pad[1])); dump_ehdr(eth); #endif /* Refill MyriNet padding identifiers, this is just being anal. */ pad[0] = MYRI_PAD_LEN; pad[1] = 0xab; switch (eth->h_proto) { #ifdef CONFIG_INET case cpu_to_be16(ETH_P_IP): return arp_find(eth->h_dest, skb); #endif default: printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n", dev->name, (int)eth->h_proto); memcpy(eth->h_source, dev->dev_addr, dev->addr_len); return 0; break; } return 0; }
int ip2xinet_rebuild_header(struct sk_buff *skb) { struct ethhdr *eth = (struct ethhdr *) (skb->data); // return arp_find(&(eth->h_dest),skb); return arp_find(eth->h_dest, skb); }
int main(int argc, char *argv[]) { extern char *optarg; extern int optind; char pcap_ebuf[PCAP_ERRBUF_SIZE]; char libnet_ebuf[LIBNET_ERRBUF_SIZE]; int c; intf = NULL; spoof_ip = target_ip = 0; while ((c = getopt(argc, argv, "i:t:h?V")) != -1) { switch (c) { case 'i': intf = optarg; break; case 't': if ((target_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1) usage(); break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); if ((spoof_ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) usage(); if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL) errx(1, "%s", pcap_ebuf); if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL) errx(1, "%s", libnet_ebuf); if (target_ip != 0 && !arp_find(target_ip, &target_mac)) errx(1, "couldn't arp for host %s", libnet_addr2name4(target_ip, LIBNET_DONT_RESOLVE)); signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGTERM, cleanup); for (;;) { arp_send(l, ARPOP_REPLY, NULL, spoof_ip, (target_ip ? (u_int8_t *)&target_mac : NULL), target_ip); sleep(2); } /* NOTREACHED */ exit(0); }
static int arp_find_all() { struct host *target = hosts; while(target->ip) { if (arp_find(target->ip, &target->mac)) { return 1; } target++; } return 0; }
int eth_rebuild_header (void *buff, struct device *dev) { struct enet_header *eth; eth = buff; if (arp_find(eth->daddr, *(unsigned long*)eth->daddr, dev, *(unsigned long *)eth->saddr)) return (1); memcpy (eth->saddr, dev->dev_addr, dev->addr_len); return (0); }
static int fwnet_header_rebuild(struct sk_buff *skb) { struct fwnet_header *h = (struct fwnet_header *)skb->data; if (get_unaligned_be16(&h->h_proto) == ETH_P_IP) return arp_find((unsigned char *)&h->h_dest, skb); dev_notice(&skb->dev->dev, "unable to resolve type %04x addresses\n", be16_to_cpu(h->h_proto)); return 0; }
static int hippi_rebuild_header(struct sk_buff *skb) { struct hippi_hdr *hip = (struct hippi_hdr *)skb->data; if(hip->snap.ethertype != htons(ETH_P_IP)) { printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype)); return 0; } return arp_find(hip->le.daddr, skb); }
int fc_rebuild_header(struct sk_buff *skb) { struct fch_hdr *fch=(struct fch_hdr *)skb->data; struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr)); if(fcllc->ethertype != htons(ETH_P_IP)) { printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons(fcllc->ethertype)); return 0; } #ifdef CONFIG_INET return arp_find(fch->daddr, skb); #else return 0; #endif }
static void cleanup(int sig) { int i; int rounds = (cleanup_src_own*5 + cleanup_src_host*5); fprintf(stderr, "Cleaning up and re-arping targets...\n"); for (i = 0; i < rounds; i++) { struct host *target = hosts; for(;target->ip;target++) { uint8_t *src_ha = NULL; if (!(target->flags & HOST_TARGET)) continue; if (!(target->flags & HOST_ACTIVE)) continue; struct host *model = hosts; for(;model->ip;model++) { if (!(model->flags & HOST_ACTIVE)) continue; int fw = arp_find(target->ip, &target->mac); int bw = poison_reverse; if (!(model->flags & HOST_MODEL)) continue; if (cleanup_src_own && (i%2 || !cleanup_src_host)) { src_ha = my_ha; } /* XXX - on BSD, requires ETHERSPOOF kernel. */ if (fw) { arp_send(l, ARPOP_REPLY, (u_int8_t *)&model->mac, model->ip, (target->ip ? (u_int8_t *)&target->mac : brd_ha), target->ip, src_ha); /* we have to wait a moment before sending the next packet */ usleep(ARP_PAUSE); } if (bw) { arp_send(l, ARPOP_REPLY, (u_int8_t *)&target->mac, target->ip, (u_int8_t *)&model->mac, model->ip, src_ha); usleep(ARP_PAUSE); } } } } exit(0); }
static int fddi_rebuild_header(struct sk_buff *skb) { struct fddihdr *fddi = (struct fddihdr *)skb->data; #ifdef CONFIG_INET if (fddi->hdr.llc_snap.ethertype == htons(ETH_P_IP)) /* Try to get ARP to resolve the header and fill destination address */ return arp_find(fddi->daddr, skb); else #endif { printk("%s: Don't know how to resolve type %04X addresses.\n", skb->dev->name, ntohs(fddi->hdr.llc_snap.ethertype)); return(0); } }
/** * eth_rebuild_header- rebuild the Ethernet MAC header. * @skb: socket buffer to update * * This is called after an ARP or IPV6 ndisc it's resolution on this * sk_buff. We now let protocol (ARP) fill in the other fields. * * This routine CANNOT use cached dst->neigh! * Really, it is used only when dst->neigh is wrong. */ int eth_rebuild_header(struct sk_buff *skb) { struct ethhdr *eth = (struct ethhdr *)skb->data; struct net_device *dev = skb->dev; switch (eth->h_proto) { #ifdef CONFIG_INET case __constant_htons(ETH_P_IP): return arp_find(eth->h_dest, skb); #endif default: memcpy(eth->h_source, dev->dev_addr, dev->addr_len); break; } return 0; }
static void cleanup(int sig) { int i; if (arp_find(spoof_ip, &spoof_mac)) { for (i = 0; i < 3; i++) { /* XXX - on BSD, requires ETHERSPOOF kernel. */ arp_send(l, ARPOP_REPLY, (u_int8_t *)&spoof_mac, spoof_ip, (target_ip ? (u_int8_t *)&target_mac : NULL), target_ip); sleep(1); } } exit(0); }
/* Rebuild the Ethernet MAC header. */ int eth_rebuild_header(void *buff, struct device *dev) { struct ethhdr *eth; unsigned long src, dst; DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n")); eth = (struct ethhdr *) buff; src = *(unsigned long *) eth->h_source; dst = *(unsigned long *) eth->h_dest; DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src))); DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst))); if(eth->h_proto!=htons(ETH_P_ARP)) /* This ntohs kind of helps a bit! */ if (arp_find(eth->h_dest, dst, dev, dev->pa_addr /* src */)) return(1); memcpy(eth->h_source, dev->dev_addr, dev->addr_len); return(0); }
/* 构建以太网头部的回调函数 */ int eth_header(unsigned char *buff, struct device *dev, unsigned short type, unsigned long daddr, unsigned long saddr, unsigned len) { struct ethhdr *eth; DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr))); DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type)); /* Fill in the basic Ethernet MAC header. */ eth = (struct ethhdr *) buff; eth->h_proto = htons(type); /* We don't ARP for the LOOPBACK device... */ if (dev->flags & IFF_LOOPBACK) { DPRINTF((DBG_DEV, "ETH: No header for loopback\n")); memcpy(eth->h_source, dev->dev_addr, dev->addr_len); memset(eth->h_dest, 0, dev->addr_len); return(dev->hard_header_len); } /* Check if we can use the MAC BROADCAST address. */ if (chk_addr(daddr) == IS_BROADCAST) { DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n")); memcpy(eth->h_source, dev->dev_addr, dev->addr_len); memcpy(eth->h_dest, dev->broadcast, dev->addr_len); return(dev->hard_header_len); } cli(); memcpy(eth->h_source, &saddr, 4); /* No. Ask ARP to resolve the Ethernet address. */ if (arp_find(eth->h_dest, daddr, dev, dev->pa_addr)) { sti(); if(type!=ETH_P_IP) printk("Erk: protocol %X got into an arp request state!\n",type); return(-dev->hard_header_len); } else { memcpy(eth->h_source,dev->dev_addr,dev->addr_len); /* This was missing causing chaos if the header built correctly! */ sti(); return(dev->hard_header_len); } }
static int nr_rebuild_header(struct sk_buff *skb) { unsigned char *bp = skb->data; if (arp_find(bp + 7, skb)) return 1; bp[6] &= ~AX25_CBIT; bp[6] &= ~AX25_EBIT; bp[6] |= AX25_SSSID_SPARE; bp += AX25_ADDR_LEN; bp[6] &= ~AX25_CBIT; bp[6] |= AX25_EBIT; bp[6] |= AX25_SSSID_SPARE; return 0; }
int tr_rebuild_header(void *buff, struct device *dev, unsigned long dest, struct sk_buff *skb) { struct trh_hdr *trh=(struct trh_hdr *)buff; struct trllc *trllc=(struct trllc *)(buff+sizeof(struct trh_hdr)); if(trllc->ethertype != htons(ETH_P_IP)) { printk("tr_rebuild_header: Don't know how to resolve type %04X addresses ?\n",(unsigned int)htons( trllc->ethertype)); return 0; } if(arp_find(trh->daddr, dest, dev, dev->pa_addr, skb)) { return 1; } else { tr_source_route(trh,dev); return 0; } }
static int hippi_rebuild_header(struct sk_buff *skb) { struct hippi_hdr *hip = (struct hippi_hdr *)skb->data; /* * Only IP is currently supported */ if(hip->snap.ethertype != htons(ETH_P_IP)) { printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype)); return 0; } /* * We don't support dynamic ARP on HIPPI, but we use the ARP * static ARP tables to hold the I-FIELDs. */ return arp_find(hip->le.daddr, skb); }
/** * eth_rebuild_header- rebuild the Ethernet MAC header. * @skb: socket buffer to update * * This is called after an ARP or IPV6 ndisc it's resolution on this * sk_buff. We now let protocol (ARP) fill in the other fields. * * This routine CANNOT use cached dst->neigh! * Really, it is used only when dst->neigh is wrong. */ int eth_rebuild_header(struct sk_buff *skb) { struct ethhdr *eth = (struct ethhdr *)skb->data; struct net_device *dev = skb->dev; switch (eth->h_proto) { #ifdef CONFIG_INET case htons(ETH_P_IP): return arp_find(eth->h_dest, skb); #endif default: printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n", dev->name, ntohs(eth->h_proto)); memcpy(eth->h_source, dev->dev_addr, ETH_ALEN); break; } return 0; }
/* * Rebuild the Ethernet MAC header. This is called after an ARP * (or in future other address resolution) has completed on this * sk_buff. We now let ARP fill in the other fields. * * This routine CANNOT use cached dst->neigh! * Really, it is used only when dst->neigh is wrong. * * TODO: This needs a checkup, I'm ignorant here. --BLG */ static int vlan_dev_rebuild_header(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); switch (veth->h_vlan_encapsulated_proto) { #ifdef CONFIG_INET case htons(ETH_P_IP): /* TODO: Confirm this will work with VLAN headers... */ return arp_find(veth->h_dest, skb); #endif default: pr_debug("%s: unable to resolve type %X addresses.\n", dev->name, ntohs(veth->h_vlan_encapsulated_proto)); memcpy(veth->h_source, dev->dev_addr, ETH_ALEN); break; } return 0; }
static int rose_rebuild_header(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct net_device_stats *stats = netdev_priv(dev); unsigned char *bp = (unsigned char *)skb->data; struct sk_buff *skbn; unsigned int len; #ifdef CONFIG_INET if (arp_find(bp + 7, skb)) { return 1; } if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { kfree_skb(skb); return 1; } if (skb->sk != NULL) skb_set_owner_w(skbn, skb->sk); kfree_skb(skb); len = skbn->len; if (!rose_route_frame(skbn, NULL)) { kfree_skb(skbn); stats->tx_errors++; return 1; } stats->tx_packets++; stats->tx_bytes += len; #endif return 1; }
int eth_hard_header (unsigned char *buff, struct device *dev, unsigned short type, unsigned long daddr, unsigned long saddr, unsigned len) { struct enet_header *eth; eth = (struct enet_header *)buff; eth->type = net16(type); memcpy (eth->saddr, dev->dev_addr, dev->addr_len); if (daddr == 0) { memset (eth->daddr, 0xff, dev->addr_len); return (14); } if (!arp_find (eth->daddr, daddr, dev, saddr)) { return (14); } else { *(unsigned long *)eth->saddr = saddr; return (-14); } }
int ax25_rebuild_header(struct sk_buff *skb) { struct sk_buff *ourskb; unsigned char *bp = skb->data; ax25_route *route; struct net_device *dev = NULL; ax25_address *src, *dst; ax25_digi *digipeat = NULL; ax25_dev *ax25_dev; ax25_cb *ax25; char ip_mode = ' '; dst = (ax25_address *)(bp + 1); src = (ax25_address *)(bp + 8); if (arp_find(bp + 1, skb)) return 1; route = ax25_get_route(dst, NULL); if (route) { digipeat = route->digipeat; dev = route->dev; ip_mode = route->ip_mode; } if (dev == NULL) dev = skb->dev; if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) { goto put; } if (bp[16] == AX25_P_IP) { if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) { /* * We copy the buffer and release the original thereby * keeping it straight * * Note: we report 1 back so the caller will * not feed the frame direct to the physical device * We don't want that to happen. (It won't be upset * as we have pulled the frame from the queue by * freeing it). * * NB: TCP modifies buffers that are still * on a device queue, thus we use skb_copy() * instead of using skb_clone() unless this * gets fixed. */ ax25_address src_c; ax25_address dst_c; if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) { kfree_skb(skb); goto put; } if (skb->sk != NULL) skb_set_owner_w(ourskb, skb->sk); kfree_skb(skb); /* dl9sau: bugfix * after kfree_skb(), dst and src which were pointer * to bp which is part of skb->data would not be valid * anymore hope that after skb_pull(ourskb, ..) our * dsc_c and src_c will not become invalid */ bp = ourskb->data; dst_c = *(ax25_address *)(bp + 1); src_c = *(ax25_address *)(bp + 8); skb_pull(ourskb, AX25_HEADER_LEN - 1); /* Keep PID */ skb_reset_network_header(ourskb); ax25=ax25_send_frame( ourskb, ax25_dev->values[AX25_VALUES_PACLEN], &src_c, &dst_c, digipeat, dev); if (ax25) { ax25_cb_put(ax25); } goto put; } } bp[7] &= ~AX25_CBIT; bp[7] &= ~AX25_EBIT; bp[7] |= AX25_SSSID_SPARE; bp[14] &= ~AX25_CBIT; bp[14] |= AX25_EBIT; bp[14] |= AX25_SSSID_SPARE; skb_pull(skb, AX25_KISS_HEADER_LEN); if (digipeat != NULL) { if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) { kfree_skb(skb); goto put; } skb = ourskb; } ax25_queue_xmit(skb, dev); put: if (route) ax25_put_route(route); return 1; }
static uint16_t send_interrupt(FAR struct uip_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { FAR struct uip_conn *conn = (FAR struct uip_conn*)pvconn; FAR struct socket *psock = (FAR struct socket *)pvpriv; nllvdbg("flags: %04x\n", flags); /* If this packet contains an acknowledgement, then update the count of * acknowledged bytes. */ if ((flags & UIP_ACKDATA) != 0) { FAR sq_entry_t *entry, *next; FAR struct uip_wrbuffer_s *segment; uint32_t ackno; ackno = uip_tcpgetsequence(TCPBUF->ackno); for (entry = sq_peek(&conn->unacked_q); entry; entry = next) { next = sq_next(entry); segment = (FAR struct uip_wrbuffer_s*)entry; if (segment->wb_seqno < ackno) { nllvdbg("ACK: acked=%d buflen=%d ackno=%d\n", segment->wb_seqno, segment->wb_nbytes, ackno); /* Segment was ACKed. Remove from ACK waiting queue */ sq_rem(entry, &conn->unacked_q); /* Return the write buffer to the pool of free buffers */ uip_tcpwrbuffer_release(segment); } } } /* Check for a loss of connection */ else if ((flags & (UIP_CLOSE | UIP_ABORT | UIP_TIMEDOUT)) != 0) { /* Report not connected */ nllvdbg("Lost connection\n"); net_lostconnection(psock, flags); goto end_wait; } /* Check if we are being asked to retransmit data */ else if ((flags & UIP_REXMIT) != 0) { sq_entry_t *entry; /* Put all segments that have been sent but not ACKed to write queue * again note, the un-ACKed segment is put at the first of the write_q, * so it can be sent as soon as possible. */ while ((entry = sq_remlast(&conn->unacked_q))) { struct uip_wrbuffer_s *segment = (struct uip_wrbuffer_s*)entry; if (segment->wb_nrtx >= UIP_MAXRTX) { //conn->unacked -= segment->wb_nbytes; /* Return the write buffer */ uip_tcpwrbuffer_release(segment); /* NOTE expired is different from un-ACKed, it is designed to * represent the number of segments that have been sent, * retransmitted, and un-ACKed, if expired is not zero, the * connection will be closed. * * field expired can only be updated at UIP_ESTABLISHED state */ conn->expired++; continue; } send_insert_seqment(segment, &conn->write_q); } } /* Check if the outgoing packet is available (it may have been claimed * by a sendto interrupt serving a different thread). */ if (dev->d_sndlen > 0) { /* Another thread has beat us sending data, wait for the next poll */ return flags; } /* We get here if (1) not all of the data has been ACKed, (2) we have been * asked to retransmit data, (3) the connection is still healthy, and (4) * the outgoing packet is available for our use. In this case, we are * now free to send more data to receiver -- UNLESS the buffer contains * unprocesed incoming data. In that event, we will have to wait for the * next polling cycle. */ if ((conn->tcpstateflags & UIP_ESTABLISHED) && (flags & (UIP_POLL | UIP_REXMIT)) && !(sq_empty(&conn->write_q))) { /* Check if the destination IP address is in the ARP table. If not, * then the send won't actually make it out... it will be replaced with * an ARP request. * * NOTE 1: This could be an expensive check if there are a lot of * entries in the ARP table. * * NOTE 2: If we are actually harvesting IP addresses on incoming IP * packets, then this check should not be necessary; the MAC mapping * should already be in the ARP table. */ #if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) if (arp_find(conn->ripaddr) != NULL) #endif { FAR struct uip_wrbuffer_s *segment; FAR void *sndbuf; size_t sndlen; /* Get the amount of data that we can send in the next packet */ segment = (FAR struct uip_wrbuffer_s *)sq_remfirst(&conn->write_q); if (segment) { sndbuf = segment->wb_buffer; sndlen = segment->wb_nbytes; DEBUGASSERT(sndlen <= uip_mss(conn)); /* REVISIT: There should be a check here to assure that we do * not excced the window (conn->winsize). */ /* Set the sequence number for this segment. NOTE: uIP * updates sndseq on receipt of ACK *before* this function * is called. In that case sndseq will point to the next * unacknowledged byte (which might have already been * sent). We will overwrite the value of sndseq here * before the packet is sent. */ if (segment->wb_nrtx == 0 && segment->wb_seqno == (unsigned)-1) { segment->wb_seqno = conn->isn + conn->sent; } uip_tcpsetsequence(conn->sndseq, segment->wb_seqno); /* Then set-up to send that amount of data. (this won't * actually happen until the polling cycle completes). */ uip_send(dev, sndbuf, sndlen); /* Remember how much data we send out now so that we know * when everything has been acknowledged. Just increment * the amount of data sent. This will be needed in * sequence* number calculations and we know that this is * not a re-transmission. Re-transmissions do not go through * this path. */ if (segment->wb_nrtx == 0) { conn->unacked += sndlen; conn->sent += sndlen; } /* Increment the retransmission counter before expiration. * NOTE we will not calculate the retransmission timer * (RTT) to save cpu cycles, each send_insert_seqment * segment will be retransmitted UIP_MAXRTX times in halt- * second interval before expiration. */ segment->wb_nrtx++; /* The segment is waiting for ACK again */ send_insert_seqment(segment, &conn->unacked_q); /* Only one data can be sent by low level driver at once, * tell the caller stop polling the other connection. */ flags &= ~UIP_POLL; } } } /* Continue waiting */ return flags; end_wait: /* Do not allow any further callbacks */ psock->s_sndcb->flags = 0; psock->s_sndcb->event = NULL; return flags; }
static int netdev_arp_ioctl(FAR struct socket *psock, int cmd, FAR struct arpreq *req) { int ret; /* Execute the command */ switch (cmd) { case SIOCSARP: /* Set an ARP mapping */ { if (req != NULL && req->arp_pa.sa_family == AF_INET && req->arp_ha.sa_family == ARPHRD_ETHER) { FAR struct sockaddr_in *addr = (FAR struct sockaddr_in *)&req->arp_pa; /* Update any existing ARP table entry for this protocol * address -OR- add a new ARP table entry if there is not. */ ret = arp_update(addr->sin_addr.s_addr, (FAR uint8_t *)req->arp_ha.sa_data); } else { ret = -EINVAL; } } break; case SIOCDARP: /* Delete an ARP mapping */ { if (req != NULL && req->arp_pa.sa_family == AF_INET) { FAR struct sockaddr_in *addr = (FAR struct sockaddr_in *)&req->arp_pa; /* Find the existing ARP table entry for this protocol address. */ FAR struct arp_entry_s *entry = arp_lookup(addr->sin_addr.s_addr); if (entry != NULL) { /* The ARP table is fixed size; an entry is deleted * by nullifying its protocol address. */ entry->at_ipaddr = 0; ret = OK; } else { ret = -ENOENT; } } else { ret = -EINVAL; } } break; case SIOCGARP: /* Get an ARP mapping */ { if (req != NULL && req->arp_pa.sa_family == AF_INET) { FAR struct sockaddr_in *addr = (FAR struct sockaddr_in *)&req->arp_pa; /* Get the hardware address from an existing ARP table entry * matching this protocol address. */ ret = arp_find(addr->sin_addr.s_addr, (FAR struct ether_addr *)req->arp_ha.sa_data); if (ret >= 0) { /* Return the mapped hardware address. */ req->arp_ha.sa_family = ARPHRD_ETHER; ret = OK; } } else { ret = -EINVAL; } } break; default: ret = -ENOTTY; break; } return ret; }
static uint16_t sendfile_interrupt(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s*)pvconn; FAR struct sendfile_s *pstate = (FAR struct sendfile_s *)pvpriv; int ret; nllvdbg("flags: %04x acked: %d sent: %d\n", flags, pstate->snd_acked, pstate->snd_sent); /* Check for a loss of connection */ if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0) { /* Report not connected */ nlldbg("Lost connection\n"); net_lostconnection(pstate->snd_sock, flags); pstate->snd_sent = -ENOTCONN; goto end_wait; } /* We get here if (1) not all of the data has been ACKed, (2) we have been * asked to retransmit data, (3) the connection is still healthy, and (4) * the outgoing packet is available for our use. In this case, we are * now free to send more data to receiver -- UNLESS the buffer contains * unprocessing incoming data. In that event, we will have to wait for the * next polling cycle. */ if ((flags & TCP_NEWDATA) == 0 && pstate->snd_sent < pstate->snd_flen) { /* Get the amount of data that we can send in the next packet */ uint32_t sndlen = pstate->snd_flen - pstate->snd_sent; if (sndlen > tcp_mss(conn)) { sndlen = tcp_mss(conn); } /* Check if we have "space" in the window */ if ((pstate->snd_sent - pstate->snd_acked + sndlen) < conn->winsize) { uint32_t seqno; /* Then set-up to send that amount of data. (this won't actually * happen until the polling cycle completes). */ ret = file_seek(pstate->snd_file, pstate->snd_foffset + pstate->snd_sent, SEEK_SET); if (ret < 0) { int errcode = errno; nlldbg("failed to lseek: %d\n", errcode); pstate->snd_sent = -errcode; goto end_wait; } ret = file_read(pstate->snd_file, dev->d_snddata, sndlen); if (ret < 0) { int errcode = errno; nlldbg("failed to read from input file: %d\n", errcode); pstate->snd_sent = -errcode; goto end_wait; } dev->d_sndlen = sndlen; /* Set the sequence number for this packet. NOTE: uIP updates * sndseq on recept of ACK *before* this function is called. In that * case sndseq will point to the next unacknowledge byte (which might * have already been sent). We will overwrite the value of sndseq * here before the packet is sent. */ seqno = pstate->snd_sent + pstate->snd_isn; nllvdbg("SEND: sndseq %08x->%08x len: %d\n", conn->sndseq, seqno, ret); tcp_setsequence(conn->sndseq, seqno); /* Check if the destination IP address is in the ARP table. If not, * then the send won't actually make it out... it will be replaced with * an ARP request. * * NOTE 1: This could be an expensive check if there are a lot of entries * in the ARP table. Hence, we only check on the first packet -- when * snd_sent is zero. * * NOTE 2: If we are actually harvesting IP addresses on incoming IP * packets, then this check should not be necessary; the MAC mapping * should already be in the ARP table in many cases. * * NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP * address mapping is already in the ARP table. */ #if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \ !defined(CONFIG_NET_ARP_SEND) if (pstate->snd_sent != 0 || arp_find(conn->ripaddr) != NULL) #endif { /* Update the amount of data sent (but not necessarily ACKed) */ pstate->snd_sent += sndlen; nllvdbg("pid: %d SEND: acked=%d sent=%d flen=%d\n", getpid(), pstate->snd_acked, pstate->snd_sent, pstate->snd_flen); } } else { nlldbg("Window full, wait for ack\n"); goto wait; } } #ifdef CONFIG_NET_SOCKOPTS /* All data has been send and we are just waiting for ACK or re-transmit * indications to complete the send. Check for a timeout. */ if (sendfile_timeout(pstate)) { /* Yes.. report the timeout */ nlldbg("SEND timeout\n"); pstate->snd_sent = -ETIMEDOUT; goto end_wait; } #endif /* CONFIG_NET_SOCKOPTS */ if (pstate->snd_sent >= pstate->snd_flen && pstate->snd_acked < pstate->snd_flen) { /* All data has been sent, but there are outstanding ACK's */ goto wait; } end_wait: /* Do not allow any further callbacks */ pstate->snd_datacb->flags = 0; pstate->snd_datacb->priv = NULL; pstate->snd_datacb->event = NULL; /* Wake up the waiting thread */ sem_post(&pstate->snd_sem); wait: return flags; }
void arp_out(FAR struct net_driver_s *dev) { struct ether_addr ethaddr; FAR struct eth_hdr_s *peth = ETHBUF; FAR struct arp_iphdr_s *pip = IPBUF; in_addr_t ipaddr; in_addr_t destipaddr; int ret; #if defined(CONFIG_NET_PKT) || defined(CONFIG_NET_ARP_SEND) /* Skip sending ARP requests when the frame to be transmitted was * written into a packet socket. */ if (IFF_IS_NOARP(dev->d_flags)) { /* Clear the indication and let the packet continue on its way. */ IFF_CLR_NOARP(dev->d_flags); return; } #endif /* Find the destination IP address in the ARP table and construct * the Ethernet header. If the destination IP address isn't on the * local network, we use the default router's IP address instead. * * If not ARP table entry is found, we overwrite the original IP * packet with an ARP request for the IP address. */ /* First check if destination is a local broadcast. */ if (net_ipv4addr_hdrcmp(pip->eh_destipaddr, g_broadcast_ipaddr)) { memcpy(peth->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); goto finish_header; } #ifdef CONFIG_NET_IGMP /* Check if the destination address is a multicast address * * - IPv4: multicast addresses lie in the class D group -- The address range * 224.0.0.0 to 239.255.255.255 (224.0.0.0/4) * * - IPv6 multicast addresses are have the high-order octet of the * addresses=0xff (ff00::/8.) */ if (NTOHS(pip->eh_destipaddr[0]) >= 0xe000 && NTOHS(pip->eh_destipaddr[0]) <= 0xefff) { /* Build the well-known IPv4 IGMP Ethernet address. The first * three bytes are fixed; the final three variable come from the * last three bytes of the IPv4 address (network order). * * Address range : 01:00:5e:00:00:00 to 01:00:5e:7f:ff:ff */ FAR const uint8_t *ip = (FAR uint8_t *)pip->eh_destipaddr; peth->dest[0] = g_multicast_ethaddr[0]; peth->dest[1] = g_multicast_ethaddr[1]; peth->dest[2] = g_multicast_ethaddr[2]; peth->dest[3] = ip[1] & 0x7f; peth->dest[4] = ip[2]; peth->dest[5] = ip[3]; goto finish_header; } #endif /* Check if the destination address is on the local network. */ destipaddr = net_ip4addr_conv32(pip->eh_destipaddr); if (!net_ipv4addr_maskcmp(destipaddr, dev->d_ipaddr, dev->d_netmask)) { /* Destination address is not on the local network */ #ifdef CONFIG_NET_ROUTE /* We have a routing table.. find the correct router to use in * this case (or, as a fall-back, use the device's default router * address). We will use the router IP address instead of the * destination address when determining the MAC address. */ netdev_ipv4_router(dev, destipaddr, &ipaddr); #else /* Use the device's default router IP address instead of the * destination address when determining the MAC address. */ net_ipv4addr_copy(ipaddr, dev->d_draddr); #endif } /* The destination address is on the local network. Check if it is * the sub-net broadcast address. */ else if (net_ipv4addr_broadcast(destipaddr, dev->d_netmask)) { /* Yes.. then we won't need to know the destination MAC address */ memcpy(peth->dest, g_broadcast_ethaddr.ether_addr_octet, ETHER_ADDR_LEN); goto finish_header; } else { /* Else, we use the destination IP address. */ net_ipv4addr_copy(ipaddr, destipaddr); } /* Check if we already have this destination address in the ARP table */ ret = arp_find(ipaddr, ðaddr); if (ret < 0) { ninfo("ARP request for IP %08lx\n", (unsigned long)ipaddr); /* The destination address was not in our ARP table, so we overwrite * the IP packet with an ARP request. */ arp_format(dev, ipaddr); arp_dump(ARPBUF); return; } /* Build an Ethernet header. */ memcpy(peth->dest, ethaddr.ether_addr_octet, ETHER_ADDR_LEN); /* Finish populating the Ethernet header */ finish_header: memcpy(peth->src, dev->d_mac.ether.ether_addr_octet, ETHER_ADDR_LEN); peth->type = HTONS(ETHTYPE_IP); dev->d_len += ETH_HDRLEN; }
int ax25_rebuild_header(struct sk_buff *skb) { struct sk_buff *ourskb; unsigned char *bp = skb->data; ax25_route *route; struct net_device *dev = NULL; ax25_address *src, *dst; ax25_digi *digipeat = NULL; ax25_dev *ax25_dev; ax25_cb *ax25; char ip_mode = ' '; dst = (ax25_address *)(bp + 1); src = (ax25_address *)(bp + 8); if (arp_find(bp + 1, skb)) return 1; route = ax25_get_route(dst, NULL); if (route) { digipeat = route->digipeat; dev = route->dev; ip_mode = route->ip_mode; } if (dev == NULL) dev = skb->dev; if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) { goto put; } if (bp[16] == AX25_P_IP) { if (ip_mode == 'V' || (ip_mode == ' ' && ax25_dev->values[AX25_VALUES_IPDEFMODE])) { ax25_address src_c; ax25_address dst_c; if ((ourskb = skb_copy(skb, GFP_ATOMIC)) == NULL) { kfree_skb(skb); goto put; } if (skb->sk != NULL) skb_set_owner_w(ourskb, skb->sk); kfree_skb(skb); bp = ourskb->data; dst_c = *(ax25_address *)(bp + 1); src_c = *(ax25_address *)(bp + 8); skb_pull(ourskb, AX25_HEADER_LEN - 1); skb_reset_network_header(ourskb); ax25=ax25_send_frame( ourskb, ax25_dev->values[AX25_VALUES_PACLEN], &src_c, &dst_c, digipeat, dev); if (ax25) { ax25_cb_put(ax25); } goto put; } } bp[7] &= ~AX25_CBIT; bp[7] &= ~AX25_EBIT; bp[7] |= AX25_SSSID_SPARE; bp[14] &= ~AX25_CBIT; bp[14] |= AX25_EBIT; bp[14] |= AX25_SSSID_SPARE; skb_pull(skb, AX25_KISS_HEADER_LEN); if (digipeat != NULL) { if ((ourskb = ax25_rt_build_path(skb, src, dst, route->digipeat)) == NULL) { kfree_skb(skb); goto put; } skb = ourskb; } ax25_queue_xmit(skb, dev); put: if (route) ax25_put_route(route); return 1; }
static uint16_t psock_send_interrupt(FAR struct net_driver_s *dev, FAR void *pvconn, FAR void *pvpriv, uint16_t flags) { FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)pvconn; FAR struct socket *psock = (FAR struct socket *)pvpriv; nllvdbg("flags: %04x\n", flags); /* If this packet contains an acknowledgement, then update the count of * acknowledged bytes. */ if ((flags & TCP_ACKDATA) != 0) { FAR struct tcp_wrbuffer_s *wrb; FAR sq_entry_t *entry; FAR sq_entry_t *next; uint32_t ackno; ackno = tcp_getsequence(TCPBUF->ackno); nllvdbg("ACK: ackno=%u flags=%04x\n", ackno, flags); /* Look at every write buffer in the unacked_q. The unacked_q * holds write buffers that have been entirely sent, but which * have not yet been ACKed. */ for (entry = sq_peek(&conn->unacked_q); entry; entry = next) { uint32_t lastseq; /* Check of some or all of this write buffer has been ACKed. */ next = sq_next(entry); wrb = (FAR struct tcp_wrbuffer_s*)entry; /* If the ACKed sequence number is greater than the start * sequence number of the write buffer, then some or all of * the write buffer has been ACKed. */ if (ackno > WRB_SEQNO(wrb)) { /* Get the sequence number at the end of the data */ lastseq = WRB_SEQNO(wrb) + WRB_PKTLEN(wrb); nllvdbg("ACK: wrb=%p seqno=%u lastseq=%u pktlen=%u ackno=%u\n", wrb, WRB_SEQNO(wrb), lastseq, WRB_PKTLEN(wrb), ackno); /* Has the entire buffer been ACKed? */ if (ackno >= lastseq) { nllvdbg("ACK: wrb=%p Freeing write buffer\n", wrb); /* Yes... Remove the write buffer from ACK waiting queue */ sq_rem(entry, &conn->unacked_q); /* And return the write buffer to the pool of free buffers */ tcp_wrbuffer_release(wrb); } else { unsigned int trimlen; /* No, then just trim the ACKed bytes from the beginning * of the write buffer. This will free up some I/O buffers * that can be reused while are still sending the last * buffers in the chain. */ trimlen = ackno - WRB_SEQNO(wrb); if (trimlen > WRB_SENT(wrb)) { /* More data has been ACKed then we have sent? */ trimlen = WRB_SENT(wrb); } nllvdbg("ACK: wrb=%p trim %u bytes\n", wrb, trimlen); WRB_TRIM(wrb, trimlen); WRB_SEQNO(wrb) = ackno; WRB_SENT(wrb) -= trimlen; /* Set the new sequence number for what remains */ nllvdbg("ACK: wrb=%p seqno=%u pktlen=%u\n", wrb, WRB_SEQNO(wrb), WRB_PKTLEN(wrb)); } } } /* A special case is the head of the write_q which may be partially * sent and so can still have un-ACKed bytes that could get ACKed * before the entire write buffer has even been sent. */ wrb = (FAR struct tcp_wrbuffer_s*)sq_peek(&conn->write_q); if (wrb && WRB_SENT(wrb) > 0 && ackno > WRB_SEQNO(wrb)) { uint32_t nacked; /* Number of bytes that were ACKed */ nacked = ackno - WRB_SEQNO(wrb); if (nacked > WRB_SENT(wrb)) { /* More data has been ACKed then we have sent? ASSERT? */ nacked = WRB_SENT(wrb); } nllvdbg("ACK: wrb=%p seqno=%u nacked=%u sent=%u ackno=%u\n", wrb, WRB_SEQNO(wrb), nacked, WRB_SENT(wrb), ackno); /* Trim the ACKed bytes from the beginning of the write buffer. */ WRB_TRIM(wrb, nacked); WRB_SEQNO(wrb) = ackno; WRB_SENT(wrb) -= nacked; nllvdbg("ACK: wrb=%p seqno=%u pktlen=%u sent=%u\n", wrb, WRB_SEQNO(wrb), WRB_PKTLEN(wrb), WRB_SENT(wrb)); } } /* Check for a loss of connection */ else if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0) { nllvdbg("Lost connection: %04x\n", flags); /* Report not connected */ net_lostconnection(psock, flags); /* Free write buffers and terminate polling */ psock_lost_connection(psock, conn); return flags; } /* Check if we are being asked to retransmit data */ else if ((flags & TCP_REXMIT) != 0) { FAR struct tcp_wrbuffer_s *wrb; FAR sq_entry_t *entry; nllvdbg("REXMIT: %04x\n", flags); /* If there is a partially sent write buffer at the head of the * write_q? Has anything been sent from that write buffer? */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); nllvdbg("REXMIT: wrb=%p sent=%u\n", wrb, wrb ? WRB_SENT(wrb) : 0); if (wrb != NULL && WRB_SENT(wrb) > 0) { FAR struct tcp_wrbuffer_s *tmp; uint16_t sent; /* Yes.. Reset the number of bytes sent sent from the write buffer */ sent = WRB_SENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; } else { conn->unacked = 0; } if (conn->sent > sent) { conn->sent -= sent; } else { conn->sent = 0; } WRB_SENT(wrb) = 0; nllvdbg("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", wrb, WRB_SENT(wrb), conn->unacked, conn->sent); /* Increment the retransmit count on this write buffer. */ if (++WRB_NRTX(wrb) >= TCP_MAXRTX) { nlldbg("Expiring wrb=%p nrtx=%u\n", wrb, WRB_NRTX(wrb)); /* The maximum retry count as been exhausted. Remove the write * buffer at the head of the queue. */ tmp = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&conn->write_q); DEBUGASSERT(tmp == wrb); UNUSED(tmp); /* And return the write buffer to the free list */ tcp_wrbuffer_release(wrb); /* NOTE expired is different from un-ACKed, it is designed to * represent the number of segments that have been sent, * retransmitted, and un-ACKed, if expired is not zero, the * connection will be closed. * * field expired can only be updated at TCP_ESTABLISHED state */ conn->expired++; } } /* Move all segments that have been sent but not ACKed to the write * queue again note, the un-ACKed segments are put at the head of the * write_q so they can be resent as soon as possible. */ while ((entry = sq_remlast(&conn->unacked_q)) != NULL) { wrb = (FAR struct tcp_wrbuffer_s*)entry; uint16_t sent; /* Reset the number of bytes sent sent from the write buffer */ sent = WRB_SENT(wrb); if (conn->unacked > sent) { conn->unacked -= sent; } else { conn->unacked = 0; } if (conn->sent > sent) { conn->sent -= sent; } else { conn->sent = 0; } WRB_SENT(wrb) = 0; nllvdbg("REXMIT: wrb=%p sent=%u, conn unacked=%d sent=%d\n", wrb, WRB_SENT(wrb), conn->unacked, conn->sent); /* Free any write buffers that have exceed the retry count */ if (++WRB_NRTX(wrb) >= TCP_MAXRTX) { nlldbg("Expiring wrb=%p nrtx=%u\n", wrb, WRB_NRTX(wrb)); /* Return the write buffer to the free list */ tcp_wrbuffer_release(wrb); /* NOTE expired is different from un-ACKed, it is designed to * represent the number of segments that have been sent, * retransmitted, and un-ACKed, if expired is not zero, the * connection will be closed. * * field expired can only be updated at TCP_ESTABLISHED state */ conn->expired++; continue; } else { /* Insert the write buffer into the write_q (in sequence * number order). The retransmission will occur below * when the write buffer with the lowest sequenc number * is pulled from the write_q again. */ nllvdbg("REXMIT: Moving wrb=%p nrtx=%u\n", wrb, WRB_NRTX(wrb)); psock_insert_segment(wrb, &conn->write_q); } } } /* Check if the outgoing packet is available (it may have been claimed * by a sendto interrupt serving a different thread). */ if (dev->d_sndlen > 0) { /* Another thread has beat us sending data, wait for the next poll */ return flags; } /* We get here if (1) not all of the data has been ACKed, (2) we have been * asked to retransmit data, (3) the connection is still healthy, and (4) * the outgoing packet is available for our use. In this case, we are * now free to send more data to receiver -- UNLESS the buffer contains * unprocessed incoming data. In that event, we will have to wait for the * next polling cycle. */ if ((conn->tcpstateflags & TCP_ESTABLISHED) && (flags & (TCP_POLL | TCP_REXMIT)) && !(sq_empty(&conn->write_q))) { /* Check if the destination IP address is in the ARP table. If not, * then the send won't actually make it out... it will be replaced with * an ARP request. * * NOTE 1: This could be an expensive check if there are a lot of * entries in the ARP table. * * NOTE 2: If we are actually harvesting IP addresses on incoming IP * packets, then this check should not be necessary; the MAC mapping * should already be in the ARP table in many cases. * * NOTE 3: If CONFIG_NET_ARP_SEND then we can be assured that the IP * address mapping is already in the ARP table. */ #if defined(CONFIG_NET_ETHERNET) && !defined(CONFIG_NET_ARP_IPIN) && \ !defined(CONFIG_NET_ARP_SEND) if (arp_find(conn->ripaddr) != NULL) #endif { FAR struct tcp_wrbuffer_s *wrb; size_t sndlen; /* Peek at the head of the write queue (but don't remove anything * from the write queue yet). We know from the above test that * the write_q is not empty. */ wrb = (FAR struct tcp_wrbuffer_s *)sq_peek(&conn->write_q); DEBUGASSERT(wrb); /* Get the amount of data that we can send in the next packet. * We will send either the remaining data in the buffer I/O * buffer chain, or as much as will fit given the MSS and current * window size. */ sndlen = WRB_PKTLEN(wrb) - WRB_SENT(wrb); if (sndlen > tcp_mss(conn)) { sndlen = tcp_mss(conn); } if (sndlen > conn->winsize) { sndlen = conn->winsize; } nllvdbg("SEND: wrb=%p pktlen=%u sent=%u sndlen=%u\n", wrb, WRB_PKTLEN(wrb), WRB_SENT(wrb), sndlen); /* Set the sequence number for this segment. If we are * retransmitting, then the sequence number will already * be set for this write buffer. */ if (WRB_SEQNO(wrb) == (unsigned)-1) { WRB_SEQNO(wrb) = conn->isn + conn->sent; } /* The TCP stack updates sndseq on receipt of ACK *before* * this function is called. In that case sndseq will point * to the next unacknowledged byte (which might have already * been sent). We will overwrite the value of sndseq here * before the packet is sent. */ tcp_setsequence(conn->sndseq, WRB_SEQNO(wrb) + WRB_SENT(wrb)); /* Then set-up to send that amount of data with the offset * corresponding to the amount of data already sent. (this * won't actually happen until the polling cycle completes). */ devif_iob_send(dev, WRB_IOB(wrb), sndlen, WRB_SENT(wrb)); /* Remember how much data we send out now so that we know * when everything has been acknowledged. Just increment * the amount of data sent. This will be needed in sequence * number calculations. */ conn->unacked += sndlen; conn->sent += sndlen; nllvdbg("SEND: wrb=%p nrtx=%u unacked=%u sent=%u\n", wrb, WRB_NRTX(wrb), conn->unacked, conn->sent); /* Increment the count of bytes sent from this write buffer */ WRB_SENT(wrb) += sndlen; nllvdbg("SEND: wrb=%p sent=%u pktlen=%u\n", wrb, WRB_SENT(wrb), WRB_PKTLEN(wrb)); /* Remove the write buffer from the write queue if the * last of the data has been sent from the buffer. */ DEBUGASSERT(WRB_SENT(wrb) <= WRB_PKTLEN(wrb)); if (WRB_SENT(wrb) >= WRB_PKTLEN(wrb)) { FAR struct tcp_wrbuffer_s *tmp; nllvdbg("SEND: wrb=%p Move to unacked_q\n", wrb); tmp = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&conn->write_q); DEBUGASSERT(tmp == wrb); UNUSED(tmp); /* Put the I/O buffer chain in the un-acked queue; the * segment is waiting for ACK again */ psock_insert_segment(wrb, &conn->unacked_q); } /* Only one data can be sent by low level driver at once, * tell the caller stop polling the other connection. */ flags &= ~TCP_POLL; } } /* Continue waiting */ return flags; }
int main(int argc, char *argv[]) { extern char *optarg; extern int optind; char pcap_ebuf[PCAP_ERRBUF_SIZE]; char libnet_ebuf[LIBNET_ERRBUF_SIZE]; int c; int n_scan_hosts = 0; char *scan_prefix = NULL; int scan_prefix_length = 32; char *cleanup_src = NULL; in_addr_t target_addr; intf = NULL; poison_reverse = 0; poison_mesh = 0; n_hosts = 0; /* allocate enough memory for target list */ hosts = calloc( argc+1, sizeof(struct host) ); while ((c = getopt(argc, argv, "vrmi:s:t:c:h?V")) != -1) { switch (c) { case 'v': verbose = 1; break; case 'i': intf = optarg; break; case 't': target_addr = libnet_name2addr4(l, optarg, LIBNET_RESOLVE); if (target_addr == -1) { usage(); } else { host_add(target_addr, HOST_TARGET); } break; case 'r': poison_reverse = 1; break; case 'm': poison_mesh = 1; break; case 's': scan_prefix = strchr(optarg, '/'); if (scan_prefix) { *scan_prefix = '\0'; scan_prefix_length = atoi(scan_prefix+1); if (scan_prefix_length < 0 || scan_prefix_length > 32) { usage(); } } n_scan_hosts += (1<<(32-scan_prefix_length)); /* we need some more memory to store the target data */ int mem = (argc+1 + n_scan_hosts) * sizeof(struct host); hosts = realloc( hosts, mem ); hosts[n_hosts].ip = (uint32_t)0; subnet_add(inet_addr(optarg), scan_prefix_length, HOST_TARGET); break; case 'c': cleanup_src = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (!cleanup_src || strcmp(cleanup_src, "own")==0) { /* default! */ /* only use our own hw address when cleaning up, * not jeopardizing any bridges on the way to our * target */ cleanup_src_own = 1; cleanup_src_host = 0; } else if (strcmp(cleanup_src, "host")==0) { /* only use the target hw address when cleaning up; * this can screw up some bridges and scramble access * for our own host, however it resets the arp table * more reliably */ cleanup_src_own = 0; cleanup_src_host = 1; } else if (strcmp(cleanup_src, "both")==0) { cleanup_src_own = 1; cleanup_src_host = 1; } else { errx(1, "Invalid parameter to -c: use 'own' (default), 'host' or 'both'."); usage(); } while (argc--) { if ((target_addr = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) { errx(1, "Invalid address: %s", argv[0]); usage(); } host_add(target_addr, HOST_MODEL); argv++; } if (poison_mesh) { struct host *host = hosts; for(;host->ip; host++) { host->flags |= (HOST_TARGET|HOST_MODEL); } } if (poison_reverse && active_targets() <= 0) { errx(1, "Spoofing the reverse path (-r) is only available when specifying at least one target (-t/-s)."); usage(); } if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL) errx(1, "%s", pcap_ebuf); if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL) errx(1, "%s", libnet_ebuf); fprintf(stderr, "Scanning %d hw addresses...\n", n_hosts); struct host *target = hosts; for (; target->ip; target++) { if (verbose) { fprintf(stderr, "Looking up host %s...\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); } int arp_status = arp_find(target->ip, &target->mac); if (arp_status && /* just make sure we are not getting an empty or broadcast address */ (memcmp(&target->mac, zero_ha, sizeof(struct ether_addr)) != 0) && (memcmp(&target->mac, brd_ha, sizeof(struct ether_addr)) != 0)) { target->flags |= HOST_ACTIVE; if (target->flags & HOST_SUBNET) { fprintf(stderr, "Found host in subnet %s: %s\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE), ether_ntoa((struct ether_addr *)&target->mac)); } } else { target->flags &= (~HOST_ACTIVE); if (! (target->flags & HOST_SUBNET)) { fprintf(stderr, "Unable to find specified host %s\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); } if (poison_reverse && target->flags & HOST_MODEL) { errx(1, "couldn't arp for spoof host %s", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); usage(); } } } if ((my_ha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) { errx(1, "Unable to determine own mac address"); } if (active_targets() == 0) { errx(1, "No target hosts found."); } signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGTERM, cleanup); fprintf(stderr, "Starting spoofing process...\n"); for (;;) { struct host *target = hosts; for(;target->ip; target++) { if (!(target->flags & HOST_TARGET)) continue; if (!(target->flags & HOST_ACTIVE)) continue; struct host *model = hosts; for (;model->ip; model++) { if (!(model->flags & HOST_ACTIVE)) continue; if (!(model->flags & HOST_MODEL)) continue; if (target->ip != model->ip) { arp_send(l, ARPOP_REPLY, my_ha, model->ip, (target->ip ? (u_int8_t *)&target->mac : brd_ha), target->ip, my_ha); usleep(ARP_PAUSE); if (poison_reverse) { arp_send(l, ARPOP_REPLY, my_ha, target->ip, (uint8_t *)&model->mac, model->ip, my_ha); usleep(ARP_PAUSE); } } } } sleep(2); } /* NOTREACHED */ exit(0); }
int arp_send(in_addr_t ipaddr) { FAR struct net_driver_s *dev; struct arp_notify_s notify; struct timespec delay; struct arp_send_s state; int ret; /* First check if destination is a local broadcast. */ if (ipaddr == INADDR_BROADCAST) { /* We don't need to send the ARP request */ return OK; } #ifdef CONFIG_NET_IGMP /* Check if the destination address is a multicast address * * - IPv4: multicast addresses lie in the class D group -- The address range * 224.0.0.0 to 239.255.255.255 (224.0.0.0/4) * * - IPv6 multicast addresses are have the high-order octet of the * addresses=0xff (ff00::/8.) */ if (NTOHL(ipaddr) >= 0xe0000000 && NTOHL(ipaddr) <= 0xefffffff) { /* We don't need to send the ARP request */ return OK; } #endif /* Get the device that can route this request */ dev = netdev_findby_ipv4addr(INADDR_ANY, ipaddr); if (!dev) { nerr("ERROR: Unreachable: %08lx\n", (unsigned long)ipaddr); ret = -EHOSTUNREACH; goto errout; } /* ARP support is only built if the Ethernet data link is supported. * Continue and send the ARP request only if this device uses the * Ethernet data link protocol. */ if (dev->d_lltype != NET_LL_ETHERNET) { return OK; } /* Check if the destination address is on the local network. */ if (!net_ipv4addr_maskcmp(ipaddr, dev->d_ipaddr, dev->d_netmask)) { in_addr_t dripaddr; /* Destination address is not on the local network */ #ifdef CONFIG_NET_ROUTE /* We have a routing table.. find the correct router to use in * this case (or, as a fall-back, use the device's default router * address). We will use the router IP address instead of the * destination address when determining the MAC address. */ netdev_ipv4_router(dev, ipaddr, &dripaddr); #else /* Use the device's default router IP address instead of the * destination address when determining the MAC address. */ net_ipv4addr_copy(dripaddr, dev->d_draddr); #endif ipaddr = dripaddr; } /* The destination address is on the local network. Check if it is * the sub-net broadcast address. */ else if (net_ipv4addr_broadcast(ipaddr, dev->d_netmask)) { /* Yes.. We don't need to send the ARP request */ return OK; } /* Allocate resources to receive a callback. This and the following * initialization is performed with the network lock because we don't * want anything to happen until we are ready. */ net_lock(); state.snd_cb = arp_callback_alloc(dev); if (!state.snd_cb) { nerr("ERROR: Failed to allocate a callback\n"); ret = -ENOMEM; goto errout_with_lock; } /* This semaphore is used for signaling and, hence, should not have * priority inheritance enabled. */ (void)nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */ nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE); state.snd_retries = 0; /* No retries yet */ state.snd_ipaddr = ipaddr; /* IP address to query */ /* Remember the routing device name */ strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname, IFNAMSIZ); /* Now loop, testing if the address mapping is in the ARP table and re- * sending the ARP request if it is not. */ ret = -ETIMEDOUT; /* Assume a timeout failure */ while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES) { /* Check if the address mapping is present in the ARP table. This * is only really meaningful on the first time through the loop. * * NOTE: If the ARP table is large than this could be a performance * issue. */ if (arp_find(ipaddr, NULL) >= 0) { /* We have it! Break out with success */ ret = OK; break; } /* Set up the ARP response wait BEFORE we send the ARP request */ arp_wait_setup(ipaddr, ¬ify); /* Arm/re-arm the callback */ state.snd_sent = false; state.snd_result = -EBUSY; state.snd_cb->flags = (ARP_POLL | NETDEV_DOWN); state.snd_cb->priv = (FAR void *)&state; state.snd_cb->event = arp_send_eventhandler; /* Notify the device driver that new TX data is available. * NOTES: This is in essence what netdev_ipv4_txnotify() does, which * is not possible to call since it expects a in_addr_t as * its single argument to lookup the network interface. */ if (dev->d_txavail) { dev->d_txavail(dev); } /* Wait for the send to complete or an error to occur. * net_lockedwait will also terminate if a signal is received. */ do { (void)net_lockedwait(&state.snd_sem); } while (!state.snd_sent); /* Check the result of the send operation */ ret = state.snd_result; if (ret < 0) { /* Break out on a send failure */ nerr("ERROR: Send failed: %d\n", ret); break; } /* Now wait for response to the ARP response to be received. The * optimal delay would be the work case round trip time. * NOTE: The network is locked. */ delay.tv_sec = CONFIG_ARP_SEND_DELAYSEC; delay.tv_nsec = CONFIG_ARP_SEND_DELAYNSEC; ret = arp_wait(¬ify, &delay); /* arp_wait will return OK if and only if the matching ARP response * is received. Otherwise, it will return -ETIMEDOUT. */ if (ret >= OK) { /* Break out if arp_wait() fails */ break; } /* Increment the retry count */ state.snd_retries++; nerr("ERROR: arp_wait failed: %d\n", ret); } nxsem_destroy(&state.snd_sem); arp_callback_free(dev, state.snd_cb); errout_with_lock: net_unlock(); errout: return ret; }