Exemple #1
0
/*
 * Fill in the reverse lookup question packet
 */
static __inline void qinit (question_t *q, DWORD ip)
{
  char *c;
  BYTE  i;

  q->h.ident   = 0x5271;         /* 7152h = 'qR' */
  q->h.flags   = intel16 (DRD);  /* recursion desired */
  q->h.qdcount = intel16 (1);
  q->h.ancount = 0;
  q->h.nscount = 0;
  q->h.arcount = 0;

  c  = q->x;
  ip = ntohl (ip);
  for (i = 0; i < 4; ++i)
  {
    BYTE x = (BYTE) ip;
    ip >>= 8;
    *c = (x < 10) ? 1 : (x < 100) ? 2 : 3;
    itoa (x,c+1,10);
    c += *c + 1;
  }
  strcpy (c,"\7in-addr\4arpa");
  c += 14;
  *(short*) c = intel16 (DTYPEPTR);
  c += sizeof(short);
  *(short*) c = intel16 (DIN);
}
Exemple #2
0
int fix_tcp_packet (in_Header *ip, tcp_Header *tcp, int ack_len, int data_len)
{
  static DWORD seq_num = 12345678;  /* starting sequence */
  tcp_PseudoHeader ph;
  WORD src_port;

  tcp->checksum = 0;
  src_port      = tcp->srcPort;
  tcp->srcPort  = tcp->dstPort;
  tcp->dstPort  = src_port;
  tcp->acknum   = intel (intel(tcp->seqnum) + ack_len);
  tcp->seqnum   = intel (seq_num);
  tcp->offset   = sizeof(*tcp) / 4;    /* in dwords */
  seq_num      += data_len;

  ph.src        = ip->source;
  ph.dst        = ip->destination;
  ph.mbz        = 0;
  ph.protocol   = TCP_PROTO;
  ph.length     = intel16 (sizeof(*tcp) + data_len);
  ph.checksum   = CHECKSUM (tcp, sizeof(*tcp) + data_len);

  ip->length    = intel16 (data_len + sizeof(*tcp) + sizeof(*ip));
  ip->checksum  = 0;
  ip->checksum  = ~CHECKSUM (ip, sizeof(*ip));
  tcp->checksum = ~CHECKSUM (&ph, sizeof(ph));
  return (sizeof(*ip) + sizeof(*tcp) + data_len);
}
Exemple #3
0
static void qinit( void )
{
    question->h.flags = intel16(DRD);
    question->h.qdcount = intel16(1);
    question->h.ancount = 0;
    question->h.nscount = 0;
    question->h.arcount = 0;
}
Exemple #4
0
/*
 * Send a tftp acknowledge packet
 */
static void send_ack (WORD block)
{
  struct tftphdr ack;

  ack.th_opcode = intel16 (ACK);
  ack.th_block  = intel16 (block);
  sock_fastwrite (sock, (BYTE*)&ack, TFTP_HEADSIZE);
}
Exemple #5
0
static int udp_loopback (udp_Header *udp, unsigned udp_len)
{
  if (intel16(udp->dstPort) == IPPORT_ECHO)
  {
    /** \todo UDP loopback handler should handle ECHO protocol */
  }
  else if (intel16(udp->dstPort) == IPPORT_DISCARD)
  {
    /** \todo UDP loopback handler should handle DISCARD protocol */
  }
  ARGSUSED (udp_len);
  return (0);
}
Exemple #6
0
static int udp_loopback (udp_Header *udp, unsigned udp_len)
{
  if (intel16(udp->dstPort) == IPPORT_ECHO)
  {
    /* !!to-do */
  }
  else if (intel16(udp->dstPort) == IPPORT_DISCARD)
  {
    /* !!to-do */
  }
  ARGSUSED (udp_len);
  return (0);
}
Exemple #7
0
/**
 * Send an "ICMP Time Exceeded" (reassebly timeout) back to 'ip->source'
 */
int icmp_send_timexceed (const in_Header *ip, const void *mac_dest)
{
  struct _pkt    *pkt;
  union ICMP_PKT *icmp;

  if (!icmp_check(ip,ICMP_TIMXCEED))
     return (0);

  pkt  = (struct _pkt*) _eth_formatpacket (mac_dest, IP4_TYPE);
  icmp = &pkt->icmp;

  icmp_print (1, icmp_exceed_str[1], ip->destination);

  memset (&icmp->unused, 0, sizeof(icmp->unused));

  icmp->unused.type = ICMP_TIMXCEED;
  icmp->unused.code = 1;

  icmp->unused.ip.hdrlen         = sizeof(in_Header) / 4;
  icmp->unused.ip.ver            = 4;
  icmp->unused.ip.ttl            = _default_ttl;
  icmp->unused.ip.identification = ip->identification;
  icmp->unused.ip.length         = intel16 (sizeof(in_Header));
  icmp->unused.ip.proto          = ip->proto;
  icmp->unused.ip.checksum       = ~CHECKSUM (&icmp->unused.ip, sizeof(in_Header));

  return icmp_send (pkt, ip->destination, ip->source, sizeof(icmp->unused));
}
Exemple #8
0
/*
 * Send a tftp request packet
 */
static void send_req (char request, const char *fname)
{
  char *cp, *mode;
  int   len;
  int   fnamlen = strlen (fname);

  /* The output buffer is setup with the request code, the file name,
   * and the name of the data format.
   */
  memset (outbuf, 0, sizeof(*outbuf));
  outbuf->th_opcode = intel16 (request);
  len = SEGSIZE - sizeof(outbuf->th_opcode) - strlen(tftp_xfer_mode) - 1;
  cp  = (char*) &outbuf->th_stuff[0];

  for ( ; *fname && len > 0 && fnamlen > 0; len--, fnamlen--)
      *cp++ = *fname++;
  *cp++ = '\0';

  for (mode = tftp_xfer_mode; *mode; )
      *cp++ = *mode++;
  *cp++ = '\0';

  /* Finally send the request
   */
  len = (int) (cp - (char*)outbuf);
  sock_fastwrite (sock, (BYTE*)outbuf, len);
}
Exemple #9
0
int sock_loopback (in_Header *ip)
{
  if (ip->proto == TCP_PROTO)
  {
    tcp_Header *tcp = (tcp_Header*) ((BYTE*)ip + in_GetHdrLen(ip));

    if (intel16(tcp->dstPort) == test_port)
    {
      BYTE flags = tcp->flags & tcp_FlagMASK;

      if (flags == tcp_FlagSYN)
      {
        tcp->flags = tcp_FlagACK | tcp_FlagSYN;
        return fix_tcp_packet (ip, tcp, 1, 0);
      }

      if (flags & tcp_FlagACK)
      {
        char *data = (char*)tcp + (tcp->offset << 2);

        if (!strncmp(data,"HELO",4))
        {
          strcpy (data, "Welcome to loop-back handler");
          return fix_tcp_packet (ip, tcp, 4, strlen(data) + 1);
        }
        if (!strncmp(data,"QUIT",4))
        {
          strcpy (data, "Bye from loop-back handler");
          return fix_tcp_packet (ip, tcp, 4, strlen(data) + 1);
        }
      }
    }
  }
  return (-1);
}
Exemple #10
0
/**
 * Build a PADx packet.
 */
static WORD build_pad (struct pppoe_Packet *pkt, WORD code)
{
  BYTE *tags = &pkt->data[0];

  if (code == PPPOE_CODE_PADI || code == PPPOE_CODE_PADR)
  {
    WORD srv_len = 0;

    *(WORD*) tags = PPPOE_TAG_SERVICE_NAME;
    tags += 2;
    if (cfg.serviceName[0])
    {
      srv_len = strlen (cfg.serviceName);
      srv_len = min (srv_len, sizeof(pkt->data)-2-PPPOE_TAG_HDR_SIZE);
      memcpy (tags+2, cfg.serviceName, srv_len);
    }
    *(WORD*) tags = intel16 (srv_len);

    /* Insert PPPOE_TAG_END_LIST ?
     */
    return (srv_len + PPPOE_TAG_HDR_SIZE);
  }
  *(WORD*)tags = 0;  /* No tags */
  return (0);
}
Exemple #11
0
/**
 * Send an ICMP destination/protocol unreachable back to 'ip->source'.
 * Limit the rate of these to 20 per second. Ref. RFC-1812.
 */
int icmp_send_unreach (const in_Header *ip, int code)
{
  static DWORD next_time = 0UL;
  struct _pkt    *pkt;
  union ICMP_PKT *unr;
  unsigned        len;

  if (!icmp_check(ip,ICMP_UNREACH))
     return (0);

  if (next_time && !chk_timeout(next_time))
     return (0);

  next_time = set_timeout (50);

  pkt = (struct _pkt*) _eth_formatpacket (MAC_SRC(ip), IP4_TYPE);
  unr = &pkt->icmp;
  len = intel16 (ip->length) - in_GetHdrLen (ip);
  len = min (len, sizeof(*ip)+sizeof(unr->unused.spares));

  icmp_print (1, _LANG(icmp_unreach_str[code]), ip->destination);
  memcpy (&unr->unused.ip, ip, len);
  unr->unused.type = ICMP_UNREACH;
  unr->unused.code = (BYTE) code;

  return icmp_send (pkt, ip->destination, ip->source, sizeof(unr->unused));
}
Exemple #12
0
/*
 * We have been called with an ip-packet located on stack in
 * _eth_send_loopback(). Hence, it's safe to call _eth_send() again
 * here. MAC-header is in front of 'ip'.
 */
int loopback_device (in_Header *ip)
{
  int   ip_hlen, ip_len;
  DWORD ip_dst;
  DWORD ip_ofs;
  WORD  ip_flg;

  if (!loopback_enable || !_chk_ip_header(ip)) /* silently discard */
     return (-1);

  ip_hlen = in_GetHdrLen (ip);    /* length of IP-header (w/options) */
  ip_len  = intel16 (ip->length); /* total length of IP-packet */
  ip_dst  = ip->destination;

  ip->destination = ip->source;   /* swap source and destination */
  ip->source      = ip_dst;
  ip->checksum    = 0;
  ip->checksum    = ~checksum (ip, ip_hlen);   /* redo check-sum */

  ip_ofs = intel16 (ip->frag_ofs);
  ip_flg = ip_ofs & ~IP_OFFMASK;
  ip_ofs = (ip_ofs & IP_OFFMASK) << 3; /* 0 <= ip_ofs <= 65536-8 */
   
  if (ip_ofs || (ip_flg & IP_MF)) /* fragment; let _ip_fragment() */
     return (ip_len);             /* handle it on next poll */

  if (ip->proto == ICMP_PROTO)
  {
    ICMP_PKT *icmp = (ICMP_PKT*) ((BYTE*)ip + ip_hlen);
    int       len  = icmp_loopback (icmp, ip_len - ip_hlen);

    if (len > 0)
       return (ip_hlen+len);
  }
  else if (ip->proto == UDP_PROTO)
  {
    udp_Header *udp = (udp_Header*) ((BYTE*)ip + ip_hlen);
    int         len = udp_loopback (udp, ip_len-ip_hlen);

    if (len > 0)
       return (ip_hlen+len);
  }

  if (loopback_handler)
     ip_len = (*loopback_handler) (ip);
  return (ip_len);
}
Exemple #13
0
/*
 * getresult() - read answer and extract host name
 *               return 0 on error, 1 on success
 */
static __inline int getresult (udp_Socket *s, char *name)
{
  answer_t a;
  struct   rrpart *rr;
  char    *c;
  int      len = sock_fastread ((sock_type*)s, (BYTE*)&a, sizeof(a));

  if (len < sizeof(struct dhead) ||
      a.h.qdcount != intel16(1) || a.h.ancount == 0)
     return (0);

  /* Skip question */
  c = a.x;
  while (*c)
        ++c;
  c += 5;

  /* Skip name */
  while (*c)
  {
    if ((*c & 0xC0) == 0xC0)
    {
      c += 2;
      break;
    }
    else
      ++c;
  }
  rr = (struct rrpart *) c;
  if (rr->rtype != intel16(DTYPEPTR))
     return (0);

  c = (char*) &rr->rdata;
  while (*c)
  {
    if ((*c & 0xC0) == 0xC0)
        c = a.x + (*(int*)c & 0x3FFF);
    strncpy (name,c+1,*c);
    name += *c;
    c += *c + 1;
    if (*c)
        *name++ = '.';
  }
  *name = 0;
  return (1);
}
Exemple #14
0
/**
 * Handle incoming PPPoE packets.
 */
int pppoe_handler (const pppoe_Packet *pkt)
{
  const BYTE *buf;
  const void *src;
  const void *dst;
  WORD  proto, len;
  BOOL  bcast, delivered = FALSE;

  if (pkt->type != 1 || pkt->ver != 1)
     return (0);

  src   = MAC_SRC (pkt);
  dst   = MAC_DST (pkt);
  proto = MAC_TYP (pkt);
  bcast = !memcmp (dst, _eth_brdcast, _eth_mac_len);

  if (proto == PPPOE_SESS_TYPE && state == StateSession)
  {
    if (pkt->code    == PPPOE_CODE_SESS &&
        pkt->session == session         && !bcast &&
        !memcmp(dst, _eth_addr, _eth_mac_len) &&  /* to us? */
        !memcmp(src, ac_macAddr, _eth_mac_len))
    {
      len = intel16 (pkt->length);
      buf = &pkt->data[0];
      ppp_input (buf, len);    /* assume ppp_input() traces it */
      delivered = TRUE;
    }
  }
  else if (!bcast && proto == PPPOE_DISC_TYPE && state == StateDiscovery)
  {
    if (pkt->code == PPPOE_CODE_PADO)          /* Offer (can this be bcast?) */
    {
      got_PADO = TRUE;
      memcpy (ac_macAddr, src, _eth_mac_len);
    }
    else if (pkt->code == PPPOE_CODE_PADT &&  /* Terminate */
             pkt->session == session)
    {
      if (cfg.trace)
         outsnl (_LANG("PPPoE: session terminated"));
      got_PADT = TRUE;
      session  = 0;
    }
    else if (pkt->code == PPPOE_CODE_PADS)    /* Session-confirmation */
    {
      got_PADS = TRUE;
      session  = pkt->session;
    }
    else if (pkt->code == PPPOE_CODE_PADM)    /* Message (what to do?) */
    {
      got_PADM = TRUE;
    }
  }
  if (!delivered)
     DEBUG_RX (NULL, pkt);
  return (1);
}
Exemple #15
0
/*  ddextract
*   extract the data from a response message.
*   returns the appropriate status code and if the data is available,
*   copies it into data
*   dtype is the RR type;  unpacker is the function to get the data
*         from the RR.
*/
static longword ddextract( struct useek *qp, byte dtype,
                        unpacker_funct unpacker, void *data )
{
    word i,j,nans,rcode;
    struct rrpart *rrp;
    byte *p,space[260];

    nans = intel16(qp->h.ancount);		/* number of answers */
    rcode = DRCODE & intel16(qp->h.flags);	/* return code for this message*/
    if (rcode > 0)
	return(rcode);

    if (nans > 0 &&								/* at least one answer */
    (intel16(qp->h.flags) & DQR)) {			/* response flag is set */
    p = (byte *)&qp->x;                 /* where question starts */
	i = unpackdom((char*)space,(char*)p,(char*)qp);    /* unpack question name */
	/*  spec defines name then  QTYPE + QCLASS = 4 bytes */
	p += i+4;
/*
 *  at this point, there may be several answers.  We will take the first
 *  one which has an IP number.  There may be other types of answers that
 *  we want to support later.
 */
	while (nans-- > 0) {					/* look at each answer */
	    i = unpackdom((char*)space,(char*)p,(char*)qp);	/* answer name to unpack */
	    /*			n_puts(space);*/
	    p += i;								/* account for string */
	    rrp = (struct rrpart *)p;			/* resource record here */
 /*
  *  check things which might not align on 68000 chip one byte at a time
  */
	    if (!*p && *(p+1) == dtype && 		/* correct type and class */
	    !*(p+2) && *(p+3) == DIN) {
		unpacker(data,rrp,qp);     /* get data we're looking for */
		return(0);						/* successful return */
	    }
	    movmem(&rrp->rdlength,&j,2);	/* 68000 alignment */
	    p += 10+intel16(j);				/* length of rest of RR */
	}
    }

    return(-1);						/* generic failed to parse */
}
Exemple #16
0
/**
 * Build and send a PPPoE Session packet (IPCP or LCP packet).
 */
int pppoe_send_sess (const void *sock, const BYTE *buf, WORD len)
{
  pppoe_Packet *pkt;

  pkt = (pppoe_Packet*) _eth_formatpacket (&ac_macAddr[0], PPPOE_SESS_TYPE);

  pkt->ver     = 1;
  pkt->type    = 1;
  pkt->code    = PPPOE_CODE_SESS;
  pkt->session = session;
  pkt->length  = intel16 (len);

  memcpy (pkt->data, buf, len);
  return _eth_send (len + PPPOE_HDR_SIZE, sock, __FILE__, __LINE__);
}
Exemple #17
0
/**
 * Build a PPPoE session packet header.
 * Only called for IPv4 packets.
 */
void *pppoe_mac_format (union link_Packet *tx)
{
  pppoe_Packet *pppoe = (pppoe_Packet*) tx->eth.data;

  memcpy (&tx->eth.head.destination[0], ac_macAddr, sizeof(mac_address));
  memcpy (&tx->eth.head.source[0], _eth_addr, sizeof(mac_address));

  tx->eth.head.type = PPPOE_SESS_TYPE;
  pppoe->ver     = 1;
  pppoe->type    = 1;
  pppoe->code    = PPPOE_CODE_SESS;
  pppoe->session = session;
  _pkt_ip_ofs    = sizeof(eth_Header) + PPPOE_HDR_SIZE + 2; /* !! see _eth_send() */
  *(WORD*) &pppoe->data[0] = intel16 (PPP_IP);
  return (void*) &pppoe->data[2];
}
Exemple #18
0
static int _rarp_request (void)
{
  rarp_Header *rarp = (rarp_Header*) _eth_formatpacket (&_eth_brdcast[0],
                                                        RARP_TYPE);
  rarp->hwType       = intel16 (_eth_get_hwtype(NULL,NULL));
  rarp->protType     = IP4_TYPE;
  rarp->hwAddrLen    = sizeof (mac_address);
  rarp->protoAddrLen = sizeof (my_ip_addr);
  rarp->opcode       = RARP_REQUEST;
  rarp->srcIPAddr    = 0;
  rarp->dstIPAddr    = 0;
  memcpy (rarp->srcEthAddr, _eth_addr, sizeof(mac_address));
  memcpy (rarp->dstEthAddr, _eth_addr, sizeof(mac_address));

  return _eth_send (sizeof(*rarp), NULL, __FILE__, __LINE__);
}
// The following code was leveraged from ip_handler() and tcp_handler()
far ll_prefix *my_ports(far ll_prefix *LL, byte *hdrbuf, word *pflags) {
   int myport;       // The port where we received this message
   word iplen;
   in_Header *ip;
   tcp_Header *tp;

   // We will always be processing the frame with the TCP/IP stack
   *pflags |= CUSTOM_PKT_FLAG_PROCESS;

   // Check whether the socket is in use
   if (! sock_alive(&socket) ) {
      // Socket is free, see if this is a packet bound for one of the ports
      // we're willing to receive on.

      // First, parse the packet (code leveraged from ip_handler(),
      // tcp_handler().)
      _pkt_buf2root(LL, ip = (in_Header *)(hdrbuf+LL->net_offs),
            sizeof(in_Header), LL->net_offs);
      iplen = in_GetHdrlenBytes(ip);
      if (ip->proto == TCP_PROTO) {
         // We have a valid TCP packet, check myport
         _pkt_buf2root(LL, tp = (tcp_Header *)(hdrbuf+LL->tport_offs),
               sizeof(tcp_Header), LL->tport_offs);

         // We received the packet on the packet's destination port
         myport = intel16(tp->dstPort);

         switch(myport) {
            // List of ports which we're willing to receive.  We could
            // also search through a list, use a range (if (myport > 23 &&
            // myport < 30)), etc.
            case 7:  // Echo protocol
            case 23: // Telnet protocol
            case 80: // HTTP protocol
               // Accept the connection by calling listen for the incoming
               // port
               tcp_listen(&socket,myport,0,0,NULL,0);
               break;
            default:
               // Do nothing -- don't accept the connection
         }
      }
Exemple #20
0
/**
 * Build and send a PADx (PPPoE Active Discovery) packet as
 * link-layer broadcast or unicast.
 */
static int pppoe_send_disc (int code)
{
  pppoe_Packet *pkt;
  WORD          len;

  pkt = (pppoe_Packet*) _eth_formatpacket (&ac_macAddr[0], PPPOE_DISC_TYPE);
  len = build_pad (pkt, code);

  pkt->ver     = 1;
  pkt->type    = 1;
  pkt->code    = code;
  pkt->session = session;
  pkt->length  = intel16 (len);

#if defined(USE_DEBUG)
  if (cfg.trace)
     (*_printf) ("PPPOE: sending %s\n", pppoe_get_code(code));
#endif

  return _eth_send (len + PPPOE_HDR_SIZE, NULL, __FILE__, __LINE__);
}
Exemple #21
0
/*
 *  Send an ICMP destination/protocol unreachable back to ip->source
 */
void icmp_unreach (const in_Header *ip, int code)
{
  struct _pkt    *pkt;
  union icmp_pkt *unr;
  int             len;

  if (!icmp_chk_src(ip,ICMP_UNREACH))
     return;

  pkt = (struct _pkt*) _eth_formatpacket (MAC_SRC(ip), IP_TYPE);
  unr = &pkt->icmp;
  len = intel16 (ip->length) - in_GetHdrLen (ip);
  len = min (len, sizeof(*ip)+sizeof(unr->unused.spares));

  icmp_print (1, icmp_unreach_str[code], ip->destination);
  memcpy (&unr->unused.ip, ip, len);
  unr->unused.type = ICMP_UNREACH;
  unr->unused.code = code;

  icmp_send (pkt, ip->destination, ip->source, sizeof(unr->unused));
}
Exemple #22
0
/*
 *  Send an "ICMP Time Exceeded" (reassebly timeout) back to 'ip->source'
 */
void icmp_timexceed (const in_Header *ip, const void *mac_dest)
{
  struct _pkt    *pkt;
  union icmp_pkt *tim;
  int             len;

  if (!icmp_chk_src(ip,ICMP_TIMXCEED))
     return;

  pkt = (struct _pkt*) _eth_formatpacket (mac_dest, IP_TYPE);
  tim = &pkt->icmp;
  len = intel16 (ip->length) - in_GetHdrLen (ip);
  len = min (len, sizeof(*ip) + sizeof(tim->unused.spares));

  icmp_print (1, icmp_exceed_str[1], ip->destination);
  memcpy (&tim->unused.ip, ip, len);
  tim->unused.type = ICMP_TIMXCEED;
  tim->unused.code = 1;

  icmp_send (pkt, ip->destination, ip->source, sizeof(tim->unused));
}
Exemple #23
0
/*  sendom
*   put together a domain lookup packet and send it
*   uses port 53
*	num is used as identifier
*/
static int sendom( char *s, longword towho, word num, byte dtype )
{
    word i,ulen;
    byte *psave,*p;

    psave = (byte*)&(question->x);
    i = packdom((char *)&(question->x),s);

    p = &(question->x[i]);
    *p++ = 0;				/* high byte of qtype */
    *p++ = dtype;			/* number is < 256, so we know high byte=0 */
    *p++ = 0;				/* high byte of qclass */
    *p++ = DIN;				/* qtype is < 256 */

    question->h.ident = intel16(num);
    ulen = sizeof(struct dhead)+(p-psave);

    udp_open( dom_sock, 997, towho, 53, NULL );    /* divide err */

    sock_write( (sock_type*)dom_sock, (byte*)question, ulen );
    return( ulen);
}
Exemple #24
0
/*
 * Open a TFTP connection on a random local port (our transaction ID).
 * Send the request, wait for first data block and send the first ACK.
 */
static int tftp_open (DWORD server, const char *fname)
{
  int  retry;
  WORD port = 69;

#if defined(USE_BSD_API)
  struct servent *sp = getservbyname ("tftp", "udp");

  if (sp)
     port = intel16 ((WORD)sp->s_port);
#endif

  currblock = 0UL;
  blocksize = 0;

  for (retry = 0; retry < tftp_retry; retry++)
  {
    WORD our_tid;  /* our transaction ID (local port) */

    if (tftp_lport && tftp_lport < TFTP_PORT_LOW)
       outsnl (_LANG("tftp: Illegal local port."));

    if (tftp_lport >= TFTP_PORT_LOW)
         our_tid = tftp_lport;
    else our_tid = Random (TFTP_PORT_LOW, TFTP_PORT_HIGH);

    /* Try to open a TFTP connection to the server
     */
    if (!udp_open(&sock->udp, our_tid, server, port, NULL))
    {
      TRACE (("tftp: %s\n", sockerr(sock)));
      return (0);
    }
    sock->udp.locflags |= LF_NOCLOSE;  /* don't close socket on timeout */

    /* Send the file request block, and then wait for the first data
     * block. If there is no response to the query, retry it with
     * another transaction ID (local port), so that all old packets get
     * discarded automatically.
     */
    send_req (RRQ, fname);

    /* This hack makes it work because the response is sent back on
     * a source-port different from port 69; i.e. the server TID
     * uses a random port. Force the response packet to match a passive
     * socket in udp_handler().
     */
    sock->udp.hisaddr = 0;

    ibuflen = recv_packet (1);
    if (ibuflen >= 0)
    {
      blocksize = ibuflen;
      isopen = TRUE;
      send_ack (1);
      return (1);
    }

    /* If an error (except timeout) occurred, retries are useless
     */
    if (tftp_errno == ERR_ERR || tftp_errno == ERR_UNKNOWN)
       break;
  }
  return (0);
}
Exemple #25
0
/**
 * Poll for arrival of new packets (IP/ARP/RARP/PPPoE protocol).
 * Sets protocol-type of packet received in 'type'.
 *
 * For Ethernet/TokenRing-type drivers: \n
 *  \retval Pointer past the MAC-header to the IP/ARP/RARP
 *          protocol header. Also check for link-layer broadcast.
 *
 * For PPP/SLIP-type drivers (no MAC-headers): \n
 *  \retval Pointer to the IP-packet itself.
 *   IP-protocol is assumed. Can never be link-layer broadcast.
 */
void *_eth_arrived (WORD *type_ptr, BOOL *broadcast)
{
  union link_Packet *pkt;
  mac_address       *dst;
  void              *ret = NULL;
  BOOL               is_bcast = FALSE;
  WORD               type = 0;

  SIO_TRACE (("_eth_arrived"));

  if (!_eth_is_init)  /* GvB 2002-09, Lets us run without a working driver */
     return (NULL);

  if (_eth_recv_hook)
       pkt = (union link_Packet*) (*_eth_recv_hook) (&type);
  else pkt = poll_recv_queue (&type);

  if (!pkt)
     return (NULL);

  if (_eth_recv_peek && !(*_eth_recv_peek)(pkt))
  {
    _eth_free (pkt);
    return (NULL);
  }

  /* Hack: If _ip?_handler() can't be reentered, only accept
   *       non-IP packets. Assume PPPoE session packets carry only IP.
   */
  if (_ip_recursion &&
      (type == IP4_TYPE || type == IP6_TYPE || type == PPPOE_SESS_TYPE))
  {
    /**< \todo push back packet, else it's lost */
    STAT (macstats.num_ip_recurse++);
    _eth_free (pkt);
    return (NULL);
  }

  if (_pktserial)
  {
    dst = NULL;
    ret = (void*) &pkt->ip;
  }
  else if (_pktdevclass == PDCLASS_TOKEN || _pktdevclass == PDCLASS_TOKEN_RIF)
  {
    dst = &pkt->tok.head.destination;
    ret = (void*) &pkt->tok.data;
  }
  else if (_pktdevclass == PDCLASS_FDDI)
  {
    dst = &pkt->fddi.head.destination;
    ret = (void*) &pkt->fddi.data;
  }
  else if (_pktdevclass == PDCLASS_ARCNET)
  {
    dst = (mac_address*) &pkt->arc.head.destination;
    ret = (void*) ((BYTE*)pkt + ARC_HDRLEN);
  }
  else   /* must be ether */
  {
    dst = &pkt->eth.head.destination;
    ret = (void*) &pkt->eth.data;
  }

#if defined(NEED_PKT_SPLIT)
  pkt_split_mac_in (pkt);
#endif

#if defined(USE_STATISTICS)
  update_in_stat();
#endif

#if defined(NEED_PKT_SPLIT) && defined(USE_DEBUG) && 0  /* test */
  pkt_print_split_in();
#endif

  /* ARCnet should never have LLC fields. So don't test for it
   */
  if (_pktdevclass != PDCLASS_ARCNET)
  {
    if (dst && !memcmp(dst, &_eth_brdcast, sizeof(_eth_brdcast)))
       is_bcast = TRUE;

    if (intel16(type) < 0x600)       /* LLC length field */
       fix_llc_head (&ret);
  }
  else if (dst && *(BYTE*)dst == 0)  /* ARCnet broadcast */
  {
    is_bcast = TRUE;
  }

  if (type_ptr)
     *type_ptr = type;

  if (broadcast)
     *broadcast = is_bcast;

  return (ret);
}
Exemple #26
0
WORD  ntohs (WORD  val) { return intel16(val); }
Exemple #27
0
WORD  htons (WORD  val) { return intel16(val); }
Exemple #28
0
/**
 * _eth_send() does the actual transmission once we are complete with
 * filling the buffer.  Do any last minute patches here, like fix the
 * size. Send to "loopback" device if it's IP and destination matches
 * loopback network (127.x.x.x.).
 *
 * Return length of network-layer packet (not length of link-layer
 * packet).
 */
int _eth_send (WORD len, const void *sock, const char *file, unsigned line)
{
#if defined(USE_DEBUG) || defined(USE_LOOPBACK)
  unsigned errline = 0;
#endif
  BOOL send_loopback_to_driver = FALSE;

  SIO_TRACE (("_eth_send, len %d", len));

  if (!_eth_is_init)  /* GvB 2002-09, Lets us run without a working eth */
  {
    SOCK_ERRNO (ENETDOWN);
    return (0);
  }

#if defined(WIN32)
  /*
   * Just a test for now; send it to the driver and look what happens....
   * They go on the wire and not to the Winsock loopback provider.
   * No surprise here yet.
   */
  if (loopback_mode & LBACK_MODE_WINSOCK)
     send_loopback_to_driver = TRUE;
#endif

  if (proto == IP4_TYPE)
  {
    /* Sending to loopback device if IPv4.
     */
    const in_Header *ip = (const in_Header*) nw_pkt;

    if (!send_loopback_to_driver &&
        _ip4_is_loopback_addr(intel(ip->destination)))
    {
#if defined(USE_LOOPBACK)
      len = send_loopback (*TX_BUF(), FALSE, &errline);
#else
      STAT (ip4stats.ips_odropped++);    /* packet dropped (null-device) */
#endif
      goto debug_tx;
    }
  }

#if defined(USE_IPV6)
  else if (proto == IP6_TYPE)
  {
    const in6_Header *ip = (const in6_Header*) nw_pkt;

    if (!send_loopback_to_driver &&
        IN6_IS_ADDR_LOOPBACK(&ip->destination))
    {
#if defined(USE_LOOPBACK)
      len = send_loopback (*TX_BUF(), TRUE, &errline);
#else
      STAT (ip6stats.ip6s_odropped++);
#endif
      goto debug_tx;
    }
  }
#endif  /* USE_IPV6 */

#if defined(USE_PPPOE)
  else if (proto == PPPOE_SESS_TYPE)
  {
    pppoe_Packet *pppoe = (pppoe_Packet*) TX_BUF()->eth.data;

    pppoe->length = intel16 (len+2);
    len += PPPOE_HDR_SIZE + 2;      /* add 2 for protocol */
  }
#endif

  /* Store the last Tx CPU timestamp (for debugging).
   */
#if (DOSX) && !(DOSX & WINWATT)
  if (_dbugxmit && has_rdtsc)
     get_rdtsc2 (&_eth_last.tx.tstamp);
#endif

  /* Do the MAC-dependant transmit. `len' on return is total length
   * of link-layer packet sent. `len' is 0 on failure. The xmit-hook
   * is used by e.g. libpcap/libnet.
   */
  if (_eth_xmit_hook)
       len = (*_eth_xmit_hook) (TX_BUF(), len + _pkt_ip_ofs);
  else len = (*mac_transmit) (TX_BUF(), len + _pkt_ip_ofs);

  if (len > _pkt_ip_ofs)
  {
    _eth_last.tx.size = len;
    len -= _pkt_ip_ofs;
  }
  else
  {
    if (debug_on)
       outs ("Tx failed. ");
    len = 0;
    _eth_last.tx.size = 0;
  }

debug_tx:

#if defined(NEED_PKT_SPLIT)
  pkt_split_mac_out (TX_BUF());
#endif

#if defined(USE_STATISTICS)
  if (len > 0)
     update_out_stat();
#endif

#if defined(USE_DEBUG)
  if (_dbugxmit)
    (*_dbugxmit) (sock, (const in_Header*)nw_pkt, file, line);

  if (len == 0)
  {
    if (errline && !send_loopback_to_driver)
       dbug_printf ("** Error in loopback handler, line %u\n", errline);
    else
    {
      const char err[] = "** Transmit fault **\n";
      TCP_CONSOLE_MSG (0, ("%s", err));
      dbug_printf (err);
    }
  }
#else
  ARGSUSED (sock);
  ARGSUSED (file);
  ARGSUSED (line);
#endif

  /* Undo hack done in pppoe_mac_format()
   */
  if (proto == PPPOE_SESS_TYPE || _pktdevclass == PDCLASS_ETHER)
     _pkt_ip_ofs = sizeof(eth_Header);
  return (len);
}
Exemple #29
0
/*
 *  Handler for incoming ICMP packets
 */
void icmp_handler (const in_Header *ip, BOOL broadcast)
{
  union icmp_pkt *icmp;
  in_Header      *orig_ip;
  int             len, type, code;
  BOOL            for_me, i_orig;  /* is it for me, did I originate it */
  const char     *msg;

  DEBUG_RX (NULL, ip);

  if (block_icmp)   /* application is handling ICMP; not needed */
     return;

  len    = in_GetHdrLen (ip);
  icmp   = (union icmp_pkt*) ((BYTE*)ip + len);
  len    = intel16 (ip->length) - len;
  for_me = (DWORD) (intel(ip->destination) - my_ip_addr) <= multihomes;

  if (!for_me || broadcast)  /* drop broadcast pings.. */
     return;

  if (len < sizeof(icmp->info))
  {
    STAT (icmpstats.icps_tooshort++);
    return;
  }

  if (checksum(icmp,len) != 0xFFFF)
  {
    STAT (icmpstats.icps_checksum++);
    icmp_print (1, _LANG("bad checksum"), ip->source);
    return;
  }

  type    = icmp->unused.type;
  code    = icmp->unused.code;
  orig_ip = &icmp->ip.ip;
  i_orig  = is_local_addr (intel(orig_ip->source));

  if (type == ICMP_MASKREPLY)
  {
    if (!_domask_req)
       return;
    i_orig = TRUE;
  }

  /* !! this needs work
   */
  if (!i_orig &&
      (type != ICMP_ECHOREPLY && type != ICMP_ECHO &&
       type != ICMP_IREQREPLY && type != ICMP_TSTAMP))
  {
    icmp_bogus (ip, type, NULL);
    return;
  }

  switch (type)
  {
    case ICMP_ECHOREPLY:  /* check if we were waiting for it */
         STAT (icmpstats.icps_inhist[ICMP_ECHOREPLY]++);
         ping_hcache = intel (ip->source);
         ping_tcache = set_timeout (1000) - *(DWORD*)&icmp->echo.identifier;
         if (ping_tcache > 0x7FFFFFFFL)
             ping_tcache += 0x1800B0L;
         ping_number = *(DWORD*)(((BYTE*)&icmp->echo.identifier) + 4);
         return;

    case ICMP_UNREACH:
         STAT (icmpstats.icps_inhist[ICMP_UNREACH]++);
         if (code < DIM(icmp_unreach_str))
         {
           icmp_print (1, msg = icmp_unreach_str[code], ip->source);
#if !defined(USE_UDP_ONLY)
           if (orig_ip->proto == TCP_PROTO)
              _tcp_cancel (orig_ip, type, msg, 0);
           else
#endif
           if (orig_ip->proto == UDP_PROTO)
              _udp_cancel (orig_ip, type, msg, 0);
         }
         else
           STAT (icmpstats.icps_badcode++);
         return;

    case ICMP_SOURCEQUENCH:
         STAT (icmpstats.icps_inhist[ICMP_SOURCEQUENCH]++);
#if !defined(USE_UDP_ONLY)
         if (orig_ip->proto == TCP_PROTO)
         {
           icmp_print (1, _LANG("Source Quench"), ip->source);
           _tcp_cancel (orig_ip, type, NULL, 0);
         }
#endif
         return;

    case ICMP_REDIRECT:
         STAT (icmpstats.icps_inhist[ICMP_REDIRECT]++);
         if (code < 4)
         {
           DWORD new_gw = intel (icmp->ip.ipaddr);

           /* Check if new gateway is on our subnet
            */
           if ((new_gw ^ my_ip_addr) & sin_mask)
           {
             char buf[100], adr[20];
             strcpy (buf, ", GW = ");
             strcat (buf, _inet_ntoa(adr,new_gw));
             icmp_bogus (ip, type, buf);
             return;
           }
           icmp_print (1, msg = icmp_redirect_str[code], ip->source);

           switch (orig_ip->proto)
           {
#if !defined(USE_UDP_ONLY)
             case TCP_PROTO:
                  if (do_redirect.tcp)  /* do it to some socket */
                     _tcp_cancel (orig_ip, type, msg, new_gw);
                  break;
#endif
             case UDP_PROTO:
                  if (do_redirect.udp)
                     _udp_cancel (orig_ip, type, msg, new_gw);
                  break;

             case ICMP_PROTO:
                  if (do_redirect.icmp)
                  {
                    _ip_recursion = 1;
                    _arp_register (new_gw, intel(orig_ip->destination), 0);
                    _ip_recursion = 0;
                  }
                  break;

             case IGMP_PROTO:
                  if (do_redirect.igmp)
                  {
                    _ip_recursion = 1;
                    _arp_register (new_gw, intel(orig_ip->destination), 0);
                    _ip_recursion = 0;
                  }
                  break;
           }
         }
         else
           STAT (icmpstats.icps_badcode++);
         return;

    case ICMP_ECHO:
         STAT (icmpstats.icps_inhist[ICMP_ECHO]++);
         icmp_print (2, _LANG("PING requested of us"), ip->source);
         {
           /* Extract eth-address and create Echo reply packet.
            */
           struct _pkt     *pkt;
           union  icmp_pkt *newicmp;

           if (!icmp_chk_src(ip,ICMP_ECHO))
              return;

           pkt     = (struct _pkt*) _eth_formatpacket (MAC_SRC(ip), IP_TYPE);
           newicmp = &pkt->icmp;

           /* Don't let a huge reassembled ICMP-packet kill us.
            */
           len = min (len, mtu - sizeof(*ip));
           memcpy (newicmp, icmp, len);
           newicmp->echo.type = ICMP_ECHOREPLY;
           newicmp->echo.code = code;

           /* Use supplied ip values in case we ever multi-home.
            * Note that ip values are still in network order.
            */
           icmp_send (pkt, ip->destination, ip->source, len);
           icmp_print (2, _LANG("PING reply sent"), 0);
         }
         return;

    case ICMP_TIMXCEED:
         if (code >= DIM(icmp_exceed_str))
         {
           STAT (icmpstats.icps_badcode++);
           return;
         }
         STAT (icmpstats.icps_inhist[ICMP_TIMXCEED]++);

         if (code != 1)
            switch (orig_ip->proto)
            {
#if !defined(USE_UDP_ONLY)
              case TCP_PROTO:
                   icmp_print (1, icmp_exceed_str[code], ip->source);
                   _tcp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0);
                   break;
#endif
              case UDP_PROTO:
                   icmp_print (1, icmp_exceed_str[code], ip->source);
                   _udp_cancel (orig_ip, ICMP_TIMXCEED, NULL, 0);
                   break;
            }
         return;

    case ICMP_PARAMPROB:
         STAT (icmpstats.icps_inhist[ICMP_PARAMPROB]++);
         switch (orig_ip->proto)
         {
#if !defined(USE_UDP_ONLY)
           case TCP_PROTO:
                icmp_print (0, _LANG(icmp_type_str[type]), ip->source);
                _tcp_cancel (orig_ip, type, NULL, 0);
                break;
#endif
           case UDP_PROTO:
                icmp_print (0, _LANG(icmp_type_str[type]), ip->source);
                _udp_cancel (orig_ip, type, NULL, 0);
                break;
         }
         return;

    case ICMP_ROUTERADVERT:  /* todo !! */
         STAT (icmpstats.icps_inhist[ICMP_ROUTERADVERT]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         return;

    case ICMP_ROUTERSOLICIT: /* todo !! */
         STAT (icmpstats.icps_inhist[ICMP_ROUTERSOLICIT]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         return;

    case ICMP_TSTAMP:
         STAT (icmpstats.icps_inhist[ICMP_TSTAMP]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, send reply? */
         return;

    case ICMP_TSTAMPREPLY:
         STAT (icmpstats.icps_inhist[ICMP_TSTAMPREPLY]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, should store */
         return;

    case ICMP_IREQ:
         STAT (icmpstats.icps_inhist[ICMP_IREQ]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, send reply */
         return;

    case ICMP_IREQREPLY:
         STAT (icmpstats.icps_inhist[ICMP_IREQREPLY]++);
         icmp_print (1, _LANG(icmp_type_str[type]), ip->source);
         /* todo!!, send reply upwards */
         return;

    case ICMP_MASKREQ:
         STAT (icmpstats.icps_inhist[ICMP_MASKREQ]++);
         break;

    case ICMP_MASKREPLY:
         STAT (icmpstats.icps_inhist[ICMP_MASKREPLY]++);
         icmp_print (0, _LANG(icmp_type_str[type]), ip->source);
         if ((icmp->mask.identifier == addr_mask_id)    &&
             (icmp->mask.sequence   == addr_mask_seq-1) &&
             sin_mask != intel(icmp->mask.mask))
            outsnl ("Conflicting net-mask from \"ICMP Addr Mask Reply\"\7");
         addr_mask_id = 0;
         return;
  }
}
Exemple #30
0
/**
 * \def loopback_device().
 *
 * We have been called with an IP-packet located on stack by `send_loopback()'
 * (in pcsed.c). Hence, it's safe to call _eth_send() again here.
 * MAC-header is in front of 'ip'.
 */
int loopback_device (in_Header *ip)
{
  int   ip_len = 0;
  DWORD ip_dst;
  DWORD ip_ofs;
  WORD  ip_flg;

  if (!(loopback_mode & LBACK_MODE_ENABLE))
     return (-1);

  if (ip->ver == 4)
  {
    int ip_hlen;

    if (!_chk_ip4_header(ip))       /* silently discard */
       return (-1);

    ip_hlen = in_GetHdrLen (ip);    /* length of IP-header (w/options) */
    ip_len  = intel16 (ip->length); /* total length of IP-packet */
    ip_dst  = ip->destination;

    ip->destination = ip->source;   /* swap source and destination */
    ip->source      = ip_dst;
    ip->checksum    = 0;
    ip->checksum    = ~CHECKSUM (ip, ip_hlen);   /* redo check-sum */

    ip_ofs = intel16 (ip->frag_ofs);
    ip_flg = (WORD) (ip_ofs & ~IP_OFFMASK);
    ip_ofs = (ip_ofs & IP_OFFMASK) << 3; /* 0 <= ip_ofs <= 65536-8 */

    if (ip_ofs || (ip_flg & IP_MF)) /* fragment; let ip4_defragment() */
       return (ip_len);             /* handle it on next poll */

    if (ip->proto == ICMP_PROTO)
    {
      ICMP_PKT *icmp = (ICMP_PKT*) ((BYTE*)ip + ip_hlen);
      int       len  = icmp_loopback (icmp, ip_len - ip_hlen);

      if (len > 0)
         return (ip_hlen+len);
    }
    else if (ip->proto == UDP_PROTO)
    {
      udp_Header *udp = (udp_Header*) ((BYTE*)ip + ip_hlen);
      int         len = udp_loopback (udp, ip_len-ip_hlen);

      if (len > 0)
         return (ip_hlen+len);
    }
  }
#if defined(USE_IPV6)
  else if (ip->ver == 6)
  {
    in6_Header *ip6 = (in6_Header*)ip;
    ip6_address ip6_dst;

    ip_len = intel16 (ip6->len);
    memcpy (&ip6_dst, &ip6->destination, sizeof(ip6_dst));
    memcpy (&ip6->destination, &ip6->source, sizeof(ip6->destination));
    memcpy (&ip6->source, &ip6_dst, sizeof(ip6->source));

    if (ip6->next_hdr == IP6_NEXT_ICMP)
    {
      ICMP_PKT *icmp = (ICMP_PKT*) (ip6 + 1);
      int       len  = icmp_loopback (icmp, ip_len);

      if (len > 0)
         return (len + sizeof(*ip6));
    }
    else if (ip6->next_hdr == UDP_PROTO)
    {
      udp_Header *udp = (udp_Header*) (ip6 + 1);
      int         len = udp_loopback (udp, ip_len);

      if (len > 0)
         return (len + sizeof(*ip6));
    }
  }
  else
  {
    (*_printf) ("%s: Illegal IP-packet (ver %d) for loopback device\n",
                __FILE__, ip->ver);
    return (-1);
  }
#endif

  if (loopback_handler)
     ip_len = (*loopback_handler) (ip);
  return (ip_len);
}