1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

as an optimization for when we want to send multiple tickles at a time

let the caller create the sending socket and use a single socket instead 
of one new one for each tickle.
pass a sending socket to ctdb_sys_send_tcp()

ctdb_sys_kill_tcp is not longer used so remove it

set the socketflags for close on exec and nonblocking in the helper that 
creates the sockets instead of in the caller

add a helper to create a sending socket to send tickles from

(This used to be ctdb commit 469f3fb238a0674a2b48fdf1a7e657e32428178a)
This commit is contained in:
Ronnie Sahlberg 2007-07-12 09:22:06 +10:00
parent 823b7d4a5f
commit a650497680
4 changed files with 78 additions and 149 deletions

View File

@ -183,12 +183,12 @@ static uint16_t tcp_checksum(uint16_t *data, size_t n, struct iphdr *ip)
This can also be used to send RST segments (if rst is true) and also
if correct seq and ack numbers are provided.
*/
int ctdb_sys_send_tcp(const struct sockaddr_in *dest,
int ctdb_sys_send_tcp(int s,
const struct sockaddr_in *dest,
const struct sockaddr_in *src,
uint32_t seq, uint32_t ack, int rst)
{
int s, ret;
uint32_t one = 1;
int ret;
struct {
struct iphdr ip;
struct tcphdr tcp;
@ -200,21 +200,6 @@ int ctdb_sys_send_tcp(const struct sockaddr_in *dest,
return -1;
}
s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
if (s == -1) {
DEBUG(0,(__location__ " failed to open raw socket (%s)\n",
strerror(errno)));
return -1;
}
ret = setsockopt(s, SOL_IP, IP_HDRINCL, &one, sizeof(one));
if (ret != 0) {
DEBUG(0,(__location__ " failed to setup IP headers (%s)\n",
strerror(errno)));
close(s);
return -1;
}
ZERO_STRUCT(pkt);
pkt.ip.version = 4;
pkt.ip.ihl = sizeof(pkt.ip)/4;
@ -240,11 +225,9 @@ int ctdb_sys_send_tcp(const struct sockaddr_in *dest,
ret = sendto(s, &pkt, sizeof(pkt), 0, dest, sizeof(*dest));
if (ret != sizeof(pkt)) {
DEBUG(0,(__location__ " failed sendto (%s)\n", strerror(errno)));
close(s);
return -1;
}
close(s);
return 0;
}
@ -273,119 +256,6 @@ bool ctdb_sys_have_ip(const char *ip)
return ret == 0;
}
static void ctdb_wait_handler(struct event_context *ev, struct timed_event *te,
struct timeval yt, void *p)
{
uint32_t *timed_out = (uint32_t *)p;
(*timed_out) = 1;
}
/* This function is used to kill (RST) the specified tcp connection.
This function is not asynchronous and will block until the operation
was successful or it timesout.
*/
int ctdb_sys_kill_tcp(struct event_context *ev,
const struct sockaddr_in *dst,
const struct sockaddr_in *src)
{
int s, ret;
uint32_t timedout;
TALLOC_CTX *tmp_ctx = talloc_new(NULL);
#define RCVPKTSIZE 100
char pkt[RCVPKTSIZE];
struct ether_header *eth;
struct iphdr *ip;
struct tcphdr *tcp;
/* Open a socket to capture all traffic */
s=socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1){
DEBUG(0,(__location__ " failed to open raw socket\n"));
return -1;
}
/* We wait for up to 1 second for the ACK coming back */
timedout = 0;
event_add_timed(ev, tmp_ctx, timeval_current_ofs(1, 0), ctdb_wait_handler, &timedout);
/* Send a tickle ack to probe what the real seq/ack numbers are */
ctdb_sys_send_tcp(dst, src, 0, 0, 0);
/* Wait until we either time out or we succeeds in sending the RST */
while (timedout==0) {
event_loop_once(ev);
ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC);
if (ret < sizeof(*eth)+sizeof(*ip)) {
continue;
}
/* Ethernet */
eth = (struct ether_header *)pkt;
/* We only want IP packets */
if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
continue;
}
/* IP */
ip = (struct iphdr *)(eth+1);
/* We only want IPv4 packets */
if (ip->version != 4) {
continue;
}
/* Dont look at fragments */
if ((ntohs(ip->frag_off)&0x1fff) != 0) {
continue;
}
/* we only want TCP */
if (ip->protocol != IPPROTO_TCP) {
continue;
}
/* We only want packets sent from the guy we tickled */
if (ip->saddr != dst->sin_addr.s_addr) {
continue;
}
/* We only want packets sent to us */
if (ip->daddr != src->sin_addr.s_addr) {
continue;
}
/* make sure its not a short packet */
if (offsetof(struct tcphdr, ack_seq) + 4 +
(ip->ihl*4) + sizeof(*eth) > ret) {
continue;
}
/* TCP */
tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip);
/* We only want replies from the port we tickled */
if (tcp->source != dst->sin_port) {
continue;
}
if (tcp->dest != src->sin_port) {
continue;
}
ctdb_sys_send_tcp(dst, src, tcp->ack_seq, tcp->seq, 1);
close(s);
talloc_free(tmp_ctx);
return 0;
}
close(s);
talloc_free(tmp_ctx);
DEBUG(0,(__location__ " timedout waiting for tickle ack reply\n"));
return -1;
}
/* This function is used to open a raw socket to capture from
*/
int ctdb_sys_open_capture_socket(void)
@ -399,9 +269,41 @@ int ctdb_sys_open_capture_socket(void)
return -1;
}
set_nonblocking(s);
set_close_on_exec(s);
return s;
}
/* This function is used to open a raw socket to send tickles from
*/
int ctdb_sys_open_sending_socket(void)
{
int s, ret;
uint32_t one = 1;
s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
if (s == -1) {
DEBUG(0,(__location__ " failed to open raw socket (%s)\n",
strerror(errno)));
return -1;
}
ret = setsockopt(s, SOL_IP, IP_HDRINCL, &one, sizeof(one));
if (ret != 0) {
DEBUG(0,(__location__ " failed to setup IP headers (%s)\n",
strerror(errno)));
close(s);
return -1;
}
set_nonblocking(s);
set_close_on_exec(s);
return s;
}
int ctdb_sys_read_tcp_packet(struct ctdb_kill_tcp *killtcp)
{
int ret;
@ -469,7 +371,7 @@ int ctdb_sys_read_tcp_packet(struct ctdb_kill_tcp *killtcp)
/* This one has been tickled !
now reset him and remove him from the list.
*/
ctdb_sys_send_tcp(&conn->dst, &conn->src, tcp->ack_seq, tcp->seq, 1);
ctdb_sys_send_tcp(killtcp->sending_fd, &conn->dst, &conn->src, tcp->ack_seq, tcp->seq, 1);
talloc_free(conn);
return 0;

View File

@ -990,12 +990,10 @@ int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
/* from takeover/system.c */
int ctdb_sys_send_arp(const struct sockaddr_in *saddr, const char *iface);
bool ctdb_sys_have_ip(const char *ip);
int ctdb_sys_send_tcp(const struct sockaddr_in *dest,
int ctdb_sys_send_tcp(int fd,
const struct sockaddr_in *dest,
const struct sockaddr_in *src,
uint32_t seq, uint32_t ack, int rst);
int ctdb_sys_kill_tcp(struct event_context *ev,
const struct sockaddr_in *dest,
const struct sockaddr_in *src);
int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist);
int ctdb_set_event_script(struct ctdb_context *ctdb, const char *script);
@ -1061,10 +1059,12 @@ struct ctdb_killtcp_connection {
struct ctdb_kill_tcp {
struct ctdb_context *ctdb;
int capture_fd;
int sending_fd;
struct fd_event *fde;
struct ctdb_killtcp_connection *connections;
};
int ctdb_sys_open_capture_socket(void);
int ctdb_sys_open_sending_socket(void);
int ctdb_killtcp_add_connection(struct ctdb_context *ctdb, struct sockaddr_in *src, struct sockaddr_in *dst);
int ctdb_sys_read_tcp_packet(struct ctdb_kill_tcp *killtcp);

View File

@ -69,7 +69,7 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
{
struct ctdb_takeover_arp *arp = talloc_get_type(private_data,
struct ctdb_takeover_arp);
int ret;
int s, ret;
struct ctdb_tcp_list *tcp;
ret = ctdb_sys_send_arp(&arp->sin, arp->ctdb->takeover.interface);
@ -77,25 +77,32 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
DEBUG(0,(__location__ " sending of arp failed (%s)\n", strerror(errno)));
}
s = ctdb_sys_open_sending_socket();
if (s == -1) {
DEBUG(0,(__location__ " failed to open raw socket for sending tickles\n"));
return;
}
for (tcp=arp->tcp_list;tcp;tcp=tcp->next) {
DEBUG(2,("sending tcp tickle ack for %u->%s:%u\n",
(unsigned)ntohs(tcp->daddr.sin_port),
inet_ntoa(tcp->saddr.sin_addr),
(unsigned)ntohs(tcp->saddr.sin_port)));
ret = ctdb_sys_send_tcp(&tcp->saddr, &tcp->daddr, 0, 0, 0);
ret = ctdb_sys_send_tcp(s, &tcp->saddr, &tcp->daddr, 0, 0, 0);
if (ret != 0) {
DEBUG(0,(__location__ " Failed to send tcp tickle ack for %s\n",
inet_ntoa(tcp->saddr.sin_addr)));
}
}
close(s);
arp->count++;
if (arp->count == CTDB_ARP_REPEAT) {
talloc_free(arp);
return;
}
event_add_timed(arp->ctdb->ev, arp->ctdb->takeover.last_ctx,
timeval_current_ofs(CTDB_ARP_INTERVAL, 0),
ctdb_control_send_arp, arp);
@ -869,7 +876,7 @@ static void ctdb_tickle_sentenced_connections(struct event_context *ev, struct t
continue;
}
ctdb_sys_send_tcp(&conn->dst, &conn->src, 0, 0, 0);
ctdb_sys_send_tcp(killtcp->sending_fd, &conn->dst, &conn->src, 0, 0, 0);
}
/* If there are no more connections to kill we can remove the
@ -891,8 +898,14 @@ static void ctdb_tickle_sentenced_connections(struct event_context *ev, struct t
*/
static int ctdb_killtcp_destructor(struct ctdb_kill_tcp *killtcp)
{
close(killtcp->capture_fd);
killtcp->capture_fd = -1;
if (killtcp->capture_fd != -1) {
close(killtcp->capture_fd);
killtcp->capture_fd = -1;
}
if (killtcp->sending_fd != -1) {
close(killtcp->sending_fd);
killtcp->sending_fd = -1;
}
killtcp->ctdb->killtcp = NULL;
return 0;
@ -921,6 +934,7 @@ int ctdb_killtcp_add_connection(struct ctdb_context *ctdb, struct sockaddr_in *s
killtcp->ctdb = ctdb;
killtcp->capture_fd = -1;
killtcp->sending_fd = -1;
killtcp->connections = NULL;
ctdb->killtcp = killtcp;
talloc_set_destructor(killtcp, ctdb_killtcp_destructor);
@ -934,11 +948,17 @@ int ctdb_killtcp_add_connection(struct ctdb_context *ctdb, struct sockaddr_in *s
DEBUG(0,(__location__ " Failed to open capturing socket for killtcp\n"));
goto failed;
}
set_nonblocking(killtcp->capture_fd);
set_close_on_exec(killtcp->capture_fd);
}
/* If we dont have a socket to send from yet we must create it
*/
if (killtcp->sending_fd == -1) {
killtcp->sending_fd = ctdb_sys_open_sending_socket();
if (killtcp->sending_fd == -1) {
DEBUG(0,(__location__ " Failed to open sending socket for killtcp\n"));
goto failed;
}
}
conn = talloc(killtcp, struct ctdb_killtcp_connection);
CTDB_NO_MEMORY(ctdb, conn);

View File

@ -338,7 +338,7 @@ static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
*/
static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
{
int ret;
int s, ret;
struct sockaddr_in src, dst;
if (argc < 2) {
@ -355,7 +355,14 @@ static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
return -1;
}
ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
s = ctdb_sys_open_sending_socket();
if (s == -1) {
printf("Failed to open socket for sending tickle\n");
return 0;
}
ret = ctdb_sys_send_tcp(s, &src, &dst, 0, 0, 0);
close(s);
if (ret==0) {
return 0;
}