Blame rhfunc.c

Packit 61cb5a
/*
Packit 61cb5a
 * Copyright (c) 2010-2011, Red Hat, Inc.
Packit 61cb5a
 *
Packit 61cb5a
 * Permission to use, copy, modify, and/or distribute this software for any
Packit 61cb5a
 * purpose with or without fee is hereby granted, provided that the above
Packit 61cb5a
 * copyright notice and this permission notice appear in all copies.
Packit 61cb5a
 *
Packit 61cb5a
 * THE SOFTWARE IS PROVIDED "AS IS" AND RED HAT, INC. DISCLAIMS ALL WARRANTIES
Packit 61cb5a
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
Packit 61cb5a
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RED HAT, INC. BE LIABLE
Packit 61cb5a
 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Packit 61cb5a
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
Packit 61cb5a
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
Packit 61cb5a
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Packit 61cb5a
 */
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Author: Jan Friesse <jfriesse@redhat.com>
Packit 61cb5a
 */
Packit 61cb5a
Packit 61cb5a
#include <sys/types.h>
Packit 61cb5a
Packit 61cb5a
#include <sys/socket.h>
Packit 61cb5a
Packit 61cb5a
#include <net/if.h>
Packit 61cb5a
#include <netinet/in.h>
Packit 61cb5a
#include <arpa/inet.h>
Packit 61cb5a
Packit 61cb5a
#include <err.h>
Packit 61cb5a
#include <limits.h>
Packit 61cb5a
#include <stdio.h>
Packit 61cb5a
#include <stdlib.h>
Packit 61cb5a
#include <string.h>
Packit 61cb5a
#include <stdarg.h>
Packit 61cb5a
Packit 61cb5a
#include "rhfunc.h"
Packit 61cb5a
#include "omping.h"
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Add item to remote host list. Addr pointer is stored in rh_item. On fail, function returns NULL,
Packit 61cb5a
 * otherwise newly allocated rh_item is returned. dup_buf_items is number of items to be stored in
Packit 61cb5a
 * duplicate buffers. rate_limit_time is maximum time between two received packets.
Packit 61cb5a
 */
Packit 61cb5a
struct rh_item *
Packit 61cb5a
rh_list_add_item(struct rh_list *rh_list, struct ai_item *addr, int dup_buf_items,
Packit 61cb5a
    int rate_limit_time)
Packit 61cb5a
{
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
	struct rh_item_ci *ci;
Packit 61cb5a
	int i;
Packit 61cb5a
Packit 61cb5a
	rh_item = (struct rh_item *)malloc(sizeof(struct rh_item));
Packit 61cb5a
	if (rh_item == NULL) {
Packit 61cb5a
		return (NULL);
Packit 61cb5a
	}
Packit 61cb5a
Packit 61cb5a
	memset(rh_item, 0, sizeof(struct rh_item));
Packit 61cb5a
Packit 61cb5a
	rh_item->addr = addr;
Packit 61cb5a
	ci = &rh_item->client_info;
Packit 61cb5a
Packit 61cb5a
	if (dup_buf_items > 0) {
Packit 61cb5a
		ci->dup_buf_items = dup_buf_items;
Packit 61cb5a
Packit 61cb5a
		for (i = 0; i < 2; i++) {
Packit 61cb5a
			ci->dup_buffer[i] = (uint32_t *)malloc(dup_buf_items * sizeof(uint32_t));
Packit 61cb5a
Packit 61cb5a
			if (ci->dup_buffer[i] == NULL) {
Packit 61cb5a
				goto malloc_error;
Packit 61cb5a
			}
Packit 61cb5a
Packit 61cb5a
			memset(ci->dup_buffer[i], 0, dup_buf_items * sizeof(uint32_t));
Packit 61cb5a
		}
Packit 61cb5a
	}
Packit 61cb5a
Packit 61cb5a
	if (rate_limit_time > 0) {
Packit 61cb5a
		gcra_init(&rh_item->server_info.gcra, rate_limit_time, GCRA_BURST);
Packit 61cb5a
	}
Packit 61cb5a
Packit 61cb5a
	TAILQ_INSERT_TAIL(rh_list, rh_item, entries);
Packit 61cb5a
Packit 61cb5a
	return (rh_item);
Packit 61cb5a
Packit 61cb5a
malloc_error:
Packit 61cb5a
	for (i = 0; i < 2; i++) {
Packit 61cb5a
		free(rh_item->client_info.dup_buffer[i]);
Packit 61cb5a
	}
Packit 61cb5a
	free(rh_item);
Packit 61cb5a
Packit 61cb5a
	return (NULL);
Packit 61cb5a
}
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Create list of rh_items. It's also possible to pass ai_list to include every address from list to
Packit 61cb5a
 * newly allocated rh_list. dup_buf_items is number of items to be stored in duplicate buffers.
Packit 61cb5a
 * rate_limit_time is maximum time between two received packets.
Packit 61cb5a
 */
Packit 61cb5a
void
Packit 61cb5a
rh_list_create(struct rh_list *rh_list, struct ai_list *remote_addrs, int dup_buf_items,
Packit 61cb5a
    int rate_limit_time)
Packit 61cb5a
{
Packit 61cb5a
	struct ai_item *addr;
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
Packit 61cb5a
	TAILQ_INIT(rh_list);
Packit 61cb5a
Packit 61cb5a
	if (remote_addrs != NULL) {
Packit 61cb5a
		TAILQ_FOREACH(addr, remote_addrs, entries) {
Packit 61cb5a
			rh_item = rh_list_add_item(rh_list, addr, dup_buf_items, rate_limit_time);
Packit 61cb5a
			if (rh_item == NULL) {
Packit 61cb5a
				errx(1, "Can't alloc memory");
Packit 61cb5a
			}
Packit 61cb5a
		}
Packit 61cb5a
	}
Packit 61cb5a
}
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Find remote host with addr sa in list. rh_item pointer is returned on success otherwise NULL is
Packit 61cb5a
 * returned.
Packit 61cb5a
 */
Packit 61cb5a
struct rh_item *
Packit 61cb5a
rh_list_find(struct rh_list *rh_list, const struct sockaddr *sa)
Packit 61cb5a
{
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
Packit 61cb5a
	TAILQ_FOREACH(rh_item, rh_list, entries) {
Packit 61cb5a
		if (af_sockaddr_eq((const struct sockaddr *)&rh_item->addr->sas, sa))
Packit 61cb5a
			return (rh_item);
Packit 61cb5a
	}
Packit 61cb5a
Packit 61cb5a
	return (NULL);
Packit 61cb5a
}
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Free list from memory.
Packit 61cb5a
 */
Packit 61cb5a
void
Packit 61cb5a
rh_list_free(struct rh_list *rh_list)
Packit 61cb5a
{
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
	struct rh_item *rh_item_next;
Packit 61cb5a
	int i;
Packit 61cb5a
Packit 61cb5a
	rh_item = TAILQ_FIRST(rh_list);
Packit 61cb5a
Packit 61cb5a
	while (rh_item != NULL) {
Packit 61cb5a
		rh_item_next = TAILQ_NEXT(rh_item, entries);
Packit 61cb5a
Packit 61cb5a
		free(rh_item->client_info.server_info);
Packit 61cb5a
		free(rh_item->client_info.ses_id);
Packit 61cb5a
Packit 61cb5a
		for (i = 0; i < 2; i++) {
Packit 61cb5a
			free(rh_item->client_info.dup_buffer[i]);
Packit 61cb5a
		}
Packit 61cb5a
Packit 61cb5a
		free(rh_item);
Packit 61cb5a
Packit 61cb5a
		rh_item = rh_item_next;
Packit 61cb5a
	}
Packit 61cb5a
Packit 61cb5a
	TAILQ_INIT(rh_list);
Packit 61cb5a
}
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Generate CID for all items in rh_list
Packit 61cb5a
 */
Packit 61cb5a
void
Packit 61cb5a
rh_list_gen_cid(struct rh_list *rh_list, const struct ai_item *local_addr)
Packit 61cb5a
{
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
Packit 61cb5a
	TAILQ_FOREACH(rh_item, rh_list, entries) {
Packit 61cb5a
		util_gen_cid(rh_item->client_info.client_id, local_addr);
Packit 61cb5a
	}
Packit 61cb5a
}
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Return length of longest host name from rh_list list.
Packit 61cb5a
 */
Packit 61cb5a
int
Packit 61cb5a
rh_list_hn_max_len(struct rh_list *rh_list)
Packit 61cb5a
{
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
	size_t max_len;
Packit 61cb5a
Packit 61cb5a
	max_len = 0;
Packit 61cb5a
	TAILQ_FOREACH(rh_item, rh_list, entries) {
Packit 61cb5a
		if (strlen(rh_item->addr->host_name) > max_len) {
Packit 61cb5a
			max_len = strlen(rh_item->addr->host_name);
Packit 61cb5a
		}
Packit 61cb5a
	}
Packit 61cb5a
Packit 61cb5a
	return (max_len > INT_MAX ? INT_MAX : (int)max_len);
Packit 61cb5a
}
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Return number of items in rh_list.
Packit 61cb5a
 */
Packit 61cb5a
unsigned int
Packit 61cb5a
rh_list_length(const struct rh_list *rh_list)
Packit 61cb5a
{
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
	unsigned int res;
Packit 61cb5a
Packit 61cb5a
	res = 0;
Packit 61cb5a
Packit 61cb5a
	TAILQ_FOREACH(rh_item, rh_list, entries) {
Packit 61cb5a
		res++;
Packit 61cb5a
	}
Packit 61cb5a
Packit 61cb5a
	return (res);
Packit 61cb5a
}
Packit 61cb5a
Packit 61cb5a
/*
Packit 61cb5a
 * Move all items in rh_list to finish state. fs is which part of remote host is put to finish
Packit 61cb5a
 * state. This may mean, that server state is put to RH_SS_FINISHING and/or client state is moved
Packit 61cb5a
 * to RH_CS_STOP
Packit 61cb5a
 */
Packit 61cb5a
void
Packit 61cb5a
rh_list_put_to_finish_state(struct rh_list *rh_list, enum rh_list_finish_state fs)
Packit 61cb5a
{
Packit 61cb5a
	struct rh_item *rh_item;
Packit 61cb5a
Packit 61cb5a
	TAILQ_FOREACH(rh_item, rh_list, entries) {
Packit 61cb5a
		if (fs == RH_LFS_SERVER || fs == RH_LFS_BOTH) {
Packit 61cb5a
			rh_item->server_info.state = RH_SS_FINISHING;
Packit 61cb5a
		}
Packit 61cb5a
		if (fs == RH_LFS_CLIENT || fs == RH_LFS_BOTH) {
Packit 61cb5a
			rh_item->client_info.state = RH_CS_STOP;
Packit 61cb5a
		}
Packit 61cb5a
	}
Packit 61cb5a
}