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

add a new ctdb_sys_kill_tcp() function that kills (RST) the specified

connection

(This used to be ctdb commit 11a972f37d4ca7daf052b3b502620af05699bec4)
This commit is contained in:
Ronnie Sahlberg 2007-07-04 13:53:22 +10:00
parent 8f0a00b72b
commit a52f6760f3
2 changed files with 108 additions and 0 deletions

View File

@ -984,6 +984,9 @@ bool ctdb_sys_have_ip(const char *ip);
int ctdb_sys_send_tcp(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);

View File

@ -438,3 +438,108 @@ int ctdb_event_script_callback(struct ctdb_context *ctdb,
return 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<40) {
continue;
}
/* Ethernet */
eth = (struct ether_header *)pkt;
/* We only want IP packets */
if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
continue;
}
/* IP */
ip = (struct iphdr *)&pkt[14];
/* 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;
}
/* TCP */
tcp = (struct tcphdr *)&pkt[14+ip->ihl*4];
/* 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;
}