Exemplo n.º 1
0
/* 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;
}
Exemplo n.º 2
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);
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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);
}
Exemplo n.º 8
0
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
}
Exemplo n.º 9
0
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);
}
Exemplo n.º 10
0
Arquivo: fddi.c Projeto: 274914765/C
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);
    }
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
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);
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
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);
  }
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
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;
	}
}
Exemplo n.º 17
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);
}
Exemplo n.º 18
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 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;
}
Exemplo n.º 19
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;
}
Exemplo n.º 20
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;
}
Exemplo n.º 21
0
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);
    }
}
Exemplo n.º 22
0
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;
}
Exemplo n.º 23
0
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;
}
Exemplo n.º 24
0
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;
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
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, &ethaddr);
  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;
}
Exemplo n.º 27
0
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;
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
0
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);
}
Exemplo n.º 30
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, &notify);

      /* 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(&notify, &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;
}