Beispiel #1
0
static u08 ip_receive_packet( ip_header * p, u16 len )
{
//	log_printf( "ip: got ip packet, proto=%d\n", p->proto );

	if (!__ip_validate_header( p ))
	{
		log_printf( "ip: bad ip checksum\n" );
		return 1;
	}

	switch( p->proto )
	{
	case IPPROTO_ICMP: return icmp_receive_packet( p, len );
	case IPPROTO_UDP: return udp_receive_packet( p, len );
	case IPPROTO_TCP: return tcp_receive_packet( p, len );
	}

	return 1;		// did we eat it? yes we did...
}
Beispiel #2
0
int32 udp_receive (DEVICE *dptr, int32 link, uint16 *pdata, uint16 maxbuf)
{
  //   Receive an IMP packet from the virtual modem. pdata is a pointer usually
  // directly into H316 simulated memory) to where the IMP packet data should
  // be stored, and maxbuf is the maximum length of that buffer in H316 words
  // (not bytes!).  If a message is successfully received then this routine
  // returns the length, again in H316 words, of the IMP packet.  The caller
  // can detect buffer overflows by comparing this result to maxbuf.  If no
  // packets are waiting right now then zero is returned, and -1 is returned
  // in the event of any fatal socket I/O error.
  //
  //  This routine also handles checking for unsolicited messages and duplicate
  // or out of sequence messages.  All of these are unceremoniously discarded.
  //
  //   One final note - it's explicitly allowed for pdata to be null and/or
  // maxbuf to be zero.  In either case the received package is discarded, but
  // the actual length of the discarded package is still returned.
  UDP_PACKET pkt;  int32 pktlen, explen, implen, i;  uint32 magic, pktseq;
  if ((link < 0) || (link >= MAXLINKS)) return SCPE_IERR;
  if (!udp_links[link].used) return SCPE_IERR;

  while ((pktlen = udp_receive_packet(link, &pkt)) > 0) {
    // First do some header checks for a valid UDP packet ...
    if (pktlen < UDP_HEADER_LEN) {
      sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet w/o header (length=%d)\n", link, pktlen);
      continue;
    }
    magic = ntohl(pkt.magic);
    if (magic != MAGIC) {
      sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet w/bad magic number (magic=%08x)\n", link, magic);
      continue;
    }
    implen = ntohs(pkt.count);
    explen = UDP_HEADER_LEN + implen*sizeof(uint16);
    if (explen != pktlen) {
      sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet length wrong (expected=%d received=%d)\n", link, explen, pktlen);
      continue;
    }

    //  Now the hard part = check the sequence number.  The rxsequence value is
    // the number of the next packet we expect to receive - that's the number
    // this packet should have.  If this packet's sequence is less than that,
    // then this packet is out of order or a duplicate and we discard it.  If
    // this packet is greater than that, then we must have missed one or two
    // packets.  In that case we MUST update rxsequence to match this one;
    // otherwise the two ends could never resynchronize after a lost packet.
    pktseq = ntohl(pkt.sequence);
    if (pktseq < udp_links[link].rxsequence) {
      sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet out of sequence 1 (expected=%d received=%d\n", link, udp_links[link].rxsequence, pktseq);
      continue;
    }
    if (pktseq != udp_links[link].rxsequence) {
      sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet out of sequence 2 (expected=%d received=%d\n", link, udp_links[link].rxsequence, pktseq);
    }
    udp_links[link].rxsequence = pktseq+1;

    // It's a valid packet - if there's no buffer then just discard it.
    if ((pdata == NULL) || (maxbuf == 0)) {
      sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet discarded (no buffer available)\n", link);
      return implen;
    }

    // Copy the data to the H316 memory and we're done!
    sim_debug(IMP_DBG_UDP, dptr, "link %d - packet received (sequence=%d, length=%d)\n", link, pktseq, pktlen);
    for (i = 0;  i < (implen < maxbuf ? implen : maxbuf);  ++i)
      *pdata++ = ntohs(pkt.data[i]);
    return implen;
  }

  // Here if pktlen <= 0 ...
  return pktlen;
}
Beispiel #3
0
int udp_receive (int link, uint8_t * pdata, uint16_t maxbuf)
  {
    // Receive an packet from the virtual modem. pdata is a pointer to where
    // the IMP packet data should be stored, and maxbuf is the maximum length
    // of that buffer in bytes.  If a message is
    // successfully received then this routine returns the length, again in
    // bytes, of the packet.  The caller can detect buffer overflows by
    // comparing this result to maxbuf.  If no packets are waiting right now
    // then zero is returned, and -1 is returned in the event of any fatal
    // socket I/O error.
    //
    // This routine also handles checking for unsolicited messages and
    // duplicate or out of sequence messages.  All of these are
    // unceremoniously discarded.
    //
    // One final note - it's explicitly allowed for pdata to be null and/or
    // maxbuf to be zero.  In either case the received package is discarded, but
    // the actual length of the discarded package is still returned.

    UDP_PACKET pkt;
    int32_t pktlen, explen, implen, i;
    uint32_t magic, pktseq;
    if ((link < 0) || (link >= MAXLINKS))
      return -1;
    if (!udp_links [link] . used)
      return -1;
    //if (dptr != udp_links [link] . dptr)
      //return SCPE_IERR;
  
    while ((pktlen = udp_receive_packet (link, & pkt, sizeof (pkt))) > 0)
      {
        // First do some header checks for a valid UDP packet ...
        if (((size_t) pktlen) < UDP_HEADER_LEN)
          {
            //sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet w/o header (length=%d)\n", link, pktlen);
            continue;
          }
        magic = pkt . magic;
        if (magic != MAGIC)
          {
            //sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet w/bad magic number (magic=%08x)\n", link, magic);
            continue;
          }
        implen = pkt . count;
        explen = UDP_HEADER_LEN + implen * sizeof (uint8_t);
        if (explen != pktlen)
          {
            //sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet length wrong (expected=%d received=%d)\n", link, explen, pktlen);
            continue;
          }
  
        // Now the hard part = check the sequence number.  The rxsequence value
        // is the number of the next packet we expect to receive - that's the
        // number this packet should have.  If this packet's sequence is less
        // than that, then this packet is out of order or a duplicate and we
        // discard it.  If this packet is greater than that, then we must have
        // missed one or two packets.  In that case we MUST update rxsequence
        // to match this one; otherwise the two ends could never resynchronize
        // after a lost packet./  And there's one final complication to worry
        // about - if the simh on the other end is restarted for some reason,
        // then his sequence numbers will reset to zero.  In that case we'll
        // never recover synchronization without special efforts.  The hack is
        // to check for a packet sequence number of zero and, if we find it,
        // force synchronization.  This improves the situation, but I freely
        // admit that it's possible to think of a number of cases where this
        // also fails.  The only absolute solution is to implement a more
        // complicated system with non-IMP control messages exchanged between
        // the modem emulation on both ends.  That'd be nice, but I'll leave it
        // as an exercise for later.

        pktseq = pkt . sequence;
        if ((pktseq == 0) && (udp_links [link] . rxsequence != 0))
          {
            //sim_debug(IMP_DBG_UDP, dptr, "link %d - remote modem restarted\n", link);
          }
        else if (pktseq < udp_links [link] . rxsequence)
          {
            //sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet out of sequence 1 (expected=%d received=%d\n", link, udp_links[link].rxsequence, pktseq);
            continue;  // discard this packet!
          }
        else if (pktseq != udp_links [link] . rxsequence)
          {
            //sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet out of sequence 2 (expected=%d received=%d\n", link, udp_links[link].rxsequence, pktseq);
          }
        udp_links [link] . rxsequence = pktseq + 1;
    
        // It's a valid packet - if there's no buffer then just discard it.
        if ((pdata == NULL) || (maxbuf == 0))
          {
            //sim_debug(IMP_DBG_UDP, dptr, "link %d - received packet discarded (no buffer available)\n", link);
            return implen;
          }
  
        // Copy the data and we're done!
        //sim_debug (IMP_DBG_UDP, dptr, "link %d - packet received (sequence=%d, length=%d)\n", link, pktseq, pktlen);
printf ("link %d - packet received (sequence=%d, length=%d)\n", link, pktseq, pktlen);
        for (i = 0;  i < (implen < maxbuf ? implen : maxbuf);  ++ i)
          * pdata ++ = pkt . data [i];
        return implen;
      }
  
    // Here if pktlen <= 0 ...
    return pktlen;
  }