Example #1
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);
}
Example #2
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));
}
Example #3
0
/*
 * igmp_handler - handles the incoming IGMP packets
 *
 * void igmp_handler (in_Header *ip)
 * Where:
 *      ip    is the IP packet in question
 *
 * Returns: None
 *
 */
void igmp_handler (const in_Header *ip, BOOL broadcast)
{
    BYTE         i;
    DWORD        host;
    BOOL         found = 0;
    WORD         len   = in_GetHdrLen (ip);
    IGMP_packet *igmp  = (IGMP_packet*) ((BYTE*)ip + len);

    DEBUG_RX (NULL, ip);

    if (len < sizeof(*igmp))
    {
        STAT (igmpstats.igps_rcv_tooshort++);
        return;
    }

    if (checksum(igmp,sizeof(*igmp)) != 0xFFFF)
    {
        STAT (igmpstats.igps_rcv_badsum++);
        return;
    }

    host = intel (igmp->address);

    /* Determine whether this is a report or a query
     */
    switch (igmp->type)
    {
    case IGMP_QUERY:
        STAT (igmpstats.igps_rcv_queries++);
        for (i = 0; i < IPMULTI_SIZE; i++)
            if (_ipmulti[i].active             &&
                    _ipmulti[i].ina != ALL_SYSTEMS &&
                    _ipmulti[i].replytime == 0)
            {
                _ipmulti[i].replytime = set_timeout (Random(500,1000));
                found = 1;
            }
        if (!found && !broadcast)
            STAT (igmpstats.igps_rcv_badqueries++);
        break;

    case IGMP_REPORT:
        STAT (igmpstats.igps_rcv_reports++);
        for (i = 0; i < IPMULTI_SIZE; i++)
            if (_ipmulti[i].active      &&
                    _ipmulti[i].ina == host &&
                    host != ALL_SYSTEMS)
            {
                _ipmulti[i].replytime = 0;
                found = 1;
                STAT (igmpstats.igps_rcv_ourreports++);
                break;
            }
        if (!found && !broadcast)
            STAT (igmpstats.igps_rcv_badreports++);
        break;
    }
}
Example #4
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);
}
Example #5
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));
}
Example #6
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));
}
Example #7
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);
}
Example #8
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;
  }
}
Example #9
0
/**
 * Handler for incoming ICMP packets.
 */
void icmp_handler (const in_Header *ip, BOOL broadcast)
{
  union ICMP_PKT  *icmp;
  const in_Header *orig_ip;
  int              type, code;
  unsigned         len;
  DWORD            delta_time;
  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 = _ip4_is_multihome_addr (intel(ip->destination));

  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  = _ip4_is_local_addr (intel(orig_ip->source));

  if (type == ICMP_MASKREPLY)
  {
    if (!_do_mask_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 */
         delta_time = set_timeout(0) - icmp->echo.identifier;
         add_ping (intel(ip->source), delta_time, icmp->echo.index);
         return;

    case ICMP_UNREACH:
         if (code < DIM(icmp_unreach_str))
         {
           UINT len_needed = 8 + in_GetHdrLen (orig_ip);
           WORD next_mtu   = 0;

           msg = _LANG (icmp_unreach_str[code]);
           icmp_print (1, msg, ip->source);

           if (orig_ip->proto == TCP_PROTO ||
               orig_ip->proto == UDP_PROTO)
              len_needed += 4;  /* Need the src/dest port numbers */

           if (len >= len_needed)
           {
             if (code == ICMP_UNREACH_NEEDFRAG)
                next_mtu = intel16 (icmp->needfrag.next_mtu);

#if !defined(USE_UDP_ONLY)
             if (orig_ip->proto == TCP_PROTO)
                _tcp_cancel (orig_ip, ICMP_UNREACH, code, msg, &next_mtu);
             else
#endif
             if (orig_ip->proto == UDP_PROTO)
                _udp_cancel (orig_ip, ICMP_UNREACH, code, msg, &next_mtu);

             /** \todo Handle cancelling raw sockets */
#if defined(USE_BSD_API) && 0  
             else
              _raw_cancel (orig_ip, ICMP_UNREACH, code, msg);
#endif
           }
           else
             STAT (icmpstats.icps_tooshort++);
         }
         else
           STAT (icmpstats.icps_badcode++);
         return;

    case ICMP_SOURCEQUENCH:
#if !defined(USE_UDP_ONLY)
         if (orig_ip->proto == TCP_PROTO)
         {
           msg = _LANG (icmp_type_str[type]);
           icmp_print (1, msg, ip->source);
           _tcp_cancel (orig_ip, ICMP_SOURCEQUENCH, code, msg, NULL);
         }
#endif
         return;

    case ICMP_REDIRECT:
         if (code < DIM(icmp_redirect_str))
              icmp_redirect (icmp, ip, orig_ip, code);
         else STAT (icmpstats.icps_badcode++);
         return;

    case ICMP_ECHO:
         icmp_print (2, _LANG("PING requested of us"), ip->source);
         icmp_echo_reply (ip, icmp, len);
         return;

    case ICMP_TIMXCEED:
         if (code >= DIM(icmp_exceed_str))
         {
           STAT (icmpstats.icps_badcode++);
           return;
         }
         if (code == 0)  /* "TTL exceeded in transit" */
            switch (orig_ip->proto)
            {
#if !defined(USE_UDP_ONLY)
              case TCP_PROTO:
                   msg = _LANG (icmp_exceed_str[0]);
                   icmp_print (1, msg, ip->source);
                   _tcp_cancel (orig_ip, ICMP_TIMXCEED, code, msg, NULL);
                   break;
#endif
              case UDP_PROTO:
                   msg = _LANG (icmp_exceed_str[0]);
                   icmp_print (1, msg, ip->source);
                   _udp_cancel (orig_ip, ICMP_TIMXCEED, code, msg, NULL);
                   break;
            }
         return;

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

    case ICMP_ROUTERADVERT:  /* todo !! */
         msg = _LANG (icmp_type_str[ICMP_ROUTERADVERT]);
         icmp_print (1, msg, ip->source);
         return;

    case ICMP_ROUTERSOLICIT: /* todo !! */
         msg = _LANG (icmp_type_str[ICMP_ROUTERSOLICIT]);
         icmp_print (1, msg, ip->source);
         return;

    case ICMP_TSTAMP:
         msg = _LANG (icmp_type_str[ICMP_TSTAMP]);
         icmp_print (1, msg, ip->source);
         /**< \todo send reply? */
         return;

    case ICMP_TSTAMPREPLY:
         msg = _LANG (icmp_type_str[ICMP_TSTAMPREPLY]);
         icmp_print (1, msg, ip->source);
         /**< \todo should store */
         return;

    case ICMP_IREQ:
         msg = _LANG (icmp_type_str[ICMP_IREQ]);
         icmp_print (1, msg, ip->source);
         /**< \todo send reply */
         return;

    case ICMP_IREQREPLY:
         msg = _LANG (icmp_type_str[ICMP_IREQREPLY]);
         icmp_print (1, msg, ip->source);
         /**< \todo send reply upwards */
         return;

    case ICMP_MASKREQ:
         /* might be sent by us, never answer */
         break;

    case ICMP_MASKREPLY:
         msg = _LANG (icmp_type_str[ICMP_MASKREPLY]);
         icmp_print (0, msg, 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;
  }
}