Пример #1
0
static inline struct pf_cn *
lookup_cn_rule(struct hash *h, const char *cn, const uint32_t cn_hash)
{
    struct hash_element *he = hash_lookup_fast(h, hash_bucket(h, cn_hash), cn, cn_hash);
    if (he)
    {
        return (struct pf_cn *) he->value;
    }
    else
    {
        return NULL;
    }
}
Пример #2
0
/**
 *	ovs_vport_locate - find a port that has already been created
 *
 * @name: name of port to find
 *
 * Must be called with RTNL or RCU read lock.
 */
struct vport *ovs_vport_locate(struct net *net, const char *name)
{
	struct hlist_head *bucket = hash_bucket(net, name);
	struct vport *vport;
	struct hlist_node *node;

	hlist_for_each_entry_rcu(vport, node, bucket, hash_node)
		if (!strcmp(name, vport->ops->get_name(vport)) &&
		    net_eq(ovs_dp_get_net(vport->dp), net))
			return vport;

	return NULL;
}
Пример #3
0
static void update_peers(struct net *net, const char *name, struct vport *vport)
{
	struct hlist_head *bucket = hash_bucket(net, name);
	struct patch_vport *peer_vport;
	struct hlist_node *node;

	hlist_for_each_entry(peer_vport, node, bucket, hash_node) {
		struct vport *curr_vport = vport_from_priv(peer_vport);
		const char *peer_name;

		peer_name = rtnl_dereference(peer_vport->patchconf)->peer_name;
		if (!strcmp(peer_name, name) && net_eq(ovs_dp_get_net(curr_vport->dp), net))
			rcu_assign_pointer(peer_vport->peer, vport);
	}
}
Пример #4
0
static struct vport *patch_create(const struct vport_parms *parms)
{
	struct vport *vport;
	struct patch_vport *patch_vport;
	const char *peer_name;
	struct patch_config *patchconf;
	struct net *net = ovs_dp_get_net(parms->dp);
	int err;

	vport = ovs_vport_alloc(sizeof(struct patch_vport),
				&ovs_patch_vport_ops, parms);
	if (IS_ERR(vport)) {
		err = PTR_ERR(vport);
		goto error;
	}

	patch_vport = patch_vport_priv(vport);

	strcpy(patch_vport->name, parms->name);

	patchconf = kmalloc(sizeof(struct patch_config), GFP_KERNEL);
	if (!patchconf) {
		err = -ENOMEM;
		goto error_free_vport;
	}

	err = patch_set_config(vport, parms->options, patchconf);
	if (err)
		goto error_free_patchconf;

	random_ether_addr(patchconf->eth_addr);

	rcu_assign_pointer(patch_vport->patchconf, patchconf);

	peer_name = patchconf->peer_name;
	hlist_add_head(&patch_vport->hash_node, hash_bucket(net, peer_name));
	rcu_assign_pointer(patch_vport->peer, ovs_vport_locate(net, peer_name));
	update_peers(net, patch_vport->name, vport);

	return vport;

error_free_patchconf:
	kfree(patchconf);
error_free_vport:
	ovs_vport_free(vport);
error:
	return ERR_PTR(err);
}
Пример #5
0
HASHDATA * hash_insert( struct hash * hp, OBJECT * key, int * found )
{
    ITEM * i;
    unsigned int keyval = hash_keyval( key );

    #ifdef HASH_DEBUG_PROFILE
    profile_frame prof[1];
    if ( DEBUG_PROFILE )
        profile_enter( 0, prof );
    #endif

    if ( !hp->items.more )
        hashrehash( hp );

    i = hash_search( hp, keyval, key, 0 );
    if ( i )
    {
        *found = 1;
    }
    else
    {
        ITEM * * base = hash_bucket( hp, keyval );

        /* try to grab one from the free list */
        if ( hp->items.free )
        {
            i = hp->items.free;
            hp->items.free = i->hdr.next;
            assert( hash_item_key( i ) == 0 );
        }
        else
        {
            i = (ITEM *)hp->items.next;
            hp->items.next += hp->items.size;
        }
        hp->items.more--;
        i->hdr.next = *base;
        *base = i;
        *found = 0;
    }

    #ifdef HASH_DEBUG_PROFILE
    if ( DEBUG_PROFILE )
        profile_exit( prof );
    #endif

    return hash_item_data( i );
}
Пример #6
0
static struct multi_instance *
multi_create_instance_tcp(struct multi_context *m)
{
    struct gc_arena gc = gc_new();
    struct multi_instance *mi = NULL;
    struct hash *hash = m->hash;

    mi = multi_create_instance(m, NULL);
    if (mi)
    {
        struct hash_element *he;
        const uint32_t hv = hash_value(hash, &mi->real);
        struct hash_bucket *bucket = hash_bucket(hash, hv);

        he = hash_lookup_fast(hash, bucket, &mi->real, hv);

        if (he)
        {
            struct multi_instance *oldmi = (struct multi_instance *) he->value;
            msg(D_MULTI_LOW, "MULTI TCP: new incoming client address matches existing client address -- new client takes precedence");
            oldmi->did_real_hash = false;
            multi_close_instance(m, oldmi, false);
            he->key = &mi->real;
            he->value = mi;
        }
        else
        {
            hash_add_fast(hash, bucket, &mi->real, hv, mi);
        }

        mi->did_real_hash = true;
    }

#ifdef ENABLE_DEBUG
    if (mi)
    {
        dmsg(D_MULTI_DEBUG, "MULTI TCP: instance added: %s", mroute_addr_print(&mi->real, &gc));
    }
    else
    {
        dmsg(D_MULTI_DEBUG, "MULTI TCP: new client instance failed");
    }
#endif

    gc_free(&gc);
    ASSERT(!(mi && mi->halt));
    return mi;
}
Пример #7
0
static ITEM * hash_search( struct hash * hp, unsigned int keyval,
    OBJECT * keydata, ITEM * * previous )
{
    ITEM * i = *hash_bucket( hp, keyval );
    ITEM * p = 0;
    for ( ; i; i = i->next )
    {
        if ( object_equal( hash_item_key( i ), keydata ) )
        {
            if ( previous )
                *previous = p;
            return i;
        }
        p = i;
    }
    return 0;
}
Пример #8
0
struct multi_instance *
multi_get_create_instance_udp (struct multi_context *m)
{
  struct gc_arena gc = gc_new ();
  struct mroute_addr real;
  struct multi_instance *mi = NULL;
  struct hash *hash = m->hash;

  if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
    {
      struct hash_element *he;
      const uint32_t hv = hash_value (hash, &real);
      struct hash_bucket *bucket = hash_bucket (hash, hv);
      uint8_t* ptr  = BPTR(&m->top.c2.buf);
      uint8_t op = ptr[0] >> P_OPCODE_SHIFT;
      uint32_t sess_id;
      bool session_forged = false;

      if (op == P_DATA_V2)
	{
	  sess_id = (*(uint32_t*)ptr) >> 8;
	  if ((sess_id < m->max_clients) && (m->instances[sess_id]))
	    {
	      mi = m->instances[sess_id];

	      if (!link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from))
		{
		  msg(D_MULTI_MEDIUM, "floating detected from %s to %s",
		      print_link_socket_actual (&mi->context.c2.from, &gc), print_link_socket_actual (&m->top.c2.from, &gc));

		  /* session-id is not trusted, so check hmac */
		  session_forged = !(crypto_test_hmac(&m->top.c2.buf, &mi->context.c2.crypto_options));
		  if (session_forged)
		    {
		      mi = NULL;
		      msg (D_MULTI_MEDIUM, "hmac verification failed, session forge detected!");
		    }
		  else
		    {
		      update_floated(m, mi, real, hv);
		    }
		}
	    }
	}
      else
	{
Пример #9
0
/**
 *	ovs_vport_add - add vport device (for kernel callers)
 *
 * @parms: Information about new vport.
 *
 * Creates a new vport with the specified configuration (which is dependent on
 * device type).  ovs_mutex must be held.
 *
 * 创建并初始化 vport:
 * 1. 参数校验
 *    * 确保 params->type 在 vport_ops_list(保持所有 vport->ops->type) 中, 返回类型为 params->type 的 ops
 *    * 确保 params->type->ops->owner 的模块是 alive 的
 * 2. 调用 internal_dev_create(params) 创建 vport, 初始化各个数据成员及私有数据
 * 3. 将 vport->hash_node 加入 dev_table
 *
 * 注: 没有初始化的 err_stats, detach_list
 */
struct vport *ovs_vport_add(const struct vport_parms *parms)
{
	struct vport_ops *ops;
	struct vport *vport;

    //确保 params->type 在 vport_ops_list(保持所有 vport->ops->type) 中, 返回
    //类型为 params->type 的 ops
	ops = ovs_vport_lookup(parms);
	if (ops) {
		struct hlist_head *bucket;

        //ops->owner 的模块是 alive 的
		if (!try_module_get(ops->owner))
			return ERR_PTR(-EAFNOSUPPORT);

        //调用 internal_dev_create 创建 vport, 初始化各个数据成员及私有数据
		vport = ops->create(parms);
		if (IS_ERR(vport)) {
            // ops->owener->refcnt = ops->owener->refcnt - 1
			module_put(ops->owner);
			return vport;
		}

		bucket = hash_bucket(ovs_dp_get_net(vport->dp),
				     vport->ops->get_name(vport));
		hlist_add_head_rcu(&vport->hash_node, bucket);
		return vport;
	}

	/* Unlock to attempt module load and return -EAGAIN if load
	 * was successful as we need to restart the port addition
	 * workflow.
	 */
	ovs_unlock();
	request_module("vport-type-%d", parms->type);
	ovs_lock();

	if (!ovs_vport_lookup(parms))
		return ERR_PTR(-EAFNOSUPPORT);
	else
		return ERR_PTR(-EAGAIN);
}
Пример #10
0
/**
 *	ovs_vport_add - add vport device (for kernel callers)
 *
 * @parms: Information about new vport.
 *
 * Creates a new vport with the specified configuration (which is dependent on
 * device type).  ovs_mutex must be held.
 */
struct vport *ovs_vport_add(const struct vport_parms *parms)
{
	struct vport_ops *ops;
	struct vport *vport;

	ops = ovs_vport_lookup(parms);
	if (ops) {
		struct hlist_head *bucket;

		if (!try_module_get(ops->owner))
			return ERR_PTR(-EAFNOSUPPORT);

		vport = ops->create(parms);
		if (IS_ERR(vport)) {
			module_put(ops->owner);
			return vport;
		}

		bucket = hash_bucket(ovs_dp_get_net(vport->dp),
				     ovs_vport_name(vport));
		hlist_add_head_rcu(&vport->hash_node, bucket);
		return vport;
	}

	if (parms->type == OVS_VPORT_TYPE_GRE && !compat_gre_loaded) {
		pr_warn("GRE protocol already loaded!\n");
		return ERR_PTR(-EAFNOSUPPORT);
	}
	/* Unlock to attempt module load and return -EAGAIN if load
	 * was successful as we need to restart the port addition
	 * workflow.
	 */
	ovs_unlock();
	request_module("vport-type-%d", parms->type);
	ovs_lock();

	if (!ovs_vport_lookup(parms))
		return ERR_PTR(-EAFNOSUPPORT);
	else
		return ERR_PTR(-EAGAIN);
}
+    union {
+        struct item  * next;
+	/*
+	 * Some architectures have 32bit pointers but 64bit time_t (as used
+	 * in file_info_t), and require natural alignement of data.
+	 * Since we offset an aligned pointer by sizeof(hashhdr) in
+	 * hash_item_data(item), we may cause misalignement if we do not
+	 * make sure that sizeof(hashhdr) is properly aligned.
+	 */
+	time_t aligner;	/* unused dummy for alignement */
+    } h;
 };
 
 typedef struct item
@@ -106,7 +116,7 @@ static ITEM * hash_search(
     ITEM * i = *hash_bucket(hp,keyval);
     ITEM * p = 0;
 
-    for ( ; i; i = i->hdr.next )
+    for ( ; i; i = i->hdr.h.next )
     {
         if ( object_equal( hash_item_key( i ), keydata ) )
         {
@@ -153,7 +163,7 @@ HASHDATA * hash_insert( struct hash * hp
         if ( hp->items.free )
         {
             i = hp->items.free;
-            hp->items.free = i->hdr.next;
+            hp->items.free = i->hdr.h.next;
             assert( hash_item_key( i ) == 0 );
         }
Пример #12
0
struct multi_instance *
multi_get_create_instance_udp (struct multi_context *m)
{
  struct gc_arena gc = gc_new ();
  struct mroute_addr real;
  struct multi_instance *mi = NULL;
  struct hash *hash = m->hash;

  if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true))
    {
      struct hash_element *he;
      const uint32_t hv = hash_value (hash, &real);
      struct hash_bucket *bucket = hash_bucket (hash, hv);
  
      he = hash_lookup_fast (hash, bucket, &real, hv);

      if (he)
	{
	  mi = (struct multi_instance *) he->value;
	}
      else
	{
	  if (!m->top.c2.tls_auth_standalone
	      || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf))
	    {
	      if (frequency_limit_event_allowed (m->new_connection_limiter))
		{
		  mi = multi_create_instance (m, &real);
		  if (mi)
		    {
		      hash_add_fast (hash, bucket, &mi->real, hv, mi);
		      mi->did_real_hash = true;
		    }
		}
	      else
		{
		  msg (D_MULTI_ERRORS,
		       "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq",
		       mroute_addr_print (&real, &gc));
		}
	    }
	}

#ifdef ENABLE_DEBUG
      if (check_debug_level (D_MULTI_DEBUG))
	{
	  const char *status;

	  if (he && mi)
	    status = "[succeeded]";
	  else if (!he && mi)
	    status = "[created]";
	  else
	    status = "[failed]";
	
	  dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
	       mroute_addr_print (&real, &gc),
	       status);
	}
#endif
    }

  gc_free (&gc);
  ASSERT (!(mi && mi->halt));
  return mi;
}
Пример #13
0
int
hashitem(
    register struct hash *hp,
    HASHDATA **data,
    int enter )
{
    register ITEM *i;
    OBJECT *b = (*data)->key;
    unsigned int keyval = hash_keyval(b);

    #ifdef HASH_DEBUG_PROFILE
    profile_frame prof[1];
    if ( DEBUG_PROFILE )
        profile_enter( 0, prof );
    #endif

    if ( enter && !hp->items.more )
        hashrehash( hp );

    if ( !enter && !hp->items.nel )
    {
        #ifdef HASH_DEBUG_PROFILE
        if ( DEBUG_PROFILE )
            profile_exit( prof );
        #endif
        return 0;
    }

    i = hash_search( hp, keyval, (*data)->key, 0 );
    if (i)
    {
        *data = &i->data;
        #ifdef HASH_DEBUG_PROFILE
        if ( DEBUG_PROFILE ) profile_exit( prof );
        #endif
        return !0;
    }

    if ( enter )
    {
        ITEM * * base = hash_bucket(hp,keyval);

        /* try to grab one from the free list */
        if ( hp->items.free )
        {
            i = hp->items.free;
            hp->items.free = i->hdr.next;
            assert( i->data.key == 0 );
        }
        else
        {
            i = (ITEM *)hp->items.next;
            hp->items.next += hp->items.size;
        }
        hp->items.more--;
        memcpy( (char *)&i->data, (char *)*data, hp->items.datalen );
        i->hdr.next = *base;
        *base = i;
        *data = &i->data;
        #ifdef OPT_BOEHM_GC
        if (sizeof(HASHDATA) == hp->items.datalen)
        {
            GC_REGISTER_FINALIZER(i->data.key,&hash_mem_finalizer,hp,0,0);
        }
        #endif
    }

    #ifdef HASH_DEBUG_PROFILE
    if ( DEBUG_PROFILE )
        profile_exit( prof );
    #endif
    return 0;
}
Пример #14
0
struct multi_instance *
multi_get_create_instance_udp (struct multi_context *m, bool *floated)
{
  struct gc_arena gc = gc_new ();
  struct mroute_addr real;
  struct multi_instance *mi = NULL;
  struct hash *hash = m->hash;

  if (mroute_extract_openvpn_sockaddr (&real, &m->top.c2.from.dest, true) &&
      m->top.c2.buf.len > 0)
    {
      struct hash_element *he;
      const uint32_t hv = hash_value (hash, &real);
      struct hash_bucket *bucket = hash_bucket (hash, hv);
      uint8_t* ptr = BPTR(&m->top.c2.buf);
      uint8_t op = ptr[0] >> P_OPCODE_SHIFT;

      /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */
      if (op == P_DATA_V2 && m->top.c2.buf.len >= (1 + 3))
	{
	  uint32_t peer_id = ntohl(*(uint32_t*)ptr) & 0xFFFFFF;
	  if ((peer_id < m->max_clients) && (m->instances[peer_id]))
	    {
	      mi = m->instances[peer_id];

	      *floated = !link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from);

	      if (*floated)
	      {
		/* reset prefix, since here we are not sure peer is the one it claims to be */
		ungenerate_prefix(mi);
		msg (D_MULTI_ERRORS, "Untrusted peer %" PRIu32 " wants to float to %s", peer_id,
			mroute_addr_print (&real, &gc));
	      }
	    }
	}
      else
	{
	  he = hash_lookup_fast (hash, bucket, &real, hv);
	  if (he)
	    {
	      mi = (struct multi_instance *) he->value;
	    }
	}
      if (!mi)
	{
	  if (!m->top.c2.tls_auth_standalone
	      || tls_pre_decrypt_lite (m->top.c2.tls_auth_standalone, &m->top.c2.from, &m->top.c2.buf))
	    {
	      if (frequency_limit_event_allowed (m->new_connection_limiter))
		{
		  mi = multi_create_instance (m, &real);
		  if (mi)
		    {
		      int i;

		      hash_add_fast (hash, bucket, &mi->real, hv, mi);
		      mi->did_real_hash = true;

		      for (i = 0; i < m->max_clients; ++i)
			{
			  if (!m->instances[i])
			    {
			      mi->context.c2.tls_multi->peer_id = i;
			      m->instances[i] = mi;
			      break;
			    }
			}

		      /* should not really end up here, since multi_create_instance returns null
		       * if amount of clients exceeds max_clients */
		      ASSERT(i < m->max_clients);
		    }
		}
	      else
		{
		  msg (D_MULTI_ERRORS,
		       "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq",
		       mroute_addr_print (&real, &gc));
		}
	    }
	}

#ifdef ENABLE_DEBUG
      if (check_debug_level (D_MULTI_DEBUG))
	{
	  const char *status = mi ? "[ok]" : "[failed]";

	  dmsg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
	       mroute_addr_print (&real, &gc),
	       status);
	}
#endif
    }

  gc_free (&gc);
  ASSERT (!(mi && mi->halt));
  return mi;
}
Пример #15
0
    my_name = sym_extract_name(name);
#ifdef SYM_MULTIPLE_NAME_SPACES
    my_name_space = name_space;
#endif

#ifdef SYM_DEEP_BINDING
    if (scope_pointer != SYM_ROOT_SCOPE)
#ifdef SYM_SCOPE_STACK_DEPTH
        *ptr = scope_stack + scope_pointer;
#else
        *ptr = &scope_pointer->linked_list;
#endif
    else
#endif
        /* Find hash bucket */
        *ptr = hash_bucket();

    /* Look for binding in bucket                                           */
    return search_linked_list(ptr);
    }


/****************************************************************************/
/*                                                                          */
/*                         P U B L I C   S T U F F                          */
/*                                                                          */
/****************************************************************************/

/* Create new symbol table entry                                            */
/* Return either SYMTAB_OK, SYMTAB_DUPLICATE or SYMTAB_NO_MEMORY            */
#ifdef SYM_MULTIPLE_NAME_SPACES