コード例 #1
0
ファイル: rfsim.c プロジェクト: fjanssen/Car2X
int
simquit(void * pio)
{
   PACKET   pkt;
   ip_addr  hop;
   struct ip * pip;
   
   if(simtimer)
   {
      in_timerkill(simtimer);
      simtimer = 0;
   }

   /* send all queued packets */
   while(simq.q_head)
   {
      pkt = (PACKET)getq(&simq); /* get pkt to send */
      hop = pkt->fhost;          /* get hop from host field */
      pip = ip_head(pkt);        /* get real host address */
      pkt->fhost = pip->ip_dest; /* restore host field */
      ip2mac(pkt, hop);          /* send pkt to hardware */
   }
   rfsim_routing = FALSE;
   ns_printf(pio, "rfsim stopped\n");
   return 0;
}
コード例 #2
0
ファイル: rfsim.c プロジェクト: fjanssen/Car2X
void
rfsim_timer()
{
   ip_addr     hop;
   struct ip * pip;
   PACKET      pkt;

   /* send al packets which have timed out */
   while(((PACKET)(simq.q_head))->nb_tstamp < cticks)
   {
      pkt = (PACKET)getq(&simq); /* get pkt to send */
      hop = pkt->fhost;          /* get hop from host field */
      pip = ip_head(pkt);        /* get real host address */
      pkt->fhost = pip->ip_dest; /* restore host field */
      simpkts++;

      /* see if it's time to drop a packet */
      if((lossrate) && 
         ((simpkts - simlastloss) > lossrate) && 
         ((cticks & deviation) == 1))
      {
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pk_free(pkt);           /* drop instead of send */
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         simlastloss = simpkts;  /* reset drop timer */
         simdrops++;             /* count drops */
      }
      else
         ip2mac(pkt, hop);          /* send pkt to hardware */
   }
   return;
}
コード例 #3
0
ファイル: igmp2.c プロジェクト: ECE492W2014G4/G4Capstone
int igmpv2_input (PACKET p)
{
   struct igmp * igmp;
   struct ip * pip;
   int igmplen;
   u_char type;
   int rc;

   pip = ip_head (p);    
   /* compute length of IGMP packet (after accounting for IP header, 
    * including the IP Router Alert option (if present)) */   
   igmplen = p->nb_plen - ip_hlen (pip);
   igmp = (struct igmp *) (ip_data (pip));   
   /* extract the IGMP packet type from received packet */
   type = igmp->igmp_type;

   switch (type) 
   {
      case IGMP_HOST_MEMBERSHIP_QUERY:
         rc = igmpv2_process_query (p);
         break;

      case IGMP_HOST_MEMBERSHIP_REPORT:
      case IGMPv2_MEMBERSHIP_REPORT:
         rc = igmpv2_process_report (p);
         break;
         
      case IGMPv2_LEAVE_GROUP:
         /* Leave messages are typically addressed to the all-routers 
          * multicast address group (224.0.0.2).  We do not implement 
          * multicast router functionality, and therefore, do not 
          * expect to receive such messages.  However, according to
          * RFC 2236, some implementations of an older version of the 
          * IGMPv2 specification send leave messages to the group 
          * being left.  If we do receive such a message, we will 
          * drop it. */       
         ++igmpstats.igmpv2mode_v2_leave_msgs_rcvd;
         rc = IGMP_OK;
         break;               

      default:     
         ++igmpstats.igmpv2mode_unknown_pkttype;
         rc = IGMP_ERR;         
         break;
   } /* end SWITCH */

   /* we're done processing the received packet; return packet buffer 
    * back to free pool */
   LOCK_NET_RESOURCE(FREEQ_RESID);
   pk_free(p);
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
   
   return rc;
}
コード例 #4
0
ファイル: igmp_cmn.c プロジェクト: ECE492W2014G4/G4Capstone
int igmp_validate (PACKET p)
{
    struct ip * pip;
    int igmplen;
    struct igmp * igmp;
    u_short osum;
    u_short xsum;
    u_char type;
    ip_addr mcgrp_addr;
    u_char resp_time;

    pip = ip_head (p);

    /* compute length of IGMP packet (after accounting for IP header,
     * including the IP Router Alert option (if present)) */
    igmplen = p->nb_plen - ip_hlen (pip);

    /* validate length (IGMP_MINLEN is 8 bytes) */
    if (igmplen != IGMP_MINLEN)
    {
        ++igmpstats.igmp_badlen_rcvd;
        return ENP_BAD_HEADER;
    }

    /* validate checksum */
    igmp = (struct igmp *) (ip_data (pip));
    osum = igmp->igmp_cksum;
    igmp->igmp_cksum = 0;
    xsum = ~cksum(igmp, igmplen>>1);
    if (xsum != osum)
    {
        igmp->igmp_cksum = osum;
        ++igmpstats.igmp_badsum_rcvd;
        return ENP_BAD_HEADER;
    }

    /* extract the IGMP packet type, Group Address, and Max Response Time
     * (unused for IGMPv1) fields from received packet */
    type = igmp->igmp_type;
    mcgrp_addr = ntohl(igmp->igmp_group);
    resp_time = igmp->igmp_code;

    if (type == IGMP_HOST_MEMBERSHIP_QUERY)
    {
        if ((resp_time == 0) || /* IGMPv1 Query */
                ((resp_time > 0) && (mcgrp_addr == 0))) /* IGMPv2 General Query */
        {
            /* if this is a IGMPv1 Host Membership Query or a IGMPv2
             * General Query, it must be addressed to the all-hosts
             * group */
            if (pip->ip_dest != igmp_all_hosts_group)
            {
                ++igmpstats.igmp_bad_queries_rcvd;
                return ENP_BAD_HEADER;
            }
        }

        if ((resp_time > 0) && (mcgrp_addr != 0))
        {
            /* this is a IGMPv2 Group-Specific Query. */
            if (p->net->igmp_oper_mode == IGMP_MODE_V1)
            {
                /* IGMPv1 code does not understand a IGMPv2 Group-
                 * Specific Query */
                return ENP_BAD_HEADER;
            }

            /* check to make sure that the group address field carries
             * a valid multicast address; if it doesn't, we
             * drop the packet.  Also drop packets that
             * carry the multicast address for the all-hosts
             * group. */
            if ((!IN_MULTICAST(mcgrp_addr)) ||
                    /* igmp_all_hosts_group is already in network byte order */
                    (igmp->igmp_group == igmp_all_hosts_group))
            {
                ++igmpstats.igmpv2mode_v2_bad_grp_specific_queries_rcvd;
                /* caller will free received packet */
                return ENP_BAD_HEADER;
            }
        }
    }

    /* check to ensure that a received IGMPv1 or v2 Report has the
     * same IP host group address in its IP destination field and
     * its IGMP group address field, and that the group address is
     * a valid multicast address */
    if ((type == IGMP_HOST_MEMBERSHIP_REPORT) ||
            (type == IGMPv2_MEMBERSHIP_REPORT))
    {
        if ((igmp->igmp_group != pip->ip_dest) ||
                (!IN_MULTICAST(mcgrp_addr)))
        {
            ++igmpstats.igmp_bad_reports_rcvd;
            return ENP_BAD_HEADER;
        }
    }

    /*
     * After receiving an IGMP packet, our IGMP module will check for the
     * presence of the Router Alert option in the following types of
     * packets.  Packets that do not have the option will be discarded.

     * (a) Version 2 General Query (0x11) (differentiated from a Version 1
           Host Membership Query by having a Max Response Time > 0)
     * (b) Version 2 Group-Specific Query (0x11)
     * (c) Version 2 Membership Report (0x16)
     * (d) Version 2 Leave Group (0x17)

     * Version 1 Host Membership Reports and Version 1 Host Membership Query
     * packets will not be checked for the IP Router Alert option.
     */
#ifdef IGMP_V2
    if ((type == IGMPv2_LEAVE_GROUP) ||
            (type == IGMPv2_MEMBERSHIP_REPORT) ||
            ((type == IGMP_HOST_MEMBERSHIP_QUERY) && (igmp->igmp_code > 0)))

    {
        if (!igmpv2_chk4_rtr_alert_opt (pip))
        {
            ++igmpstats.igmpv2mode_v2_rtr_alert_missing;
            return ENP_BAD_HEADER;
        }
    }
#endif

    /* validation successful */
    return IGMP_OK;
}
コード例 #5
0
ファイル: igmp2.c プロジェクト: ECE492W2014G4/G4Capstone
int igmpv2_process_query (PACKET p)
{
   struct igmp * igmp;
   struct ip * pip;
   NET netp;
   u_short max_resp_time;
   u_char process_all;
   struct in_multi * inm;
   ip_addr mcgrp_addr;

   netp = p->net;
   pip = ip_head (p);
   igmp = (struct igmp *) (ip_data (pip));
   mcgrp_addr = ntohl(igmp->igmp_group);

   if (igmp->igmp_code == 0)
   {
      /* this is a IGMPv1 Host Membership Query */
      netp->igmpv1_rtr_present = IGMP_TRUE;
      netp->igmpv1_query_rcvd_time = cticks;      
      ++igmpstats.igmpv2mode_v1_queries_rcvd;
      /* set maximum time to respond to the equivalent of 10 
       * seconds worth of "ticks" (the timeout routine is
       * intended to be invoked PR_FASTHZ (5) times a second,
       * so each tick is equal to 200 ms) */
      max_resp_time = IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ;
      process_all = IGMP_TRUE;
   }
   else
   {
      /* this is either a IGMPv2 General Query or 
       * a IGMPv2 Group-Specific Query */
      if (igmp->igmp_group == 0)
      {
         /* this is a IGMPv2 General Query */
         ++igmpstats.igmpv2mode_v2_general_queries_rcvd;
         process_all = IGMP_TRUE;
      }
      else
      {
         /* this is a IGMPv2 Group-Specific Query */       
         ++igmpstats.igmpv2mode_v2_grp_specific_queries_rcvd;
         process_all = IGMP_FALSE;
      }
      
      /* irrespective of whether received message is a 
       * IGMPv2 General Query or a IGMPv2 Group-Specific Query,
       * set maximum time to respond to value extracted 
       * from received message. The value in the message
       * is in tenths of a second.  max_resp_time is in
       * units of ticks (where one tick is 200 ms) */
      max_resp_time = (igmp->igmp_code * PR_FASTHZ) / 10;
   }
   
   /* process all entries in a link's multicast address linked
    * list (pointed to by mc_list) as part of the response to
    * the received IGMPv1 Host Membership Query or IGMPv2 General
    * Query message */
   if (process_all)
   {
      for (inm = netp->mc_list; inm; inm = inm->inm_next)
      {
         /* skip all IPv6 entries - they are indicated by 
          * an IPv4 address field of 0 */
         if (!(inm->inm_addr)) continue;
         /* skip IPv4 multicast address of 224.0.0.1 (note that
          * the IPv4 address stored in inm_addr is in network 
          * byte order */
         if (inm->inm_addr != igmp_all_hosts_group)
            igmpv2_chk_set_timer (inm, max_resp_time);
      } /* end FOR (iterate thru' mc_list on net) */
   } /* end IF (process all) */
   else
   {
      /* process one (for IGMPv2 Group-Specific Query) entry (the 
       * one that corresponds to the address listed in the received 
       * query) - it should be present in the link's multicast
       * address list */
      inm = lookup_mcast(igmp->igmp_group, netp);
      if (inm != NULL)
         igmpv2_chk_set_timer (inm, max_resp_time);
      else ++igmpstats.igmpv2mode_v2_unknown_grp_specific_queries_rcvd;
   } /* end ELSE (process ALL) */
   
   /* return success; caller will the received packet back to the 
    * free pool */
   return IGMP_OK;
}
コード例 #6
0
ファイル: igmp2.c プロジェクト: ECE492W2014G4/G4Capstone
int igmpv2_process_report (PACKET p)
{
   struct igmp * igmp;
   struct ip * pip;
   NET netp;
   struct in_multi * inm;

   netp = p->net;
   pip = ip_head (p);
   igmp = (struct igmp *) (ip_data (pip));   
   
   /* If we receive a IGMP (v1 or v2) report for a multicast group 
    * that we have a timer running for, the IGMPv2 specification 
    * requires that we stop the timer (and thereby cancel the 
    * future transmission of our report).
    
    * However, we will use the following table to guide our actions
    * instead.  Scenario #4 causes us to not cancel the timer, 
    * since we have received a IGMPv2 report, but we believe that 
    * the querier on the network is running IGMPv1, and therefore 
    * will not be able to understand the IGMPv2 report.  As a 
    * result, we let our timer run, and if it expires, we will 
    * send out a report.

    * The type of a received report can be determined by examining 
    * the first byte of the IGMP message.  This byte is 0x12 for a 
    * IGMPv1 Host Membership Report, and 0x16 for a Version 2 
    * Membership Report.
    
    * Scenario# igmpv1_rtr_present Type of rcvd report Cancel timer
    * =============================================================
    * 1         No                 IGMPv1              Yes 
    * 2         No                 IGMPv2              Yes
    * 3         Yes                IGMPv1              Yes
    * 4         Yes                IGMPv2              No

    * In scenario #1 and #2, we have a IGMPv2-capable router that 
    * can understand both IGMPv1 and IGMPv2 reports.  In scenario 
    * #3, we have a IGMPv1-capable router that can understand IGMPv1 
    * reports. In scenario #4, we have a IGMPv1-capable router that
    * cannot understand a IGMPv2 report.  It is possible that the 
    * IGMPv1-capable router in scenario #4 is also capable of 
    * processing IGMPv2 packets (it has "downgraded" itself because
    * there are IGMPv1 routers on that network); however, we do not
    * know that, and hence we don't cancel our timer (for the 
    * subsequent transmission of a IGMPv1 report).
    */
   inm = lookup_mcast(igmp->igmp_group, netp);
   if (inm != NULL) 
   {
      if (inm->inm_timer != 0)
      {
         /* we have a timer running */
         if (!(netp->igmpv1_rtr_present && 
             igmp->igmp_type == IGMPv2_MEMBERSHIP_REPORT))
         {
            /* cancel timer */
            inm->inm_timer = 0;
            /* decrement the count of running timers */
            --igmp_timers_are_running;
            /* indicate that we are not the last host to send a 
             * report for this group */
            inm->last2send_report = IGMP_FALSE;
            ++igmpstats.igmpv2mode_v12_reports_rcvd_canceled_timer;
         }
      }
      else
      {
         /* we don't have a timer running; perhaps the source
          * host has just joined the group, and has sent an
          * unsolicited report */
         ++igmpstats.igmpv2mode_v12_reports_rcvd_no_timer;   
      }
   }
   else 
   {
      /* since the Reports are sent the group address, we should
       * never receive them unless we are a member of that group
       * on that interface.  Even if imperfect filtering at the 
       * device level causes reports for unregistered groups to 
       * be passed up to the IP module, ip_rcv_phase2 () is 
       * responsible for dropping them, and so we should never
       * receive such packets. */
      ++igmpstats.igmpv2mode_v12_unknown_grp_reports_rcvd;
   }
   
   return IGMP_OK;   
}
コード例 #7
0
ファイル: nptcp.c プロジェクト: ECE492W2014G4/G4Capstone
void
so_icmpdu(PACKET p, struct destun * pdp)
{
   ip_addr lhost;    /* IP address of originator (our iface) */
   ip_addr fhost;    /* IP address we sent to */
   unshort  fport;   /* TCP/UDP port we sent to */
   unshort  lport;   /* TCP/UDP port we sent from */
   struct inpcb * inp;
   struct socket *   so;
   struct tcpcb * tp;

   /* extract information about packet which generated DU */
   fhost = htonl(pdp->dip.ip_dest);
   lhost = htonl(pdp->dip.ip_src);
   lport = htons(*(unshort*)(&pdp->ddata[0]));
   fport = htons(*(unshort*)(&pdp->ddata[2]));

#ifndef IP_PMTU
   /* if it's a datagram-too-big message, ignore it -- As the
    * build isn't using PMTU Discovery this packet is most 
    * probably a Denial of Service Attack.
    */
    if(pdp->dcode == DSTFRAG)
    {
       goto done;
    }
#endif   /* IP_PMTU */

   /* if it's a TCP connection, clean it up */
   if (pdp->dip.ip_prot == TCPTP)
   {
      /* find associated data structs and socket */
      inp = in_pcblookup(&tcb, fhost, fport, lhost, lport, INPLOOKUP_WILDCARD);
      if (inp == 0)
         goto done;
      so = inp->inp_socket;
      if (so == 0)
         goto done;
      tp = intotcpcb(inp);
      if (tp)
      {
         if (tp->t_state <= TCPS_LISTEN)
         {
            goto done;
         }

#ifdef ICMP_TCP_DOS
         {
         struct ip * pip;
         struct tcpiphdr * ti;

         pip = ip_head(p);  /* find IP header */
         ti = (struct tcpiphdr *)p->nb_prot;

         if(!((tp->snd_una <=  ti->ti_seq) && (ti->ti_seq <= tp->snd_nxt)))
            goto done;

         /* If we get an ICMP Type 3 (Destination Unreachable) - Code 2
          * (Protocol Unreachable) message and during the life of a TCP
          * connection, then its most probably a Denial of Service Attack.
          * As the only other interpretation would be that the support for
          * the transport protocol has been removed from the host sending
          * the error message during the life of the corresponding 
          * connection. As in common practice this is higly unlikely in most
          * cases, we will treat this message as a DOS attack.
          */
         if(pdp->dcode == DSTPROT)
         {
            if((tp->t_state >= TCPS_ESTABLISHED) && (tp->t_state <= TCPS_TIME_WAIT))
               goto done;
         }

        /* Note some ICMP error messages generated by intermediate routers,
         * include more than the recommended 64 bits of the IP Data. If the
         * TCP ACK number happens to be present then use it in detecting a
         * Denial of Service attack.
         *
         * This way we can ensure that the TCP Acknowledgement number should
         * correspond to data that have already been acknowledged. This way
         * we can further reduce the possiblity of considering a spoofed ICMP
         * packet by a factor of 2.
         */
        if(pip->ip_len >= 32)
        {
            if(!(ti->ti_seq <= tp->rcv_nxt))
               goto done;
        }
   }
#endif

         tcp_close(tp);
      }
      so->so_error = ECONNREFUSED;  /* set error for socket owner */
   }   
#ifdef UDP_SOCKETS   /* this sockets layer supports UDP too */
   else if(pdp->dip.ip_prot == UDP_PROT)
   {
      UDPCONN tmp;
      /* search udp table (which keeps hosts in net endian) */
      for (tmp = firstudp; tmp; tmp = tmp->u_next)
         if ((tmp->u_fport == fport || tmp->u_fport == 0) &&
             (tmp->u_fhost == htonl(fhost)) &&
             (tmp->u_lport == lport))
         {
            break;   /* found our UDP table entry */
         }
      if (!tmp) 
         goto done;
      so = (struct socket *)tmp->u_data;
      /* May be non-socket (lightweight) UDP connection. */
      if (so->so_type != SOCK_DGRAM)
         goto done;
      so->so_error = ECONNREFUSED;  /* set error for socket owner */
      /* do a select() notify on socket here */
      sorwakeup(so);
      sowwakeup(so);
   }
#endif   /* UDP_SOCKETS */
   else
      goto done;

#ifdef IP_PMTU
   /* if this is a datagram-too-big message, update the Path MTU cache */
   if (pdp->dcode == DSTFRAG)
      pmtucache_set(pdp->dip.ip_dest, htons(pdp->dno2));
#endif   /* IP_PMTU */

done:
   LOCK_NET_RESOURCE(FREEQ_RESID);
   pk_free(p); /* done with original packet */
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
   return;
}