コード例 #1
0
void fastpath_fragmagic_uninit(SshFastpath fastpath)
{
  SshFastpathFragEntry frag;

  ssh_kernel_mutex_lock(fastpath->frag_lock);
  if (fastpath->frag_timeout_scheduled)
    {
      ssh_kernel_timeout_cancel(ssh_fastpath_fragmagic_timeout, 
				(void *)fastpath);
      fastpath->frag_timeout_scheduled = 0;
    }
  ssh_kernel_mutex_unlock(fastpath->frag_lock);

  /* Free fragments. */
  for (frag = fastpath->frag_data_lru_head; frag; frag = frag->data_lru_next)
    {
      SshInterceptorPacket pp, pp_next;

      for (pp = frag->pp_chain; pp; pp = pp_next)
        {
          pp_next = pp->next;

	  /* An exeption for using ssh_fastpath_fragmagic_packet_free. 
	     We are uninitialising here and we don't receive any more
	     packets. */
          ssh_interceptor_packet_free(pp);
        }
    }
}
コード例 #2
0
/*--------------------------------------------------------------------------*/
SshInterceptorPacket
ssh_flat_packet_to_icept_packet(const SshInterceptor interceptor,
                                const SshAdapter adapter,
                                unsigned char * flat_packet,
                                unsigned int flat_packet_size)
{
  SshInterceptorPacket pp;

  pp = ssh_interceptor_packet_alloc(interceptor, SSH_PACKET_FROMPROTOCOL,
                                    SSH_PROTOCOL_ETHERNET, adapter->ifnum,
				    SSH_INTERCEPTOR_INVALID_IFNUM,
                                    flat_packet_size);
  if (pp)
    {
      if (!ssh_interceptor_packet_copyin(pp, 0, flat_packet,
                                         flat_packet_size))
        {
          ssh_interceptor_packet_free(pp);
          pp = NULL;
        }
    }
  else
    {
      SSH_DEBUG(SSH_D_ERROR, ("Can not allocate new packet"));
    }

  return pp;
}
コード例 #3
0
/* Send a packet to the IP stack like it was received by the virtual
   IP interface indexed by pp->ifnum_in. */
void ssh_virtual_adapter_send(SshInterceptor interceptor,
			      SshInterceptorPacket pp)
{
  SshInterceptorInternalPacket ipp;
  VxWorksVa *va;
  M_BLK_ID m;

  if (!(va = vxworks_va_find_va(pp->ifnum_out)))
    {
      SSH_TRACE(
        SSH_D_ERROR,
        ("trying to send to a nonexistent ifnum %d", (int)pp->ifnum_out));

      ssh_interceptor_packet_free(pp);
      return;
    }

  if (pp->protocol != SSH_PROTOCOL_ETHERNET)
    {
      SSH_TRACE(SSH_D_ERROR, ("%s: dropping non-ethernet packet", va->name));

      ssh_interceptor_packet_free(pp);
      return;
    }

  ipp = (void *)pp;
  m = ipp->head;
  ipp->head = NULL;
  ssh_interceptor_packet_free_header(ipp);

  SSH_DEBUG(
    SSH_D_LOWOK,
    ("feeding receive packet to %s, ifnum %d", va->name, (int)va->ifnum));

  END_RCV_RTN_CALL(&va->end, m);
}
コード例 #4
0
static void
ssh_fastpath_fragmagic_free_packet_list(SshInterceptorPacket frag_free_list)
{
  SshInterceptorPacket pp;

  SSH_DEBUG(SSH_D_NICETOKNOW, ("Removing fragmagic free list %p.",
                               frag_free_list));

  while (frag_free_list)
    {
      pp = frag_free_list;
      frag_free_list = pp->next;
      ssh_interceptor_packet_free(pp);
    }
}
コード例 #5
0
Boolean 
ssh_engine_packet_start(SshEngine engine, SshInterceptorPacket pp,
			SshUInt32 tunnel_id, SshUInt32 prev_transform_index,
			SshUInt32 pc_flags)
{
  SshEnginePacketContext pc;
  SshEngineTransformData trd;
    
  SSH_DEBUG(SSH_D_LOWOK, ("Sending packet to the fastpath pp=%p, "
			  "tunnel_id=%d, prev_transform_index=%x",
			  pp, (int) tunnel_id,
			  (unsigned int) prev_transform_index));

  if (pp->flags & SSH_PACKET_FROMADAPTER)
    pp->flags |= SSH_ENGINE_P_FROMADAPTER;

  /* Allocate a packet context for the new packet. */  
  if ((pc = ssh_engine_alloc_pc(engine)) == NULL)
    {
      ssh_interceptor_packet_free(pp);
      return FALSE;
    }

  /* Initialize the new pc. */
  ssh_engine_init_pc(pc, engine, pp, tunnel_id, NULL);
  pc->flags = pc_flags;
  pc->prev_transform_index = prev_transform_index;

  /* Initialize transform_counter for outbound nested tunnel packets. */
  if (pc->flags & SSH_ENGINE_PC_RESTARTED_OUT
      && pc->prev_transform_index != SSH_IPSEC_INVALID_INDEX)
    {
      ssh_kernel_mutex_lock(engine->flow_control_table_lock);
      trd = FASTPATH_GET_READ_ONLY_TRD(engine->fastpath, 
				       pc->prev_transform_index);
      SSH_ASSERT(trd != NULL);
      SSH_ASSERT(trd->nesting_level > 0);
      pc->transform_counter = trd->nesting_level - 1;
      FASTPATH_RELEASE_TRD(engine->fastpath, pc->prev_transform_index);
      ssh_kernel_mutex_unlock(engine->flow_control_table_lock);
    }
  
  /* Send the packet to the fastpath. This will handle the packet as if
     it had just been received from the network. */
  engine_packet_continue(pc, SSH_ENGINE_RET_RESTART);
  return TRUE;
}
コード例 #6
0
ファイル: upper_edge.c プロジェクト: patrick-ken/kernel_808l
/*-------------------------------------------------------------------------
  ssh_driver_return_packet()

  Previously indicated NDIS packet is returned so that it can be reused.
  
  Arguments:
  miniport_context - virtual NIC object
  pkt - NDIS packet
        
  Returns:
  
  Notes:
  NDIS calls this function when the protocol layer above has processed
  the received packet and the resources allocated for the packet can be
  freed (reused).

  Default IRQL: DISPATCH_LEVEL
  -------------------------------------------------------------------------*/
static void
ssh_driver_return_packet(NDIS_HANDLE miniport_context,
                         NDIS_PACKET *ndis_pkt)
{
  SshNdisIMAdapter adapter = (SshNdisIMAdapter)miniport_context;
  SshNdisPacket packet;

#ifndef _WIN32_WCE
  SSH_ASSERT(SSH_GET_IRQL() == SSH_DISPATCH_LEVEL);
#endif /* _WIN32_WCE */
  SSH_ASSERT(adapter != NULL);
  SSH_ASSERT(ndis_pkt != NULL);

  packet = SSH_PACKET_CTX(ndis_pkt);

  ssh_interceptor_packet_free(&packet->ip);
}
コード例 #7
0
void
ssh_virtual_adapter_send(SshInterceptor interceptor,
			    SshInterceptorPacket pp)
{
  unsigned char *packet, *internal;
  size_t packet_len, internal_len;

  /* Linearize the packet. */

  packet_len = ssh_interceptor_packet_len(pp);
  packet = ssh_xmalloc(packet_len);

  ssh_interceptor_packet_copyout(pp, 0, packet, packet_len);

  if (!ssh_interceptor_packet_export_internal_data(pp, &internal,
                                                   &internal_len))
    return;

  SSH_DEBUG(SSH_D_NICETOKNOW, 
	    ("sending send request for virtual adapter %d to forwarder.",
	     (int) pp->ifnum_out));

  /* Send the packet to the kernel forwarder module. */
  ssh_usermode_interceptor_send_encode(
                        interceptor,
                        SSH_ENGINE_IPM_FORWARDER_VIRTUAL_ADAPTER_SEND,
			SSH_FORMAT_UINT32, pp->ifnum_in,
                        SSH_FORMAT_UINT32, pp->ifnum_out,
                        SSH_FORMAT_UINT32, pp->protocol,
                        SSH_FORMAT_UINT32_STR, packet, packet_len,
                        SSH_FORMAT_UINT32_STR, internal, internal_len,
                        SSH_FORMAT_END);

  /* Free the linearized packet. */
  ssh_xfree(packet);

  /* Free the original packet object. */
  ssh_interceptor_packet_free(pp);
}
コード例 #8
0
/* Dummy function which packets get routed to after ssh_interceptor_stop()
   has been called. */
static void
ssh_interceptor_dummy_packet_cb(SshInterceptorPacket pp, void *ctx)
{
  ssh_interceptor_packet_free(pp);
}
コード例 #9
0
void
ssh_virtual_adapter_send(SshInterceptor interceptor,
			 SshInterceptorPacket pp)
{
  SshVirtualAdapter adapter;
  SshInterceptorInternalPacket ipp = (SshInterceptorInternalPacket) pp;
  struct net_device_stats *stats;
  struct sk_buff *skb;

  local_bh_disable();
  ssh_kernel_mutex_lock(interceptor->interceptor_lock);
  adapter = ssh_virtual_adapter_ifnum_to_adapter(interceptor, pp->ifnum_out);
  if (adapter == NULL)
    {
      ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
      local_bh_enable();
      SSH_DEBUG(SSH_D_ERROR,
                ("Virtual adapter %d does not exist", (int)pp->ifnum_out));
      goto error;
    }

  /* Check the type of the source packet. */
  if (pp->protocol == SSH_PROTOCOL_ETHERNET)
    {
      /* We can send this directly. */
    }
  else if (pp->protocol == SSH_PROTOCOL_IP4
#ifdef SSH_LINUX_INTERCEPTOR_IPV6
           || pp->protocol == SSH_PROTOCOL_IP6
#endif /* SSH_LINUX_INTERCEPTOR_IPV6 */
	   )
    {
      unsigned char ether_hdr[SSH_ETHERH_HDRLEN];
      SshIpAddrStruct src;
      SshUInt16 ethertype = SSH_ETHERTYPE_IP;
      unsigned char *cp = NULL;
      size_t packet_len;

      /* Add ethernet framing. */

      /* Destination is virtual adapter's ethernet address. */
      memcpy(ether_hdr + SSH_ETHERH_OFS_DST, adapter->dev->dev_addr,
             SSH_ETHERH_ADDRLEN);

      /* Resolve packet's source and the ethernet type to use. */
      packet_len = ssh_interceptor_packet_len(pp);

      /* IPv4 */
      if (pp->protocol == SSH_PROTOCOL_IP4)
        {
          if (packet_len < SSH_IPH4_HDRLEN)
            {
	      ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
	      local_bh_enable();
              SSH_DEBUG(SSH_D_ERROR,
                        ("Packet is too short to contain IPv4 header"));
              goto error;
            }

	  /* Pullup requests data from the header of a writable skb. */
	  if (likely(skb_headlen(ipp->skb) >= SSH_IPH4_HDRLEN
		     && !skb_shared(ipp->skb) && 
		     SSH_SKB_WRITABLE(ipp->skb, SSH_IPH4_HDRLEN)))
	    cp = ipp->skb->data;

          if (cp == NULL)
	    {
	      ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
	      local_bh_enable();
	      goto error_already_freed;
	    }

          SSH_IPH4_SRC(&src, cp);
        }

#ifdef SSH_LINUX_INTERCEPTOR_IPV6
      /* IPv6 */
      else
        {
          if (packet_len < SSH_IPH6_HDRLEN)
            {
	      ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
	      local_bh_enable();
              SSH_DEBUG(SSH_D_ERROR,
                        ("Packet too short to contain IPv6 header"));
              goto error;
            }

	  if (likely(skb_headlen(ipp->skb) >= SSH_IPH6_HDRLEN
		     && !skb_shared(ipp->skb) && 
		     SSH_SKB_WRITABLE(ipp->skb, SSH_IPH6_HDRLEN)))
	    cp = ipp->skb->data;
	    
          if (cp == NULL)
	    {
	      ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
	      local_bh_enable();
	      goto error_already_freed;
	    }

          SSH_IPH6_SRC(&src, cp);
          ethertype = SSH_ETHERTYPE_IPv6;
        }
#endif /* SSH_LINUX_INTERCEPTOR_IPV6 */

      /* Finalize ethernet header. */
      ssh_virtual_adapter_ip_ether_address(&src,
                                           ether_hdr + SSH_ETHERH_OFS_SRC);
      SSH_PUT_16BIT(ether_hdr + SSH_ETHERH_OFS_TYPE, ethertype);

      /* Insert header to the packet. */
      cp = NULL;
      if (likely((skb_headroom(ipp->skb) >= 
		  (SSH_ETHERH_HDRLEN + SSH_INTERCEPTOR_PACKET_HARD_HEAD_ROOM))
		 && !skb_shared(ipp->skb) && SSH_SKB_WRITABLE(ipp->skb, 0)))
	cp = skb_push(ipp->skb, SSH_ETHERH_HDRLEN);

      if (cp == NULL)
	{
	  ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
	  goto error_already_freed;
	}
      memcpy(cp, ether_hdr, SSH_ETHERH_HDRLEN);

      /* Just to be pedantic. */
      pp->protocol = SSH_PROTOCOL_ETHERNET;
    }
  else
    {
      ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
      local_bh_enable();
      SSH_DEBUG(SSH_D_ERROR, ("Can not handle protocol %d", pp->protocol));
      goto error;
    }

  /* Tear off the internal packet from the generic SshInterceptorPacket. */
  skb = ipp->skb;
  ipp->skb = NULL;

  /* (re-)receive the packet via the interface; this should
     make the packet go back up the stack */
  skb->protocol = eth_type_trans(skb, adapter->dev);
  skb->dev = adapter->dev;

  /* Update per virtual adapter statistics. */ 
  stats = &adapter->low_level_stats;
  stats->rx_packets++;
  stats->rx_bytes += skb->len;

  ssh_kernel_mutex_unlock(interceptor->interceptor_lock);
  local_bh_enable();

  /* Send the skb up towards stack. If it is IP (or ARP), it will be 
     intercepted by ssh_interceptor_packet_in. */
  netif_rx(skb);
  
  /* Put the packet header on freelist. */
  ssh_interceptor_packet_free((SshInterceptorPacket) ipp);
  return;
  
 error:
  ssh_interceptor_packet_free(pp);

 error_already_freed:
  return;
}
コード例 #10
0
ファイル: interceptor.c プロジェクト: patrick-ken/kernel_808l
/*--------------------------------------------------------------------------
  ssh_interceptor_send()
  
  Sends packet either down to the network or up to the protocol.
  --------------------------------------------------------------------------*/
void
ssh_interceptor_send(SshInterceptor interceptor,
                     SshInterceptorPacket ip,
                     size_t media_header_len)
{
  SshNdisPacket packet;
  ULONG first_buf_len = SSH_ETHERH_HDRLEN;
  SshNdisIMAdapter adapter;
  SshCpuContext cpu_ctx;
  Boolean use_one_buffer = FALSE;
  ULONG new_value;

  /* Sanity checks for arguments */
  SSH_ASSERT(interceptor != NULL);
  SSH_ASSERT(ip != NULL);
  SSH_ASSERT((ip->flags & SSH_PACKET_FROMADAPTER) !=
              (ip->flags & SSH_PACKET_FROMPROTOCOL));
#ifndef _WIN32_WCE
  SSH_ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
#endif /* _WIN32_WCE */

  cpu_ctx = &interceptor->cpu_ctx[ssh_kernel_get_cpu()];

  packet = CONTAINING_RECORD(ip, SshNdisPacketStruct, ip);

#ifdef DEBUG_LIGHT
  packet->f.flags.in_engine = 0;
#endif /* DEBUG_LIGHT */

  adapter = (SshNdisIMAdapter)packet->adapter_in;

  /* Check if adapter where the packet should be sent is
     different where the packet originated from */
  if (adapter && (adapter->ifnum == ip->ifnum_out))
    {
      new_value = InterlockedIncrement(&adapter->ref_count);
      packet->adapter_out = (SshAdapter)adapter;
    }
  else
    {
      SshAdapter gen_adapter = NULL;

      if (ip->ifnum_out < SSH_INTERCEPTOR_MAX_ADAPTERS)
        {
          ssh_kernel_rw_mutex_lock_read(&interceptor->adapter_lock);
          gen_adapter = interceptor->adapter_table[ip->ifnum_out];
          if (gen_adapter)
            {
              new_value = InterlockedIncrement(&gen_adapter->ref_count);
              packet->adapter_out = gen_adapter;
            }
          ssh_kernel_rw_mutex_unlock_read(&interceptor->adapter_lock);
        }

      if (gen_adapter == NULL)
        goto free_packet;

      adapter = (SshNdisIMAdapter)gen_adapter;
    }
  SSH_ASSERT(new_value > 0);

  /* Check that active adapter found and it supports the protocol */
  if (!ssh_adapter_is_enabled((SshNdisIMAdapter)adapter))
    {
      SSH_DEBUG(SSH_D_FAIL, ("active network connection not found"));
      goto free_packet;
    }

#ifndef _WIN32_WCE
  /* Check if packet is plain IPv4 (IPv6) and then add ethernet framing */
  if (ip->protocol == SSH_PROTOCOL_IP4 || ip->protocol == SSH_PROTOCOL_IP6)
    {
      if (!ssh_wan_packet_encapsulate((SshAdapter)adapter, ip))
        {
          SSH_DEBUG(SSH_D_FAIL, ("packet framing failed"));
          goto free_packet;
        }

      /* Some dial-up drivers seem to expect to receive whole packet in one
         NDIS buffer. */
      if (ip->flags & SSH_PACKET_FROMADAPTER)
        use_one_buffer = TRUE;
    }
#endif /* _WIN32_WCE */

  /* Add the VLAN tagging, if any */
  if (packet->vlan_tag_count > 0)
    {
      if (adapter != (SshNdisIMAdapter)packet->adapter_in)
        {
          /* Engine forwards this packet to different interface. Check 
             whether this is VLAN/QoS enabled interface and reconstruct
             tagging accordingly. */

          switch (adapter->options 
                  & (NDIS_MAC_OPTION_8021Q_VLAN
                     | NDIS_MAC_OPTION_8021P_PRIORITY))
            {
            case 0:
              /* Adapter doesn't support IEEE 802.1q/p; drop VLAN tag(s). */
              packet->vlan_tag_count = 0;
              break;

            case NDIS_MAC_OPTION_8021P_PRIORITY:
              /* Adapter supports only priority (QoS) tagging. */
              packet->vlan_tags[0].vlan_id = 0;
              packet->vlan_tag_count = 1;
              break;

            default:
              /* Adapter supports also VLAN. Change the VLAN ID of the
                 first tag to the one configued to this NIC driver. */
              packet->vlan_tags[0].vlan_id = adapter->vlan_id;
              break;
            }
        }

      if (packet->vlan_tag_count)
        {
          unsigned char *vlan_tags;
          SshUInt16 i;

          vlan_tags = 
            ssh_interceptor_packet_insert(ip, SSH_ETHERH_OFS_TYPE,
                                          packet->vlan_tag_count * 4);
          if (vlan_tags == NULL)
            {
              SSH_DEBUG(SSH_D_FAIL, ("Failed to add VLAN tags"));
              return;
            }

          for (i = 0; i < packet->vlan_tag_count; i++)
            {
              unsigned char *tag = vlan_tags + (i * 4);

              SSH_PUT_16BIT(tag, SSH_ETHERTYPE_VLAN);
              SSH_PUT_16BIT((tag + 2), 
                            (packet->vlan_tags[i].vlan_id << 4
                            | packet->vlan_tags[i].qos));
            }
        }
    }

  NDIS_SET_PACKET_HEADER_SIZE(packet->np, SSH_ETHERH_HDRLEN);
  NDIS_SET_PACKET_STATUS(packet->np, NDIS_STATUS_SUCCESS);

#ifdef _WIN32_WCE
  if (adapter->media == NdisMediumWan)
    {
      if (ip->flags & SSH_PACKET_FROMPROTOCOL)
        {
          if (!ssh_wan_send_to_adapter(adapter, packet, ip->protocol))
            SSH_DEBUG(SSH_D_FAIL, ("Cannot send packet to WAN adapter"));
        }
      else if (ip->flags & SSH_PACKET_FROMADAPTER)
        {
          if (!ssh_wan_send_to_protocol(adapter, packet, ip->protocol))
            SSH_DEBUG(SSH_D_FAIL, ("Cannot send packet to WAN protocol"));
        }
      else
        {
          SSH_DEBUG(SSH_D_ERROR, ("Dropping WAN packet without direction"));
        }
      ssh_interceptor_packet_free(&packet->ip);
      return;
    }
#endif /* _WIN32_WCE */

  if (ip->flags & SSH_PACKET_FROMPROTOCOL)
    {
      NDIS_STATUS status;

      /* Send packet to network */
      NdisSetPacketFlags(packet->np, NDIS_FLAGS_DONT_LOOPBACK);

      if (cpu_ctx->in_packet_cb 
	  || cpu_ctx->in_route_cb
	  || cpu_ctx->in_timeout_cb)
        {
          SSH_DEBUG(SSH_D_NICETOKNOW, 
                    ("Risk for recursive call; enqueueing packet 0x%p",
                     packet));

#ifdef DEBUG_LIGHT
          packet->f.flags.in_send_queue = 1;
#endif /* DEBUG_LIGHT */
	  if (cpu_ctx->in_packet_cb)
	    {
	      ssh_net_packet_enqueue(&cpu_ctx->send_queue[adapter->ifnum],
				     (SshNetDataPacket)packet);
	      cpu_ctx->packets_in_send_queue = 1;
	    }
	  else if (cpu_ctx->in_route_cb)
	    {
	      ssh_net_packet_enqueue(&cpu_ctx->route_send_queue[adapter->ifnum],
				     (SshNetDataPacket)packet);
	      cpu_ctx->packets_in_route_send_queue = 1;
	    }
	  else if (cpu_ctx->in_timeout_cb)
	    {
	      ssh_net_packet_enqueue(
                             &cpu_ctx->timeout_send_queue[adapter->ifnum],
			     (SshNetDataPacket)packet);
	      cpu_ctx->packets_in_timeout_send_queue = 1;
	    }
        }
      else
        {
#ifdef DEBUG_LIGHT
          SSH_DEBUG(SSH_D_NICETOKNOW, 
                    ("Sending packet 0x%p to underlying driver",
                     packet));

          packet->f.flags.in_miniport = 1;
#endif /* DEBUG_LIGHT */
          NdisSend(&status, adapter->binding_handle, packet->np);

          if (status != NDIS_STATUS_PENDING)
            {
              SSH_DEBUG(SSH_D_NICETOKNOW,
                        ("Send operation completed synchronously; "
                         "packet=0x%p, status=%@",
                         ssh_ndis_status_render, status));
              ssh_interceptor_packet_free(&packet->ip);
            }
        }
    }
  else if (ip->flags & SSH_PACKET_FROMADAPTER)
    {
      /* Packet is ready now so check packet consistency */
      if (use_one_buffer)
        first_buf_len = packet->packet_len;
      else
        first_buf_len += adapter->lookahead_size;
      first_buf_len = MIN(first_buf_len, packet->packet_len);
        
      if (!ssh_packet_get_contiguous_data((SshNetDataPacket)packet, 
                                          0, first_buf_len, FALSE))
        {
          SSH_DEBUG(SSH_D_FAIL, ("Invalid packet"));
          goto free_packet;
        }

      if (cpu_ctx->in_packet_cb
	  || cpu_ctx->in_route_cb
	  || cpu_ctx->in_timeout_cb)
        {
          SSH_DEBUG(SSH_D_NICETOKNOW, 
                    ("Risk for recursive call; enqueueing packet 0x%p",
                     packet));

#ifdef DEBUG_LIGHT
          packet->f.flags.in_recv_queue = 1;
#endif /* DEBUG_LIGHT */
	  if (cpu_ctx->in_packet_cb)
	    {
	      ssh_net_packet_enqueue(&cpu_ctx->recv_queue[adapter->ifnum],
				     (SshNetDataPacket)packet);
	      cpu_ctx->packets_in_recv_queue = 1;
	    }
	  else if (cpu_ctx->in_route_cb)
	    {
	      ssh_net_packet_enqueue(&cpu_ctx->route_recv_queue[adapter->ifnum],
				     (SshNetDataPacket)packet);
	      cpu_ctx->packets_in_route_recv_queue = 1;
	    }
	  else if (cpu_ctx->in_timeout_cb)
	    {
	      ssh_net_packet_enqueue(
			     &cpu_ctx->timeout_recv_queue[adapter->ifnum],
			     (SshNetDataPacket)packet);
	      cpu_ctx->packets_in_timeout_recv_queue = 1;
	    }
        }
      else
        {
          SSH_DEBUG(SSH_D_NICETOKNOW, 
                    ("Indicating packet 0x%p to upper layers",
                     packet));

#ifdef DEBUG_LIGHT
          packet->f.flags.in_protocol = 1;
#endif /* DEBUG_LIGHT */
          NdisMIndicateReceivePacket(adapter->handle, &packet->np, 1);
        }
    }
  else
    {
      SSH_NOTREACHED;
    }

  return;

 free_packet:
  /* Otherwise just drop the packet */
  SSH_DEBUG(SSH_D_FAIL, ("ssh_interceptor_send(): dropping packet"));
  ssh_interceptor_packet_free(&packet->ip);
}
コード例 #11
0
void ssh_engine_test_basic(SshEngine engine, SshUInt32 flags)
{
    SshUInt32 pass, packetflags, proto, ifnum_in, ifnum_out, sum, offset;
    SshUInt32 i;
    size_t seglen, prevseglen, len, iterlen;
    unsigned char *seg, *prevseg;
    SshInterceptorPacket pp;

    engine->test = "basic";

    SSH_DEBUG(0, ("testing basic packet processing functions"));
    for (pass = 0; pass < 1000; pass++)
    {
        if (pass % 100 == 0)
            SSH_DEBUG(0, ("pass=%d", (int)pass));

        /* Compute packet length.  We want to test all small values, and
           others at random. */
        if (ssh_rand() % 2 == 0)
            packetflags = SSH_PACKET_FROMADAPTER;
        else
            packetflags = SSH_PACKET_FROMPROTOCOL;
        if (pass < 300)
            len = pass;
        else
            len = ssh_rand() % 100000;
        ifnum_in = ssh_rand() % ((SshInterceptorIfnum) 0xffffffff);
        ifnum_out = ssh_rand() % ((SshInterceptorIfnum) 0xffffffff);
        proto = SSH_PROTOCOL_IP4;
        SSH_DEBUG(1, ("packetflags 0x%lx, len %ld, proto %d",
                      (long)packetflags, (long)len, (int)proto));
        pp = ssh_interceptor_packet_alloc(engine->interceptor,
                                          packetflags, proto,
                                          ifnum_in, ifnum_out, len);
        if (pp == NULL)
        {
            ssh_engine_test_fail(engine, "packet_alloc returned NULL");
            return;
        }
        if ((pp->flags &
                (0xffffff00|SSH_PACKET_FROMPROTOCOL|SSH_PACKET_FROMADAPTER)) !=
                packetflags)
        {
            ssh_engine_test_fail(engine, "packet_alloc flags not properly set");
            ssh_interceptor_packet_free(pp);
            return;
        }
        /* Add all flags reserved to the engine so that the interceptor cannot
           use them for anything. */
        pp->flags |= 0xffffff00;

        /* Check protocol and ifnum. */
        if (pp->protocol != proto)
        {
            ssh_engine_test_fail(engine, "packet_alloc proto not properly set");
            ssh_interceptor_packet_free(pp);
            return;
        }
        if (pp->ifnum_in != ifnum_in)
        {
            ssh_engine_test_fail(engine,
                                 "packet_alloc ifnum_in not properly set");
            ssh_interceptor_packet_free(pp);
            return;
        }
        if (pp->ifnum_out != ifnum_out)
        {
            ssh_engine_test_fail(engine,
                                 "packet_alloc ifnum_out not properly set");
            ssh_interceptor_packet_free(pp);
            return;
        }

        /* Check that packet length is correctly returned. */
        if (ssh_interceptor_packet_len(pp) != len)
        {
            ssh_engine_test_fail(engine, "packet_alloc returned wrong len %ld "
                                 "should have been %ld",
                                 (long)ssh_interceptor_packet_len(pp),
                                 (long)len);
            ssh_interceptor_packet_free(pp);
            return;
        }

        if (flags & SSH_INTERCEPTOR_TEST_BASIC_ITERATE)
        {
            SSH_DEBUG(1, ("iterating"));

            for (i = 0; i < 10; i++)
            {
                offset = ssh_rand() % (len + 1);
                iterlen = ssh_rand() % (len - offset + 1);
                SSH_ASSERT(offset + iterlen <= len);
                sum = 0;
                prevseg = NULL;
                prevseglen = 0;
                ssh_interceptor_packet_reset_iteration(pp, offset, iterlen);
                while (ssh_interceptor_packet_next_iteration(pp, &seg, &seglen))
                {
                    if (prevseg && prevseglen != 0)
                        if (prevseg[0] != (prevseglen & 0xff))
                        {
                            ssh_engine_test_fail(engine,
                                                 "iter pointer not preserved");
                            ssh_interceptor_packet_free(pp);

                            return;
                        }

                    sum += seglen;
                    memset(seg, seglen & 0xff, seglen);
                    prevseg = seg, prevseglen = seglen;
                }
                if (seg != NULL)
                {
                    ssh_engine_test_fail(engine, "next iteration fails");
                    return;
                }
                if (sum != iterlen)
                {
                    ssh_engine_test_fail(engine, "iteration test fails");
                    ssh_interceptor_packet_free(pp);
                    return;
                }
            }
        }

        if (flags & SSH_INTERCEPTOR_TEST_BASIC_PREPEND)
        {
            SSH_DEBUG(1, ("inserting (prepend)"));

            seg = ssh_interceptor_packet_insert(pp, 0, 80);
            if (seg == NULL)
            {
                ssh_engine_test_fail(engine, "insert (prepend) 80 failed");
                return;
            }
            memset(seg, 'I', 80);
            len += 80;

            for (i = 0; i < 10; i++)
            {
                seglen = ssh_rand() % (80 + 1);
                SSH_ASSERT(seglen <= 80);
                seg = ssh_interceptor_packet_insert(pp, 0, seglen);
                if (seg == NULL)
                {
                    ssh_engine_test_fail(engine, "insert (prepend) failed");
                    return;
                }
                memset(seg, 'I', seglen);
                len += seglen;
            }
            if (len != ssh_interceptor_packet_len(pp))
            {
                ssh_engine_test_fail(engine, "len mismatch after insert");
                ssh_interceptor_packet_free(pp);
                return;
            }
        }

        if (flags & SSH_INTERCEPTOR_TEST_BASIC_PULLUP)
        {
            SSH_DEBUG(1, ("pullup"));

            for (i = 0; i < 10; i++)
            {
                seglen = ssh_rand() % (80 + 1);
                SSH_ASSERT(seglen <= 80);
                if (seglen > len)
                    seglen = len;
                seg = ssh_interceptor_packet_pullup(pp, seglen);
                if (seg == NULL)
                {
                    ssh_engine_test_fail(engine, "pullup failed");
                    return;
                }
                if (flags & SSH_INTERCEPTOR_TEST_BASIC_PREPEND)
                    for (offset = 0; offset < seglen; offset++)
                        if (seg[offset] != 'I')
                        {
                            ssh_engine_test_fail(engine, "pullup compare failed");
                            ssh_interceptor_packet_free(pp);
                            return;
                        }
            }
            if (len != ssh_interceptor_packet_len(pp))
            {
                ssh_engine_test_fail(engine, "len mismatch after pullup");
                ssh_interceptor_packet_free(pp);
                return;
            }
        }

        if (flags & SSH_INTERCEPTOR_TEST_BASIC_INSERT)
        {
            SSH_DEBUG(1, ("random inserts"));

            for (i = 0; i < 10; i++)
            {
                offset = ssh_rand() % (len + 1);
                seglen = ssh_rand() % (80 + 1);
                seg = ssh_interceptor_packet_insert(pp, offset, seglen);
                if (seg == NULL)
                {
                    ssh_engine_test_fail(engine, "insert failed");
                    return;
                }
                memset(seg, 'i', seglen);
                len += seglen;
            }
            if (len != ssh_interceptor_packet_len(pp))
            {
                ssh_engine_test_fail(engine, "len mismatch after pullup");
                ssh_interceptor_packet_free(pp);
                return;
            }
        }

        if (flags & SSH_INTERCEPTOR_TEST_BASIC_DELETE)
        {
            SSH_DEBUG(1, ("random deletes"));

            for (i = 0; i < 10; i++)
            {
                offset = ssh_rand() % (len + 1);
                seglen = ssh_rand() % (len - offset + 1);
                if (!ssh_interceptor_packet_delete(pp, offset, seglen))
                {
                    ssh_engine_test_fail(engine, "packet_delete failed");
                    return;
                }
                len -= seglen;
            }
            if (len != ssh_interceptor_packet_len(pp))
            {
                ssh_engine_test_fail(engine, "len mismatch after delete");
                ssh_interceptor_packet_free(pp);
                return;
            }
        }

        if (flags & SSH_INTERCEPTOR_TEST_BASIC_ITERATE)
        {
            SSH_DEBUG(1, ("iterating again"));

            /* Again check that all iterations return correct total length. */
            for (i = 0; i < 10; i++)
            {
                offset = ssh_rand() % (len + 1);
                iterlen = ssh_rand() % (len - offset + 1);
                SSH_ASSERT(offset + iterlen <= len);
                sum = 0;
                prevseg = NULL;
                prevseglen = 0;
                ssh_interceptor_packet_reset_iteration(pp, offset, iterlen);
                while (ssh_interceptor_packet_next_iteration(pp, &seg, &seglen))
                {
                    if (prevseg && prevseglen != 0)
                        if (prevseg[0] != (prevseglen & 0xff))
                        {
                            ssh_engine_test_fail(engine,
                                                 "iter pointer not preserved");
                            ssh_interceptor_packet_free(pp);
                            return;
                        }

                    sum += seglen;
                    memset(seg, seglen & 0xff, seglen);
                    prevseg = seg, prevseglen = seglen;
                }
                if (seg != NULL)
                {
                    ssh_engine_test_fail(engine, "next iteration fails");
                    return;
                }
                if (sum != iterlen)
                {
                    ssh_engine_test_fail(engine, "iteration (again) test fails");
                    ssh_interceptor_packet_free(pp);
                    return;
                }
            }
        }

        SSH_DEBUG(1, ("freeing"));

        ssh_interceptor_packet_free(pp);
    }

    ssh_engine_test_ok(engine);
}
コード例 #12
0
/*------------------------------------------------------------------------
  ssh_interceptor_send_to_engine()
   
  If interceptor is enabled then packets are sent
  to engine for post-processing otherwise the packet resources are freed.  
  
  Arguments:
  interceptor - interceptor object
  adpater - adapter object
  pkt_cts - packet context
  
  Returns:
  Notes:
  ------------------------------------------------------------------------*/
void
ssh_interceptor_send_to_engine(SshNdisIMInterceptor interceptor,
                               SshNdisIMAdapter adapter,
                               SshNdisPacket packet)
{
  PNDIS_PACKET pkt = packet->np;
  size_t media_header_len = SSH_ETHERH_HDRLEN;
  SshCpuContext cpu_ctx;

#ifdef _WIN32_WCE
  SSH_ASSERT(MAXIMUM_PROCESSORS == 1);
#else
  SSH_ASSERT(SSH_GET_IRQL() == SSH_DISPATCH_LEVEL);
#endif /* _WIN32_WCE */

  /* Remove VLAN tagging before forwarding this packet to engine. This code
     supports also stacked VLANs. The maximum amount of VLAN encapsulation
     tags is defined by SSH_VLAN_MAX_VLAN_TAGS. */
  if (packet->eth_type == SSH_ETHERTYPE_VLAN)
    {
      SshUInt16 tag_count = 0;
 
      while (packet->eth_type == SSH_ETHERTYPE_VLAN)
        {
          unsigned char temp[4];
          SshUInt16 tag;

          if (tag_count == SSH_VLAN_MAX_VLAN_TAGS)
            {
              SSH_DEBUG(SSH_D_FAIL, 
                        ("Maximum number of stacked VLAN IDs edceeded; "
                        "dropping packet."));

              ssh_interceptor_packet_free(&packet->ip);
              return;
            }

          /* Copy next VLAN tag to packet context */
          ssh_interceptor_packet_copyout(&packet->ip, 
                                         media_header_len 
                                         + tag_count * sizeof(temp), 
                                         temp, sizeof(temp));

          tag = SSH_GET_16BIT(temp);

          packet->vlan_tags[tag_count].qos = (tag & 0x0007);
          packet->vlan_tags[tag_count].vlan_id = (tag >> 4);
          packet->eth_type = SSH_GET_16BIT(&temp[2]);

          /* If we haven't seen OID_GEN_VLAN_ID query/set (this is the case
             in Windows 2000), we need to pick and store the VLAN ID from 
             this packet. */
          if ((tag_count == 0) && (adapter->vlan_id_known == 0))
            adapter->vlan_id = packet->vlan_tags[0].vlan_id;

          tag_count++;
        }

      /* Delete VLAN tags from packet */
      if (!ssh_interceptor_packet_delete(&packet->ip,
                                         SSH_ETHERH_OFS_TYPE,
                                         tag_count * 4))
        {
          SSH_DEBUG(SSH_D_FAIL, ("Failed to remove VLAN tags"));
          return;
        }

      packet->vlan_tag_count = tag_count;
    }