|
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 <stdlib.h>
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
#include "addrfunc.h"
|
|
Packit |
61cb5a |
#include "logging.h"
|
|
Packit |
61cb5a |
#include "msg.h"
|
|
Packit |
61cb5a |
#include "msgsend.h"
|
|
Packit |
61cb5a |
#include "omping.h"
|
|
Packit |
61cb5a |
#include "rsfunc.h"
|
|
Packit |
61cb5a |
#include "util.h"
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
/*
|
|
Packit |
61cb5a |
* Send answer message. ucast_socket is socket used to send message, mcast_addr is used multicast
|
|
Packit |
61cb5a |
* address, orig_msg is received query message with orig_msg_len, decoded is decoded message,
|
|
Packit |
61cb5a |
* to is sockaddr_storage address of destination, ttl is set TTL and answer_type can specify what
|
|
Packit |
61cb5a |
* type of response to send.
|
|
Packit |
61cb5a |
* Function returns 0 on sucess, otherwise same error as rs_sendto or -4 if message cannot be
|
|
Packit |
61cb5a |
* created (usually due to small message buffer)
|
|
Packit |
61cb5a |
*/
|
|
Packit |
61cb5a |
int
|
|
Packit |
61cb5a |
ms_answer(int ucast_socket, const struct sockaddr_storage *mcast_addr, const char *orig_msg,
|
|
Packit |
61cb5a |
size_t orig_msg_len, const struct msg_decoded *decoded, const struct sockaddr_storage *to,
|
|
Packit |
61cb5a |
uint8_t ttl, enum ms_answer_type answer_type)
|
|
Packit |
61cb5a |
{
|
|
Packit |
61cb5a |
char addr_str[INET6_ADDRSTRLEN];
|
|
Packit |
61cb5a |
char new_msg[MAX_MSG_SIZE];
|
|
Packit |
61cb5a |
struct sockaddr_storage to_mcast;
|
|
Packit |
61cb5a |
size_t new_msg_len;
|
|
Packit |
61cb5a |
ssize_t sent;
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
new_msg_len = msg_answer_create(orig_msg, orig_msg_len, new_msg, sizeof(new_msg),
|
|
Packit |
61cb5a |
ttl, decoded->request_opt_server_tstamp);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (new_msg_len == 0) {
|
|
Packit |
61cb5a |
return (-4);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (answer_type == MS_ANSWER_UCAST || answer_type == MS_ANSWER_BOTH) {
|
|
Packit |
61cb5a |
af_sa_to_str(AF_CAST_SA(to), addr_str);
|
|
Packit |
61cb5a |
DEBUG_PRINTF("Sending unicast answer msg to %s", addr_str);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
msg_update_server_tstamp(new_msg, new_msg_len);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
sent = rs_sendto(ucast_socket, new_msg, new_msg_len, to);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (sent < 0) {
|
|
Packit |
61cb5a |
return (sent);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (answer_type == MS_ANSWER_MCAST || answer_type == MS_ANSWER_BOTH) {
|
|
Packit |
61cb5a |
af_copy_addr(mcast_addr, to, 1, 2, &to_mcast);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
af_sa_to_str(AF_CAST_SA(&to_mcast), addr_str);
|
|
Packit |
61cb5a |
DEBUG_PRINTF("Sending multicast answer msg to %s", addr_str);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
msg_update_server_tstamp(new_msg, new_msg_len);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
sent = rs_sendto(ucast_socket, new_msg, new_msg_len, &to_mcast);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (sent < 0) {
|
|
Packit |
61cb5a |
return (sent);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
return (0);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
/*
|
|
Packit |
61cb5a |
* Send init message. ucast_socket is socket used to send message, remote_addr is address of host
|
|
Packit |
61cb5a |
* to send message, mcast_addr is used multicast address, client_id is client id string with
|
|
Packit |
61cb5a |
* CLIENTID_LEN length, req_si should be non 0 if server information request is required.
|
|
Packit |
61cb5a |
* Function returns 0 on success, otherwise same error as rs_sendto or -4 if message cannot be
|
|
Packit |
61cb5a |
* created (usually due to small message buffer)
|
|
Packit |
61cb5a |
*/
|
|
Packit |
61cb5a |
int
|
|
Packit |
61cb5a |
ms_init(int ucast_socket, const struct sockaddr_storage *remote_addr,
|
|
Packit |
61cb5a |
const struct sockaddr_storage *mcast_addr, const char *client_id, int req_si)
|
|
Packit |
61cb5a |
{
|
|
Packit |
61cb5a |
char addr_str[INET6_ADDRSTRLEN];
|
|
Packit |
61cb5a |
char msg[MAX_MSG_SIZE];
|
|
Packit |
61cb5a |
size_t msg_len;
|
|
Packit |
61cb5a |
ssize_t sent;
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
af_sa_to_str(AF_CAST_SA(remote_addr), addr_str);
|
|
Packit |
61cb5a |
DEBUG_PRINTF("Sending init msg to %s", addr_str);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
msg_len = msg_init_create(msg, sizeof(msg), req_si, mcast_addr, client_id, CLIENTID_LEN);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (msg_len == 0) {
|
|
Packit |
61cb5a |
return (-4);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
sent = rs_sendto(ucast_socket, msg, msg_len, remote_addr);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
return (sent);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
/*
|
|
Packit |
61cb5a |
* Send query message. ucast_socket is socket used to send message, remote_addr is address of host
|
|
Packit |
61cb5a |
* to send message, mcast_addr is used multicast address, client_id is client id string with
|
|
Packit |
61cb5a |
* CLIENTID_LEN length, ses_id is Session ID string with ses_id_len length. seq_num is sequential
|
|
Packit |
61cb5a |
* number to set in packet.
|
|
Packit |
61cb5a |
* Function returns 0 on success, otherwise same error as rs_sendto or -4 if message cannot be
|
|
Packit |
61cb5a |
* created (usually due to small message buffer)
|
|
Packit |
61cb5a |
*/
|
|
Packit |
61cb5a |
int
|
|
Packit |
61cb5a |
ms_query(int ucast_socket, const struct sockaddr_storage *remote_addr,
|
|
Packit |
61cb5a |
const struct sockaddr_storage *mcast_addr, uint32_t seq_num, const char *client_id,
|
|
Packit |
61cb5a |
const char *ses_id, size_t ses_id_len)
|
|
Packit |
61cb5a |
{
|
|
Packit |
61cb5a |
char addr_str[INET6_ADDRSTRLEN];
|
|
Packit |
61cb5a |
char msg[MAX_MSG_SIZE];
|
|
Packit |
61cb5a |
size_t msg_len;
|
|
Packit |
61cb5a |
ssize_t sent;
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
af_sa_to_str(AF_CAST_SA(remote_addr), addr_str);
|
|
Packit |
61cb5a |
DEBUG_PRINTF("Sending query msg to %s", addr_str);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
msg_len = msg_query_create(msg, sizeof(msg), mcast_addr, seq_num, 0, client_id,
|
|
Packit |
61cb5a |
CLIENTID_LEN, ses_id, SESSIONID_LEN);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (msg_len == 0) {
|
|
Packit |
61cb5a |
return (-4);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
sent = rs_sendto(ucast_socket, msg, msg_len, remote_addr);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
return (sent);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
/*
|
|
Packit |
61cb5a |
* Send response message. ucast_socket is socket used to send message, mcast_addr is used multicast
|
|
Packit |
61cb5a |
* address, decoded is decoded message, to is sockaddr_storage address of destination, mcast_grp is
|
|
Packit |
61cb5a |
* used to distinguish if add or not add mcast group tlv, similarly to mcast_prefix. session_id and
|
|
Packit |
61cb5a |
* is session id string with session_id_len length.
|
|
Packit |
61cb5a |
* Function returns 0 on sucess, otherwise same error as rs_sendto or -4 if message cannot be
|
|
Packit |
61cb5a |
* created (usually due to small message buffer)
|
|
Packit |
61cb5a |
*/
|
|
Packit |
61cb5a |
int
|
|
Packit |
61cb5a |
ms_response(int ucast_socket, const struct sockaddr_storage *mcast_addr,
|
|
Packit |
61cb5a |
const struct msg_decoded *decoded, const struct sockaddr_storage *to, int mcast_grp,
|
|
Packit |
61cb5a |
int mcast_prefix, const char *session_id, size_t session_id_len)
|
|
Packit |
61cb5a |
{
|
|
Packit |
61cb5a |
char addr_str[INET6_ADDRSTRLEN];
|
|
Packit |
61cb5a |
char msg[MAX_MSG_SIZE];
|
|
Packit |
61cb5a |
size_t msg_len;
|
|
Packit |
61cb5a |
ssize_t sent;
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
af_sa_to_str((struct sockaddr *)to, addr_str);
|
|
Packit |
61cb5a |
DEBUG_PRINTF("Sending response msg to %s", addr_str);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
msg_len = msg_response_create(msg, sizeof(msg), decoded, mcast_grp, mcast_prefix,
|
|
Packit |
61cb5a |
mcast_addr, session_id, session_id_len);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
if (msg_len == 0) {
|
|
Packit |
61cb5a |
return (-4);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
sent = rs_sendto(ucast_socket, msg, msg_len, to);
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
return (sent);
|
|
Packit |
61cb5a |
}
|
|
Packit |
61cb5a |
|
|
Packit |
61cb5a |
/*
|
|
Packit |
61cb5a |
* Send response message with stop meaning. It's just shortcut to ms_send_response where
|
|
Packit |
61cb5a |
* parameters with same name has same meaning. Also returned values are same.
|
|
Packit |
61cb5a |
*/
|
|
Packit |
61cb5a |
int
|
|
Packit |
61cb5a |
ms_stop(int ucast_socket, const struct sockaddr_storage *mcast_addr,
|
|
Packit |
61cb5a |
const struct msg_decoded *decoded, const struct sockaddr_storage *to)
|
|
Packit |
61cb5a |
{
|
|
Packit |
61cb5a |
return (ms_response(ucast_socket, mcast_addr, decoded, to, 0,0, NULL, 0));
|
|
Packit |
61cb5a |
}
|