Exemple #1
0
void mds_free_local_links(struct mds_links* ln)
{
  int self, other;
  self = find_peer(ln, PCU_Comm_Self());
  if (self == -1)
    return;
  other = find_peer(ln, PCU_Comm_Peers());
  ln->n[self] = ln->n[other] = 0;
  free(ln->l[self]);
  free(ln->l[other]);
  ln->l[self] = ln->l[other] = NULL;
}
Exemple #2
0
static void take_local_link(mds_id i, struct mds_copy c, void* u)
{
  struct mds_links* ln = u;
  int self = find_peer(ln, PCU_Comm_Self());
  int other = find_peer(ln, PCU_Comm_Peers());
  mds_id j = mds_index(c.e);
  if ((PCU_Comm_Self() == c.p) && (i < j)) {
    ln->l[self][ln->n[self]] = i;
    ln->l[other][ln->n[other]] = j;
    /* use ns as (redundant) position keepers */
    ++ln->n[self];
    ++ln->n[other];
  }
}
Exemple #3
0
void mds_set_type_links(struct mds_net* net, struct mds* m,
    int t, struct mds_links* ln)
{
  unsigned i;
  unsigned j;
  unsigned* in;
  struct mds_copy c;
  PCU_Comm_Begin();
  for (i = 0; i < ln->np; ++i) {
    PCU_ALWAYS_ASSERT(ln->l);
    for (j = 0; j < ln->n[i]; ++j)
      PCU_COMM_PACK(ln->p[i], ln->l[i][j]);
  }
  PCU_Comm_Send();
  while (PCU_Comm_Listen()) {
    c.p = PCU_Comm_Sender();
    PCU_ALWAYS_ASSERT(c.p != PCU_Comm_Self());
    i = find_peer(ln, c.p);
    in = PCU_Comm_Extract(ln->n[i] * sizeof(unsigned));
    for (j = 0; j < ln->n[i]; ++j) {
      c.e = mds_identify(t, in[j]);
      mds_add_copy(net, m, mds_identify(t, ln->l[i][j]), c);
    }
  }
}
Exemple #4
0
int connection_register(struct btd_service *service)
{
	struct btd_device *device = btd_service_get_device(service);
	struct network_peer *peer;
	struct network_conn *nc;
	uint16_t id = get_service_id(service);

	DBG("%s id %u", device_get_path(device), id);

	peer = find_peer(peers, device);
	if (!peer) {
		peer = create_peer(device);
		if (!peer)
			return -1;
		peers = g_slist_append(peers, peer);
	}

	nc = g_new0(struct network_conn, 1);
	nc->id = id;
	nc->service = btd_service_ref(service);
	nc->state = DISCONNECTED;
	nc->peer = peer;

	btd_service_set_user_data(service, nc);

	DBG("id %u registered", id);

	peer->connections = g_slist_append(peer->connections, nc);

	return 0;
}
Exemple #5
0
PMIX_EXPORT pmix_status_t PMIx_Data_unpack(const pmix_proc_t *source,
                                           pmix_data_buffer_t *buffer, void *dest,
                                           int32_t *max_num_values,
                                           pmix_data_type_t type)
{
    pmix_status_t rc;
    pmix_buffer_t buf;
    pmix_peer_t *peer;

    if (NULL == (peer = find_peer(source))) {
        return PMIX_ERR_NOT_SUPPORTED;
    }

    /* setup the host */
    PMIX_CONSTRUCT(&buf, pmix_buffer_t);

    /* embed the data buffer into a buffer */
    PMIX_EMBED_DATA_BUFFER(&buf, buffer);

    /* unpack the value */
    PMIX_BFROPS_UNPACK(rc, peer,
                       &buf, dest, max_num_values, type);

    /* extract the data buffer - the pointers may have changed */
    PMIX_EXTRACT_DATA_BUFFER(&buf, buffer);

    /* no need to cleanup as all storage was xfered */
    return rc;
}
Exemple #6
0
/**
 * ampe_open_peer_link - attempt to establish a peer link
 * @peer:      MAC address of the candidate peer
 * @cookie:    Opaque cookie that will be returned to the caller along with
 *             frames to be transmitted.
 *
 * Returns 0 or a negative error.
 */
int ampe_open_peer_link(unsigned char *peer_mac, void *cookie) {
  struct candidate *cand;

  assert(peer_mac);

  if ((cand = find_peer(peer_mac, 0)) == NULL) {
    sae_debug(
        AMPE_DEBUG_FSM,
        "Mesh plink: Attempt to peer with "
        " non-authed peer\n");
    return -EPERM;
  }

  peer_ampe_init(&ampe_conf, cand, cookie);
  set_link_state(cand, PLINK_OPN_SNT);
  cb->evl->rem_timeout(cand->t2);
  cand->t2 = cb->evl->add_timeout(SRV_MSEC(cand->timeout), plink_timer, cand);

  sae_debug(
      AMPE_DEBUG_FSM,
      "Mesh plink: starting establishment "
      "with " MACSTR "\n",
      MAC2STR(peer_mac));

  return plink_frame_tx(cand, PLINK_OPEN, 0);
}
Exemple #7
0
void mds_get_local_matches(struct mds_net* net, struct mds* m,
                         int t, struct mds_links* ln)
{
  int self, other;
  for_type_net(net, m, t, note_local_link, ln);
  self = find_peer(ln, PCU_Comm_Self());
  if (self == -1)
    return;
  other = find_peer(ln, PCU_Comm_Peers());
  assert(ln->n[self] == ln->n[other]);
  ln->l[self] = malloc(ln->n[self] * sizeof(unsigned));
  ln->l[other] = malloc(ln->n[other] * sizeof(unsigned));
  ln->n[self] = 0;
  ln->n[other] = 0;
  for_type_net(net, m, t, take_local_link, ln);
}
Exemple #8
0
int rudp_sendto(rudp_socket_t rsocket_t, void* data, int len, struct sockaddr_in6* to) {
	struct rudp_socket *rsocket;
	struct peer * cur_peer;
	struct vsftp * vs_data;

	rsocket = (struct rudp_socket *) rsocket_t;
	vs_data = (struct vsftp *) data;
	vs_data->vs_type = ntohl(vs_data->vs_type);

	// find the corresponding peer
	cur_peer = find_peer(rsocket, to);

	// create a new peer if needed
	if (cur_peer == NULL) {
		// ignore if it's not VS_TYPE_BEGIN
		if (vs_data->vs_type != VS_TYPE_BEGIN) {
			printf("rudp_sendto: cannot find peer\n");
			return -1;
		}

		cur_peer = add_peer(rsocket, to);	
	}

	// if the peer is the first peer, store the data to the data list of the socket
	if (cur_peer == rsocket->peer_head) {
		store_data(rsocket, vs_data, len);
	}

	vs_data->vs_type = htonl(vs_data->vs_type);
	
	return 0;
}
Exemple #9
0
int connection_register(struct btd_device *device, const char *path,
			bdaddr_t *src, bdaddr_t *dst, uint16_t id)
{
	struct network_peer *peer;
	struct network_conn *nc;

	if (!path)
		return -EINVAL;

	peer = find_peer(peers, path);
	if (!peer) {
		peer = create_peer(device, path, src, dst);
		if (!peer)
			return -1;
		peers = g_slist_append(peers, peer);
	}

	nc = find_connection(peer->connections, id);
	if (nc)
		return 0;

	nc = g_new0(struct network_conn, 1);
	nc->id = id;
	memset(nc->dev, 0, sizeof(nc->dev));
	strcpy(nc->dev, "bnep%d");
	nc->state = DISCONNECTED;
	nc->peer = peer;

	peer->connections = g_slist_append(peer->connections, nc);

	return 0;
}
Exemple #10
0
/**
 * @brief config file function for broadcasting dmq message
 */
int ki_dmq_bcast_message(sip_msg_t *msg, str *peer_str, str *body_str,
		str *ct_str)
{
	LM_DBG("cfg_dmq_bcast_message: %.*s - %.*s - %.*s\n", peer_str->len,
			peer_str->s, body_str->len, body_str->s, ct_str->len, ct_str->s);

	dmq_peer_t *destination_peer = find_peer(*peer_str);
	if(!destination_peer) {
		LM_INFO("cannot find peer %.*s - adding it.\n", peer_str->len,
				peer_str->s);
		dmq_peer_t new_peer;
		new_peer.callback = empty_peer_callback;
		new_peer.description.s = "";
		new_peer.description.len = 0;
		new_peer.peer_id = *peer_str;
		destination_peer = register_dmq_peer(&new_peer);
		if(!destination_peer) {
			LM_ERR("error in register_dmq_peer\n");
			goto error;
		}
	}
	if(bcast_dmq_message(destination_peer, body_str, 0, &notification_callback,
			   1, ct_str) < 0) {
		LM_ERR("cannot send dmq message\n");
		goto error;
	}
	return 1;
error:
	return -1;
}
Exemple #11
0
int ampe_close_peer_link(unsigned char *peer_mac) {
  struct candidate *cand;

  assert(peer_mac);

  if ((cand = find_peer(peer_mac, 0)) == NULL) {
    sae_debug(
        AMPE_DEBUG_FSM,
        "Mesh plink: Attempt to close link with non-existent peer\n");
    return -EPERM;
  }

  if (!cand->conf) {
    /*
     * This can happen if we get a delete event for a station but they
     * haven't yet advanced to link establishment phase.  No need to send
     * a close then.
     */
    sae_debug(
        AMPE_DEBUG_FSM,
        "Mesh plink: not sending close to uninitialized peer " MACSTR "\n",
        MAC2STR(peer_mac));
    return -EPERM;
  }

  sae_debug(
      AMPE_DEBUG_FSM,
      "Mesh plink: closing link with " MACSTR "\n",
      MAC2STR(peer_mac));

  return plink_frame_tx(cand, PLINK_CLOSE, MESH_LINK_CANCELLED);
}
Exemple #12
0
/**
 * @brief config file function for sending dmq message
 */
int cfg_dmq_send_message(struct sip_msg* msg, char* peer, char* to, char* body, char* content_type)
{
	str peer_str;
	str to_str;
	str body_str;
	str ct_str;
	
	if(get_str_fparam(&peer_str, msg, (fparam_t*)peer)<0) {
		LM_ERR("cannot get peer value\n");
		return -1;
	}
	if(get_str_fparam(&to_str, msg, (fparam_t*)to)<0) {
		LM_ERR("cannot get dst value\n");
		return -1;
	}
	if(get_str_fparam(&body_str, msg, (fparam_t*)body)<0) {
		LM_ERR("cannot get body value\n");
		return -1;
	}
	if(get_str_fparam(&ct_str, msg, (fparam_t*)content_type)<0) {
		LM_ERR("cannot get content-type value\n");
		return -1;
	}

	
	LM_DBG("cfg_dmq_send_message: %.*s - %.*s - %.*s - %.*s\n",
		peer_str.len, peer_str.s,
		to_str.len, to_str.s,
		body_str.len, body_str.s,
		ct_str.len, ct_str.s);
	
	dmq_peer_t* destination_peer = find_peer(peer_str);
	if(!destination_peer) {
		LM_INFO("cannot find peer %.*s\n", peer_str.len, peer_str.s);
		dmq_peer_t new_peer;
		new_peer.callback = empty_peer_callback;
		new_peer.description.s = "";
		new_peer.description.len = 0;
		new_peer.peer_id = peer_str;
		destination_peer = register_dmq_peer(&new_peer);
		if(!destination_peer) {
			LM_ERR("error in register_dmq_peer\n");
			goto error;
		}
	}
	dmq_node_t* to_dmq_node = find_dmq_node_uri(node_list, &to_str);
	if(!to_dmq_node) {
		LM_ERR("cannot find dmq_node: %.*s\n", to_str.len, to_str.s);
		goto error;
	}
	if(dmq_send_message(destination_peer, &body_str, to_dmq_node,
				&notification_callback, 1, &ct_str) < 0) {
		LM_ERR("cannot send dmq message\n");
		goto error;
	}
	return 1;
error:
	return -1;
}
Exemple #13
0
size_t pcu_msg_packed(pcu_msg* m, int id)
{
  if (m->state != pack_state)
    reel_fail("PCU_Comm_Packed called at the wrong time");
  pcu_msg_peer* peer = find_peer(m->peers,id);
  if (!peer)
    reel_fail("PCU_Comm_Packed called but nothing was packed");
  return peer->message.buffer.size;
}
Exemple #14
0
void received_data(network::connection sock, simple_wml::document& data)
{
    const network::connection peer = find_peer(sock);
    if(!peer) {
        return;
    }

    const simple_wml::string_span& output = data.output_compressed();
    network::send_raw_data(output.begin(), output.size(), peer);
}
Exemple #15
0
static void take_remote_link(mds_id i, struct mds_copy c, void* u)
{
  struct mds_links* ln = u;
  int pi;
  if (PCU_Comm_Self() < c.p) {
    pi = find_peer(ln, c.p);
    ln->l[pi][ln->n[pi]] = i;
    /* use n as position keeper */
    ++ln->n[pi];
  }
}
Exemple #16
0
static void recv_links(struct mds_links* ln)
{
  int from;
  mds_id* tmp;
  int pi;
  unsigned i;
  from = PCU_Comm_Sender();
  pi = find_peer(ln, from);
  tmp = PCU_Comm_Extract(ln->n[pi] * sizeof(mds_id));
  for (i = 0; i < ln->n[pi]; ++i)
    ln->l[pi][i] = mds_index(tmp[i]);
}
Exemple #17
0
void* pcu_msg_pack(pcu_msg* m, int id, size_t size)
{
  if (m->state != pack_state)
    reel_fail("PCU_Comm_Pack called at the wrong time");
  pcu_msg_peer* peer = find_peer(m->peers,id);
  if (!peer)
  {
    peer = make_peer(id);
    pcu_aa_insert(&(peer->node),&(m->peers),peer_less);
  }
  return pcu_push_buffer(&(peer->message.buffer),size);
}
Exemple #18
0
void mds_set_local_matches(struct mds_net* net, struct mds* m,
                         int t, struct mds_links* ln)
{
  int self, other;
  unsigned i;
  mds_id a, b;
  struct mds_copy c;
  c.p = PCU_Comm_Self();
  self = find_peer(ln, PCU_Comm_Self());
  if (self == -1)
    return;
  other = find_peer(ln, PCU_Comm_Peers());
  assert(ln->n[self] = ln->n[other]);
  for (i = 0; i < ln->n[self]; ++i) {
    a = mds_identify(t, ln->l[self][i]);
    b = mds_identify(t, ln->l[other][i]);
    c.e = b;
    mds_add_copy(net, m, a, c);
    c.e = a;
    mds_add_copy(net, m, b, c);
  }
}
Exemple #19
0
void disconnect(network::connection sock)
{
    const network::connection peer = find_peer(sock);
    if(!peer) {
        return;
    }

    servers_to_clients.erase(sock);
    servers_to_clients.erase(peer);
    clients_to_servers.erase(sock);
    clients_to_servers.erase(peer);

    network::disconnect(peer);
}
Exemple #20
0
int connect_to_listener()
{
    int sockfd;
    sockfd = Socket(AF_INET, SOCK_STREAM, 0);

    /*
     * Now, we'll use a different algorithm to find our peers on a LAN.
     *
     * We will iterate over all the hosts in a given subnet, try to connect to
     * each one on a given port, and if the connection is successful, start
     * chatting with them.
     */
    find_peer(sockfd);

    return sockfd;
}
Exemple #21
0
static int insert_peer(struct mds_links* ln, int p)
{
  int i;
  i = find_peer(ln, p);
  if (i != -1)
    return i;
  i = ln->np;
  ++(ln->np);
  ln->p = realloc(ln->p, ln->np * sizeof(unsigned));
  ln->n = realloc(ln->n, ln->np * sizeof(unsigned));
  ln->l = realloc(ln->l, ln->np * sizeof(unsigned*));
  ln->p[i] = p;
  ln->n[i] = 0;
  ln->l[i] = NULL;
  return i;
}
Exemple #22
0
void connection_unregister(const char *path, uint16_t id)
{
	struct network_peer *peer;
	struct network_conn *nc;

	peer = find_peer(peers, path);
	if (!peer)
		return;

	nc = find_connection(peer->connections, id);
	if (!nc)
		return;

	peer->connections = g_slist_remove(peer->connections, nc);
	connection_free(nc);
	if (peer->connections)
		return;

	g_dbus_unregister_interface(connection, path, NETWORK_PEER_INTERFACE);
}
Exemple #23
0
/* when an ack packet is received, invoke the function to process the pakcet */
void process_ack_packet(char* packet, bt_config_t* config,
                         struct sockaddr_in* from) {
    /* 1. parse ack packet */
    int ack_num = parse_ack(packet);

    // fix 0-1 problem
    ack_num--;

    DPRINTF(DEBUG_SOCKETS, "recv ack: %d\n", ack_num);

    /* 2. find the peer that send the ack packet */
    bt_peer_t* peer = find_peer(config->peers, from);

    if (peer->up_con == NULL){
        /* a "out-of-date" ack packet, ignore it*/
        return;
    }

    /* successfully receive a packet, reset successive_fail */
    peer->up_con->successive_fail = 0;

    /* 3. ack to window */
    int is_resend = window_ack_packet(peer->up_con, ack_num);

    if (is_resend)
        DPRINTF(DEBUG_SOCKETS, "resend data packet due to duplicate ack\n");

    /* 4. send (or resend) data packet */
    send_data_packet(is_resend, config, peer);

    /* 5. check if have received all acks (finish uploading) */
    if (window_finish_ack(peer->up_con)){
        /* CLR select set*/
        FD_CLR(peer->up_con->timer_fd, &config->readset);
        /* destroy connection with peer */
        destroy_connection(peer->up_con);
        peer->up_con = NULL;
        /* dec current upload number */
        config->cur_upload_num--;
    }
}
Exemple #24
0
static int handle_del_peer(struct netlink_config_s *nlcfg,
        struct nl_msg *msg, void *arg)
{
    struct nlattr *tb[NL80211_ATTR_MAX + 1];
    struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
    struct candidate *peer;

    nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
            genlmsg_attrlen(gnlh, 0), NULL);

    if (nla_get_u32(tb[NL80211_ATTR_IFINDEX]) != nlcfg->ifindex)
        return -1;

    if (!tb[NL80211_ATTR_MAC] || nla_len(tb[NL80211_ATTR_MAC]) != ETH_ALEN)
        return -1;

    if ((peer = find_peer(nla_data(tb[NL80211_ATTR_MAC]), 0)))
         delete_peer(&peer);

	return 0;
}
Exemple #25
0
	optional_type find_peer(const std::wstring& ip_address)
	{
		return find_peer(peer_detail(ip_address));
	}
Exemple #26
0
/**
 * process_ampe_frame - process an ampe frame
 * @frame:     The full frame
 * @len:       The full frame length
 * @me:        The MAC address of the local interface
 * @cookie:    Opaque cookie that will be returned to the caller along with
 *             frames to be transmitted.
 *
 * Returns 0 unless something really horrible happened.  In other words, even
 * the frame could not be processed or it was corrupted, the function still
 * returns 0.
 */
int process_ampe_frame(struct ieee80211_mgmt_frame *mgmt, int len,
                        unsigned char *me, void *cookie)
{
    struct info_elems elems;
    struct info_elems our_elems;
    unsigned char ftype;
	struct candidate *cand = NULL;
	enum plink_event event;
	unsigned char ie_len = 0;
	unsigned short plid = 0, llid = 0;
    unsigned char *ies;
    unsigned short ies_len;

#define FAKE_LOSS_PROBABILITY 0
#if (FAKE_LOSS_PROBABILITY > 0)
    do {
        unsigned short dice;
        dice = RAND_bytes((unsigned char *) &dice, sizeof(dice));
        if ((dice % 100) < FAKE_LOSS_PROBABILITY) {
            sae_debug(AMPE_DEBUG_FSM, "Frame dropped\n");
            return 0;
        }
    } while (0);
#endif

	/* management header, category, action code, mesh id and peering mgmt*/
	if (len < 24 + 1 + 1 + 2 + 2)
		return 0;

	//if (is_multicast_ether_addr(mgmt->da)) {
	//	sae_debug(AMPE_DEBUG_FSM, "Mesh plink: ignore frame to multicast address");
	//	return 0;
	//}


	ies = start_of_ies(mgmt, len, &ies_len);
	parse_ies(ies, ies_len, &elems);
	if (!elems.mesh_peering) {  // || !elems.rsn) {
		sae_debug(AMPE_DEBUG_FSM, "Mesh plink: missing necessary peer link ie\n");
		return 0;
	}

	ftype = mgmt->action.action_code;
	ie_len = elems.mesh_peering_len;

	if ((ftype == PLINK_OPEN && ie_len != 20) ||
	    (ftype == PLINK_CONFIRM && ie_len != 22) ||
	    (ftype == PLINK_CLOSE && ie_len != 22 && ie_len != 24)) {
		sae_debug(AMPE_DEBUG_FSM, "Mesh plink: incorrect plink ie length %d %d\n",
		    ftype, ie_len);
		return 0;
	}

    if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) {
        sae_debug(AMPE_DEBUG_FSM, "Mesh plink: missing necessary ie %p %p\n", elems.mesh_id, elems.mesh_config);
        return 0;
    }

	/* Note the lines below are correct, the llid in the frame is the plid
	 * from the point of view of this host.
	 */
 	memcpy(&plid, PLINK_GET_LLID(elems.mesh_peering), 2);
    if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 10))
        memcpy(&llid, PLINK_GET_PLID(elems.mesh_peering), 2);

    /* match BSSBasicRateSet*/
    parse_ies(sta_fixed_ies, sta_fixed_ies_len, &our_elems);
    if (get_basic_rates(&our_elems) != get_basic_rates(&elems)) {
        sae_debug(AMPE_DEBUG_FSM, "mesh plink: mismatched BSSBasicRateSet!\n");
        return 0;
    }

    /* "1" here means only get peers in SAE_ACCEPTED */
    if ((cand = find_peer(mgmt->sa, 1)) == NULL) {
		sae_debug(AMPE_DEBUG_FSM, "Mesh plink: plink open from unauthed peer "MACSTR"\n",
                  MAC2STR(mgmt->sa));
        return 0;
    }

    if (cand->my_lid == 0)
        peer_ampe_init(&ampe_conf, cand, me, cookie);

    if (elems.sup_rates) {
        memcpy(cand->sup_rates, elems.sup_rates,
                elems.sup_rates_len);
        cand->sup_rates_len = elems.sup_rates_len;
        if (elems.ext_rates) {
            memcpy(cand->sup_rates + elems.sup_rates_len,
                    elems.ext_rates, elems.ext_rates_len);
            cand->sup_rates_len += elems.ext_rates_len;
        }
    }

    check_frame_protection(cand, mgmt, len, &elems);

    cand->cookie = cookie;



	if (cand->link_state == PLINK_BLOCKED) {
		return 0;
	}

	/* Now we will figure out the appropriate event... */
	event = PLINK_UNDEFINED;
//	if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) {
	if (ftype != PLINK_CLOSE) {
		switch (ftype) {
		case PLINK_OPEN:
			event = OPN_RJCT;
			break;
		case PLINK_CONFIRM:
			event = CNF_RJCT;
			break;
		case PLINK_CLOSE:
			break;
		}
	}

    switch (ftype) {
    case PLINK_OPEN:
        if (!plink_free_count() ||
            (cand->peer_lid && cand->peer_lid != plid))
            event = OPN_IGNR;
        else {
            cand->peer_lid = plid;
            event = OPN_ACPT;
        }
        break;
    case PLINK_CONFIRM:
        if (!plink_free_count() ||
            (cand->my_lid != llid || cand->peer_lid != plid))
            event = CNF_IGNR;
        else
            event = CNF_ACPT;
        break;
    case PLINK_CLOSE:
        if (cand->link_state == PLINK_ESTAB)
            /* Do not check for llid or plid. This does not
             * follow the standard but since multiple plinks
             * per cand are not supported, it is necessary in
             * order to avoid a livelock when MP A sees an
             * establish peer link to MP B but MP B does not
             * see it. This can be caused by a timeout in
             * B's peer link establishment or B beign
             * restarted.
             */
            event = CLS_ACPT;
        else if (cand->peer_lid != plid)
            event = CLS_IGNR;
        else if (ie_len == 7 && cand->my_lid != llid)
            event = CLS_IGNR;
        else
            event = CLS_ACPT;
        break;
    default:
        sae_debug(AMPE_DEBUG_FSM, "Mesh plink: unknown frame subtype\n");
        return 0;
    }

	sae_debug(AMPE_DEBUG_FSM, "Mesh plink (peer, state, llid, plid, event): " MACSTR " %s %d %d %d\n",
		MAC2STR(mgmt->sa), mplstates[cand->link_state],
		le16toh(cand->my_lid), le16toh(cand->peer_lid),
		event);

    fsm_step(cand, event);

    return 0;
}
Exemple #27
0
/*
int main()
{
  return 0;
}
*/
int communicate(struct donnees* donnees)
{
  printf("communicate\n");
  struct client* client=donnees->client;
  ulong ip = client->sockaddr->sin_addr.s_addr;
  struct peer* peer = find_peer(donnees->peer_list, ip);
  struct file_list* file_list = donnees->file_list;
  struct peer_list* peer_list = donnees->peer_list;
  int refresh_time=get_refresh_time();
  printf("refresh time:%d\n",refresh_time);
  char* recv_buffer= malloc(sizeof(char)*RECV_BUF_SIZE);
  char* send_buffer= malloc(sizeof(char)*SEND_BUF_SIZE);  
  char* s1 = malloc(RECV_BUF_SIZE*sizeof(char));
  char* s2 = malloc(RECV_BUF_SIZE*sizeof(char));
  char* s3 = malloc(RECV_BUF_SIZE*sizeof(char));
  char* s4 = malloc(RECV_BUF_SIZE*sizeof(char));
  char* s5 = malloc(RECV_BUF_SIZE*sizeof(char));
  char* s6 = malloc(RECV_BUF_SIZE*sizeof(char));
  char* s0 = malloc(RECV_BUF_SIZE*sizeof(char));
  char* saux = malloc(RECV_BUF_SIZE*sizeof(char));
  char** tab = malloc(7*sizeof(char *));
  tab[0]=s0;
  tab[1]=s1;
  tab[2]=s2;
  tab[3]=s3;
  tab[4]=s4;
  tab[5]=s5;
  tab[6]=s6;
  int port;
  int read;
  int decalage;
  int length;
  int piece_size;
  struct timeval *t = malloc(sizeof(struct timeval));
  struct timeval *t2 = malloc(sizeof(struct timeval));
  struct timezone *tz = malloc(sizeof(struct timezone));
  struct timezone *tz2 = malloc(sizeof(struct timezone));
  gettimeofday(t,tz);
  while(1)
    { 
      recv_buffer[0]='\0';
      send_buffer[0]='\0';
      gettimeofday(t2,tz2);
      if(( (int)(t2->tv_sec - t->tv_sec))>3*refresh_time)
	{
	  if(peer!=NULL)
	    {
	      peer->time--;
	      if(!peer->time)
		{
		  peer_list_peer_delete(peer_list,file_list,peer->ip_address);
		}
	    }
	  //free  
	  free(s0);
	  free(s1);
	  free(s2);
	  free(s3);
	  free(s4);
	  free(s5);
	  free(s6);
	  free(saux);
	  free(recv_buffer);
	  free(send_buffer);
	  free(tab);
	  free(t);
	  free(t2);
	  free(tz);
	  free(tz2);
	  end(client,donnees->ct);
	  return 0;
	}
      read=read_client(client->sock, recv_buffer);
      if(read > 0)
	{
	  gettimeofday(t,tz);
	  if(peer!=NULL)
	    peer->time ++;
	  //print_data(file_list, peer_list);	  
	  printf("received:\n");
	  switch(recv_buffer[0])
	    {
	     pthread_mutex_lock(& mutex);
	    case'a':
	      decalage=0;
	      while(compte_crochet_fermant(recv_buffer)<2)
		{
		  decalage+=read;
		  read=read_client(client->sock, recv_buffer + decalage);
		}	  
	      recv_buffer[decalage+read]='\0';
	      printf("%s\n", recv_buffer);
	      parse(recv_buffer, tab);
	      port = atoi(s2);
	      if(strcmp(s0,"announce")==0 && strcmp(s1,"listen")==0 && strcmp(s3,"seed")==0 && strcmp(s5,"leech")==0)
		{
		  
		  if(peer == NULL)
		    {
		      peer = peer_init(ip, port);
		      peer_list_add(peer_list, peer);
		      peer->time=1;
		    }
		  int i=0;
		  while(strlen(s4+i) > 0)
		    {
		      if(compte_espace(s4+i)>3)
			{		 
			  
			  sscanf(s4+i, "%s %d %d %s", s1, &length, &piece_size, s2);
			  sprintf(saux, "%s %d %d %s", s1, length, piece_size, s2);
			  struct file* file = find_file(file_list, s1);
			  if(NULL == file)
			    {
			      file = remplit_file(s1, length, piece_size, s2);
			      file_list_add(file_list, file);
			    }
			  add_link(file, peer); 
			  i+=strlen(saux)+1;
			  
			}
		      else
			{
			  
			  sscanf(s4+i, "%s %d %d %s", s1, &length, &piece_size, s2); 
			  struct file* file = find_file(file_list, s1);
			  if(NULL == file)
			    {
			      file = remplit_file(s1, length, piece_size, s2);
			      file_list_add(file_list, file);
			    }
			  add_link(file, peer); 
			  s4[i]='\0';			
			}
		    }
		  struct file_list* f_add = keys_string_to_file_list(s6);
		  
		  update_add(file_list, peer, f_add);
		  file_list_delete(f_add);
		  write_client(client->sock, "ok");
		  printf("replied:ok\n");
		  
		}
	      break;
	      
	    case'u':
	      decalage=0;
	      while(compte_crochet_fermant(recv_buffer)<2)
		{
		  decalage+=read;
		  read=read_client(client->sock, recv_buffer + decalage);
		}	  
	      recv_buffer[decalage+read]='\0'; 
	      printf("%s\n", recv_buffer);	      
	      parse(recv_buffer, tab);
	      if(strcmp(s0,"update")==0 && strcmp(s1,"seed")==0 && strcmp(s3,"leech")==0)
		{
		  if(peer==NULL){
		    //free  
		    free(s0);
		    free(s1);
		    free(s2);
		    free(s3);
		    free(s4);
		    free(s5);
		    free(s6);
		    free(saux);
		    free(recv_buffer);
		    free(send_buffer);
		    free(tab);
		    free(t);
		    free(t2);
		    free(tz);
		    free(tz2);
		    end(client, donnees->ct);
		    
		    return 0;}//ferme la socket
		  else
		    { 
		    
		      char* res=fusion_keys_string(s2, s4);
		      struct file_list* f = keys_string_to_file_list(res);
		      update_diff(f, peer->file_list, file_list, peer);
		      file_list_delete(f);
		      free(res);
		      write_client(client->sock, "ok");
		      printf("replied:ok\n");
		  
		    }	    
		}
	      break;
	      
	    case'l':
	      decalage=0;
	      while(compte_crochet_fermant(recv_buffer)<1)
		{
		  decalage+=read;
		  read=read_client(client->sock, recv_buffer + decalage);
		}	  
	      recv_buffer[decalage+read]='\0'; 
	      printf("%s\n", recv_buffer);	      
	      parse(recv_buffer, tab);
	      if(strcmp(s0,"look")==0)
		{
		  char* filename="filename";
		  int egal=1;
		  int i;
		  s2[0]='\n';
		  for(i=0;i<8;i++)
		    {
		      if(s1[i]!=filename[i]) egal --;
		    }
		  if(egal==1)
		    {
		      for(i=10;i<((int) strlen(s1))-1;i++)
			{
			  s2[i-10]=s1[i];
			}
		      s2[strlen(s1)-11]='\0';
		      
		      printf("recherche:\nfilename=%s\n",s2);
		      struct file* file=find_file_name(file_list, s2);
		      if(file==NULL) write_client(client->sock, "list []");
		      else
			{
			  sprintf(send_buffer, "list [%s %d %d %s]", s2, file->length, file->p_size, file->key);
			  write_client(client->sock, send_buffer);
			  printf("replied:%s\n", send_buffer);
			}
		    }
		}
	      break;

	    case'g':
	      recv_buffer[read]='\0'; 
	      printf("%s\n", recv_buffer);	      
	      parse(recv_buffer, tab);
	      if(strcmp(s0,"getfile")==0)
		{
		  struct file* f=find_file(file_list, s1);
		  if(f==NULL||f->peer_list->first==NULL)
		    {
		      sprintf(send_buffer, "peers %s []", s1);
		      write_client(client->sock, send_buffer);
		    }
		  else
		    {
		      struct elt_peer* aux=f->peer_list->first;
		      struct in_addr* in_addr1=malloc(sizeof(struct in_addr));
		      in_addr1->s_addr=aux->peer->ip_address;
		      char* d= inet_ntoa(*in_addr1);
		      sprintf(send_buffer, "peers %s [%s:%d", s1, d, aux->peer->port);
		      aux=aux->next;
		      while(aux!=NULL)
			{
			  struct in_addr* in_addr=malloc(sizeof(struct in_addr));
			  in_addr->s_addr=aux->peer->ip_address;
			  char* c= inet_ntoa(*in_addr);
			  sprintf(send_buffer+strlen(send_buffer), " %s:%d", c, aux->peer->port);
			  aux=aux->next;
			}
		      sprintf(send_buffer+strlen(send_buffer), "]");
		      write_client(client->sock, send_buffer);
		      printf("replied:%s\n", send_buffer);
		    }
		}
	      break;

	    default:
	      printf("entree non valide");
	      //free  
	      free(s0);
	      free(s1);
	      free(s2);
	      free(s3);
	      free(s4);
	      free(s5);
	      free(s6);
	      free(saux);
	      free(recv_buffer);
	      free(send_buffer);
	      free(tab);
	      free(t);
	      free(t2);
	      free(tz);
	      free(tz2);
	      end(client,donnees->ct);
	      return 0;
	      
	     
	    }
	  pthread_mutex_unlock( &mutex);
	}
      
    }
  return EXIT_SUCCESS;
}
Exemple #28
0
static void receiver_recv_handler_send (DPReceiveReceiver *o, uint8_t *packet, int packet_len)
{
    DebugObject_Access(&o->d_obj);
    DPReceivePeer *peer = o->peer;
    DPReceiveDevice *device = peer->device;
    ASSERT(packet_len >= 0)
    ASSERT(packet_len <= device->packet_mtu)
    
    uint8_t *data = packet;
    int data_len = packet_len;
    
    int local = 0;
    DPReceivePeer *src_peer;
    DPReceivePeer *relay_dest_peer = NULL;
    
    // check header
    if (data_len < sizeof(struct dataproto_header)) {
        BLog(BLOG_WARNING, "no dataproto header");
        goto out;
    }
    struct dataproto_header header;
    memcpy(&header, data, sizeof(header));
    data += sizeof(header);
    data_len -= sizeof(header);
    uint8_t flags = ltoh8(header.flags);
    peerid_t from_id = ltoh16(header.from_id);
    int num_ids = ltoh16(header.num_peer_ids);
    
    // check destination ID
    if (!(num_ids == 0 || num_ids == 1)) {
        BLog(BLOG_WARNING, "wrong number of destinations");
        goto out;
    }
    peerid_t to_id = 0; // to remove warning
    if (num_ids == 1) {
        if (data_len < sizeof(struct dataproto_peer_id)) {
            BLog(BLOG_WARNING, "missing destination");
            goto out;
        }
        struct dataproto_peer_id id;
        memcpy(&id, data, sizeof(id));
        to_id = ltoh16(id.id);
        data += sizeof(id);
        data_len -= sizeof(id);
    }
    
    // check remaining data
    if (data_len > device->device_mtu) {
        BLog(BLOG_WARNING, "frame too large");
        goto out;
    }
    
    // inform sink of received packet
    if (peer->dp_sink) {
        DataProtoSink_Received(peer->dp_sink, !!(flags & DATAPROTO_FLAGS_RECEIVING_KEEPALIVES));
    }
    
    if (num_ids == 1) {
        // find source peer
        if (!(src_peer = find_peer(device, from_id))) {
            BLog(BLOG_INFO, "source peer %d not known", (int)from_id);
            goto out;
        }
        
        // is frame for device or another peer?
        if (device->have_peer_id && to_id == device->peer_id) {
            // let the frame decider analyze the frame
            FrameDeciderPeer_Analyze(src_peer->decider_peer, data, data_len);
            
            // pass frame to device
            local = 1;
        } else {
            // check if relaying is allowed
            if (!peer->is_relay_client) {
                BLog(BLOG_WARNING, "relaying not allowed");
                goto out;
            }
            
            // provided source ID must be the peer sending the frame
            if (src_peer != peer) {
                BLog(BLOG_WARNING, "relay source must be the sending peer");
                goto out;
            }
            
            // find destination peer
            DPReceivePeer *dest_peer = find_peer(device, to_id);
            if (!dest_peer) {
                BLog(BLOG_INFO, "relay destination peer not known");
                goto out;
            }
            
            // destination cannot be source
            if (dest_peer == src_peer) {
                BLog(BLOG_WARNING, "relay destination cannot be the source");
                goto out;
            }
            
            relay_dest_peer = dest_peer;
        }
    }
    
out:
    // accept packet
    PacketPassInterface_Done(&o->recv_if);
    
    // pass packet to device
    if (local) {
        o->device->output_func(o->device->output_func_user, data, data_len);
    }
    
    // relay frame
    if (relay_dest_peer) {
        DPRelayRouter_SubmitFrame(&device->relay_router, &src_peer->relay_source, &relay_dest_peer->relay_sink, data, data_len, device->relay_flow_buffer_size, device->relay_flow_inactivity_time);
    }
}
Exemple #29
0
void
do_iax_event(FILE *f) {
	int sessions = 0;
	struct iax_event *e = 0;
	struct peer *peer;

	while ( (e = iax_get_event(0))) {
		peer = find_peer(e->session);
		if(peer) {
			handle_event(f, e, peer);
		} else if (e->session == registry) {
			fprintf(stderr, "Registration complete: %s (%d)\n",
				(e->event.regreply.status == IAX_REG_SUCCESS) ? "Success" : "Failed",
				e->event.regreply.status);
			registry = NULL;
		} else {
			if(e->etype != IAX_EVENT_CONNECT) {
				fprintf(stderr, "Huh? This is an event for a non-existant session?\n");
				continue;
			}
			sessions++;

			if(sessions >= MAX_SESSIONS) {
				fprintf(f, "Missed a call... too many sessions open.\n");
			}


			if(e->event.connect.callerid && e->event.connect.dnid)
				fprintf(f, "Call from '%s' for '%s'", e->event.connect.callerid,
				e->event.connect.dnid);
			else if(e->event.connect.dnid) {
				fprintf(f, "Call from '%s'", e->event.connect.dnid);
			} else if(e->event.connect.callerid) {
				fprintf(f, "Call from '%s'", e->event.connect.callerid);
			} else printf("Call from");
			fprintf(f, " (%s)\n", inet_ntoa(iax_get_peer_addr(e->session).sin_addr));

			if(most_recent_answer) {
				fprintf(f, "Incoming call ignored, there's already a call waiting for answer... \
please accept or reject first\n");
				iax_reject(e->session, "Too many calls, we're busy!");
			} else {
				if ( !(peer = malloc(sizeof(struct peer)))) {
					fprintf(f, "Warning: Unable to allocate memory!\n");
					return;
				}

				peer->time = time(0);
				peer->session = e->session;
				if (peer->gsmin)
					free(peer->gsmin);
				peer->gsmin = 0;
				if (peer->gsmout)
					free(peer->gsmout);
				peer->gsmout = 0;

				peer->next = peers;
				peers = peer;

				iax_accept(peer->session);
				iax_ring_announce(peer->session);
				most_recent_answer = peer;
				ringing = 1;
				gentone(TONE_RINGER, 0);
				fprintf(f, "Incoming call!\n");
			}
			issue_prompt(f);
		}
		iax_event_free(e);
	}
Exemple #30
0
/* accept and process request form local client */
void process_client_request(int fd_un2) 
{
	int	len, len_toreceive, len_received, len_tosend, len_sent;
	int rc, fd_in = 0;

	CLI_REQUEST		creq;
	CLI_RESPONSE	cresp;
	SRV_REQUEST		sreq;
	SRV_RESPONSE	sresp;
	SRV_MESSAGE		smsg;
	char 			buf[2048];
	
	char			keyid[MAX_TAG_LEN + MAX_HOST_LEN + 10];

	BIGNUM 			*bn_base = NULL, *bn_prime = NULL, *bn_private = NULL;
	unsigned char*	public = NULL;
	int				public_len;
	unsigned char*	secret_key = NULL;
	int				secret_key_len;

	memset(&cresp, 0, sizeof(cresp));
	memset(&sreq, 0, sizeof(sreq));
	memset(&smsg, 0, sizeof(smsg));
		
	/* receive request - we can expect at least 7 first bytes to receive */
	len = recv(fd_un2, buf, 7, 0);
	if (len < 0) {
		output(LOG_ERR, "recv failed. %s", strerror(errno));
		cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
		goto send;
	}
	else if (!len) return;

	len_received = len;
	len_toreceive = get_der_seq_size(buf);
	if (len_toreceive > sizeof(buf)) {
		output(LOG_ERR, "packet sent by client is too big");
		cresp.status = MK_STATUS(SCOPE_CLIENT, ERR_MALFORMED);
		goto send;
	}

	/* get the rest */
	while (len_toreceive > len_received) {
		len = len_toreceive - len_received;
		len = recv(fd_un2, &buf[len_received], len, 0);
		if (len < 0) {
			output(LOG_ERR, "recv failed. %s", strerror(errno));
			cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
			goto send;
		}
		else if (!len) return;

		len_received += len;
	}

	/* decode request message */
	rc = decode_client_request(buf, len_received, &creq);
	if (rc) {
		cresp.status = MK_STATUS(SCOPE_CLIENT, rc);
		goto send;
	}

	/* check if parameters, flags are valid */
	if (creq.version != CURRENT_PROTOCOL_VERSION) {
		output(LOG_ERR, "unsupported protocol version %d", creq.version);
		cresp.status = MK_STATUS(SCOPE_CLIENT, ERR_PROTOCOL);
		goto send;
	}

	if (check_flag_validity(creq.flags)) {
		output(LOG_ERR, "not allowed option combination");
		cresp.status = MK_STATUS(SCOPE_CLIENT, ERR_INVALID_PARAM);
		goto send;
	}

	if (creq.reqType == CRT_ENUM_KEYS) {
		cresp.status = STATUS_SUCCESS;
		goto send;
	}
	else
	if (creq.reqType == CRT_REQUEST_KEY &&
		(!creq.keyLen || creq.keyLen > MAX_KEY_LEN)) {
		output(LOG_ERR, "invalid size of requested key: %d", creq.keyLen);
		cresp.status = MK_STATUS(SCOPE_CLIENT, ERR_INVALID_PARAM);
		goto send;
	}

	/* make keyid */
	sprintf(keyid, "%s@%s", creq.tag, creq.peer);
	
	/* process request */
	if (creq.reqType == CRT_DELETE_KEY) {
		/* check for a key in database and delete it */
		if (keydb_exists(keyid)) {
			rc = keydb_delete(keyid);
			if (rc) {
				output(LOG_ERR, "keydb_delete failed. %s", strerror(errno));
				cresp.status = MK_STATUS(SCOPE_HOST, ERR_INTERNAL);
			}
		}
		else {
			output(LOG_ERR, "requested key does not exist: '%s'", keyid);
			cresp.status = MK_STATUS(SCOPE_HOST, ERR_KEY_NOT_EXISTS);
		}
	}
	/* here we block and get requested key */
	else if (creq.flags & FLAG_INIT_KEY) {
		struct sockaddr_in peer_addr;
		char addr_accept[] = "0123456789.";
		PEER_ENTRY* pe;

		/* locate and check the peer */
		pe = find_peer(creq.peer);
		if (!pe) {
			output(LOG_ERR, "peer '%s' is not available", creq.peer);
			cresp.status = MK_STATUS(SCOPE_HOST, ERR_NOT_AVAILABLE);
			goto send;
		}
		else
		if (!pe->allow) {
			output(LOG_ERR, "access denied for peer '%s'", creq.peer);
			cresp.status = MK_STATUS(SCOPE_HOST, ERR_ACCESS_DENIED);
			goto send;
		}
		
		/* generate secret, calculate public value */
		rc = dh_init_group_params(conf_dh_group, &bn_prime, &bn_base);
		if (rc) {
			output(LOG_ERR, "dh_init_group_params failed");
			cresp.status = MK_STATUS(SCOPE_HOST, rc);
			goto send;
		}
		DUMP_BN(bn_prime, "prime ");
		DUMP_BN(bn_base, "base  ");
		
		rc = dh_gen_private_public(conf_dh_group, bn_prime, bn_base,
			&bn_private, &public, &public_len);
		if (rc) {
			output(LOG_ERR, "dh_gen_private_public failed");
			cresp.status = MK_STATUS(SCOPE_HOST, rc);
			goto send;
		}
		DUMP_BN(bn_private, "priv-i");
		DUMP_BIN(public, public_len, "publ-i");
		
		/* fill-in request */
		sreq.cookie = generate_unique_cookie();
		sreq.keyLen = creq.keyLen;
		strncpy(sreq.tag, creq.tag, sizeof(sreq.tag));
		strncpy(sreq.host, conf_host, sizeof(sreq.host));
		strncpy(sreq.expires, creq.expires, sizeof(sreq.expires));
		sreq.dhGroup = conf_dh_group;
		sreq.dhPublic_len = public_len;
		memcpy(sreq.dhPublic, public, public_len);

		smsg.tbsMsg_len = sizeof(smsg.tbsMsg);
		rc = encode_server_request(&sreq, smsg.tbsMsg, &smsg.tbsMsg_len);
		if (rc) {
			cresp.status = MK_STATUS(SCOPE_HOST, rc);
			goto send;
		}

		/* fill-in request message */
		smsg.version = CURRENT_PROTOCOL_VERSION;

		/* sign request if required */
		if (pe->auth != AUTH_NONE) {
			rc = sign_message(pe, smsg.tbsMsg, smsg.tbsMsg_len,
				smsg.sigAlg, &smsg.sigAlg_len, smsg.sig, &smsg.sig_len);
			if (rc) {
				cresp.status = MK_STATUS(SCOPE_HOST, rc);
				goto send;
			}
		}

		/* encode message */	
		len = sizeof(buf);
		rc = encode_server_message(&smsg, buf, &len);
		if (rc) {
			cresp.status = MK_STATUS(SCOPE_HOST, rc);
			goto send;
		}
	
		/* get peer id & address, connect to socket and send the message */
	
		/* is it ip address? */
		if (strspn(creq.peer, addr_accept) == strlen(creq.peer)) {
			if (!inet_aton(creq.peer, &(peer_addr.sin_addr))) {
				output(LOG_ERR, "inet_aton failed");
				cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
				goto send;
			}
		}

		/* resolve dns */
		else {
			struct hostent* h = gethostbyname(creq.peer);
			if (!h) {
				output(LOG_ERR, "gethostbyname failed");
				cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
				goto send;
			}

			peer_addr.sin_addr = *((struct in_addr*)h->h_addr);
		}
	
		peer_addr.sin_family = AF_INET;
		peer_addr.sin_port = htons(creq.port ? creq.port : DEFAULT_PORT);
		memset(peer_addr.sin_zero, 0, sizeof(peer_addr.sin_zero));

		fd_in = socket(AF_INET, SOCK_STREAM, 0);
		if (!fd_in) {
			output(LOG_ERR, "socket failed. %s", strerror(errno));
			cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
			goto send;
		}

		rc = connect(fd_in, (struct sockaddr*)&peer_addr,
			sizeof(struct sockaddr));
		if (rc == -1) {
			output(LOG_ERR, "connect failed. %s", strerror(errno));
			cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
			goto send;
		}

		/* send request */
		len_sent = 0;
		len_tosend = len;
		while (len_tosend > len_sent) {
			len = len_tosend - len_sent;
			len = send(fd_in, &buf[len_sent], len, 0);
			if (len < 0) {
				output(LOG_ERR, "send failed/connection closed by peer");
				cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
				goto send;
			}
			len_sent += len;
		}

		memset(&smsg, 0, sizeof(smsg));
		
		/* receive response - we can expect at least 14 bytes to receive */
		len = recv(fd_in, buf, 14, 0);
		if (len <= 0) {
			output(LOG_ERR, "recv failed/connection closed by peer");
			cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
			goto send;
		}

		len_received = len;
		len_toreceive = get_der_seq_size(buf);
		assert(len_toreceive <= sizeof(buf));
		if (len_toreceive > sizeof(buf)) {
			output(LOG_ERR, "packet sent by peer is too big");
			cresp.status = MK_STATUS(SCOPE_PEER, ERR_MALFORMED);
			goto send;
		}

		/* get the rest */
		while (len_toreceive > len_received) {
			len = len_toreceive - len_received;
			len = recv(fd_in, &buf[len_received], len, 0);
			if (len < 0) {
				output(LOG_ERR, "recv failed/connection closed by peer");
				cresp.status = MK_STATUS(SCOPE_HOST, ERR_COMM);
				goto send;
			}
			len_received += len;
		}

		close(fd_in);
		fd_in = 0;

		/* decode response message */
		rc = decode_server_message(buf, len_received, &smsg);
 		if (rc) {
			cresp.status = MK_STATUS(SCOPE_HOST, rc);
			goto send;
		}

		/* sanity check */
		if (smsg.version != CURRENT_PROTOCOL_VERSION) {
			output(LOG_ERR, "unsupported protocol version %d", smsg.version);
			cresp.status = MK_STATUS(SCOPE_PEER, ERR_PROTOCOL);
			goto send;
		}

		/* verify signature if required */
		if (smsg.sigAlg_len && smsg.sig_len) {
			rc = verify_signature(pe, smsg.tbsMsg, smsg.tbsMsg_len,
				smsg.sigAlg, smsg.sigAlg_len, smsg.sig, smsg.sig_len);
			if (rc) {
				cresp.status = MK_STATUS(SCOPE_HOST, rc);
				goto send;
			}
		}
		else
		if (pe->auth != AUTH_NONE) {
			output(LOG_ERR, "response is not signed");
			cresp.status = MK_STATUS(SCOPE_PEER, ERR_SIG_VERIFY);
			goto send;
		}
		
		/* decode response */
		rc = decode_server_response(smsg.tbsMsg, smsg.tbsMsg_len, &sresp);
 		if (rc) {
			cresp.status = MK_STATUS(SCOPE_HOST, rc);
			goto send;
		}

		if (GET_ERR(sresp.status)) {
			output(LOG_ERR, "peer returned status 0x%0.2hx", sresp.status);
			cresp.status = MK_STATUS(SCOPE_PEER, GET_ERR(sresp.status));
			goto send;
		}

		/* calculate shared secret, make a requested key */
		rc = dh_get_secret(sresp.dhPublic, sresp.dhPublic_len,
			bn_private, bn_prime, &secret_key, &secret_key_len);
		if (rc) {
			output(LOG_ERR, "dh_get_secret failed");
			cresp.status = MK_STATUS(SCOPE_HOST, rc);
			goto send;
		}

		DUMP_BIN(sresp.dhPublic, sresp.dhPublic_len, "publ-r");
		DUMP_BIN(secret_key, secret_key_len, "secr-i");
		
		assert(secret_key_len >= BITS_TO_BYTES(creq.keyLen));

		/* store a key to database */
		if (creq.flags & FLAG_STORE_KEY) {
			char kval_buf[KEY_VAL_SIZE + MAX_KEY_LEN];
			PKEY_VAL pkey_val = (PKEY_VAL)kval_buf;

			pkey_val->expires = gentime_to_time_t(creq.expires);
			if (pkey_val->expires == -1) {
				output(LOG_ERR, "cannot convert time value %s", creq.expires);
				cresp.status = MK_STATUS(SCOPE_HOST, ERR_INVALID_PARAM);
				goto send;
			}
			
			pkey_val->key_len = creq.keyLen;
			memcpy(pkey_val->key, secret_key,
				BITS_TO_BYTES(pkey_val->key_len));
			
			rc = keydb_store(keyid, kval_buf, sizeof(KEY_VAL) +
				BITS_TO_BYTES(pkey_val->key_len));
			if (rc) {
				output(LOG_ERR, "keydb_store failed. %s", strerror(errno));
				cresp.status = MK_STATUS(SCOPE_HOST, ERR_INTERNAL);
				goto send;
			}

			output(LOG_INFO, "new key '%s' (%dbits) added, validity: %s",
				keyid, pkey_val->key_len, ctime(&pkey_val->expires));
		}

		cresp.keyLen = creq.keyLen;
		memcpy(cresp.key, secret_key, BITS_TO_BYTES(cresp.keyLen));
		cresp.status = STATUS_SUCCESS;
	}
	else {