From: Martin Schwenke Date: Thu, 28 Jun 2018 11:12:04 +0000 (+1000) Subject: ctdb-common: Move capture_socket functions to ctdb_socket.[ch] X-Git-Tag: tevent-0.9.37~177 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=fa94a49dbbec4a65c368a533a534f952a9f147a7;p=thirdparty%2Fsamba.git ctdb-common: Move capture_socket functions to ctdb_socket.[ch] The system_.c files contain a lot of duplication, making maintenance difficult. These functions are being merged into system_socket.c and system.c. Bring across ctdb_sys_open_capture_socket(), ctdb_sys_close_capture_socket() and ctdb_sys_read_tcp_packet(). Remove empty system_.c files. Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs --- diff --git a/ctdb/common/system.h b/ctdb/common/system.h index 5507c0527fe..8d558e2f7ad 100644 --- a/ctdb/common/system.h +++ b/ctdb/common/system.h @@ -22,15 +22,6 @@ #include -/* From system_.c */ - -int ctdb_sys_open_capture_socket(const char *iface, void **private_data); -int ctdb_sys_close_capture_socket(void *private_data); -int ctdb_sys_read_tcp_packet(int s, void *private_data, - ctdb_sock_addr *src, ctdb_sock_addr *dst, - uint32_t *ack_seq, uint32_t *seq, - int *rst, uint16_t *window); - /* From system_util.c */ bool set_scheduler(void); diff --git a/ctdb/common/system_aix.c b/ctdb/common/system_aix.c deleted file mode 100644 index 08ee10383b3..00000000000 --- a/ctdb/common/system_aix.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - ctdb system specific code to manage raw sockets on aix - - Copyright (C) Ronnie Sahlberg 2007 - Copyright (C) Andrew Tridgell 2007 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . -*/ - - -#include "replace.h" -#include "system/network.h" -#include "system/filesys.h" -#include "system/wait.h" - -#include "lib/util/debug.h" -#include "lib/util/blocking.h" - -#include "protocol/protocol.h" - -#include -#include -#include -#include -#include -#include - -#include "common/logging.h" -#include "common/system.h" -#include "common/system_socket.h" - - -#if 0 -This function is no longer used and its code should be moved into -send tcp packet after that function has been enhanced to do ipv6 as well. - -/* 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, IPPROTO_RAW); - if (s == -1) { - DEBUG(DEBUG_CRIT,(" failed to open raw socket (%s)\n", - strerror(errno))); - return -1; - } - - ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)); - if (ret != 0) { - DEBUG(DEBUG_CRIT, (" failed to setup IP headers (%s)\n", - strerror(errno))); - close(s); - return -1; - } - - set_blocking(s, false); - set_close_on_exec(s); - - return s; -} -#endif - -/* This function is used to open a raw socket to capture from - */ -int ctdb_sys_open_capture_socket(const char *iface, void **private_data) -{ - pcap_t *pt; - - pt=pcap_open_live(iface, 100, 0, 0, NULL); - if (pt == NULL) { - DEBUG(DEBUG_CRIT,("Failed to open capture device %s\n", iface)); - return -1; - } - *((pcap_t **)private_data) = pt; - - return pcap_fileno(pt); -} - - -/* This function is used to close the capture socket - */ -int ctdb_sys_close_capture_socket(void *private_data) -{ - pcap_t *pt = (pcap_t *)private_data; - pcap_close(pt); - return 0; -} - -/* - get ethernet MAC address on AIX - */ -static int aix_get_mac_addr(const char *device_name, uint8_t mac[6]) -{ - size_t ksize; - struct kinfo_ndd *ndd; - int count, i; - - ksize = getkerninfo(KINFO_NDD, 0, 0, 0); - if (ksize == 0) { - errno = ENOSYS; - return -1; - } - - ndd = (struct kinfo_ndd *)malloc(ksize); - if (ndd == NULL) { - errno = ENOMEM; - return -1; - } - - if (getkerninfo(KINFO_NDD, ndd, &ksize, 0) == -1) { - errno = ENOSYS; - return -1; - } - - count= ksize/sizeof(struct kinfo_ndd); - for (i=0;iether_type == htons(ETHERTYPE_IP)) { - /* IP */ - ip = (struct ip *)(eth+1); - - /* We only want IPv4 packets */ - if (ip->ip_v != 4) { - return -1; - } - /* Dont look at fragments */ - if ((ntohs(ip->ip_off)&0x1fff) != 0) { - return -1; - } - /* we only want TCP */ - if (ip->ip_p != IPPROTO_TCP) { - return -1; - } - - /* make sure its not a short packet */ - if (offsetof(struct tcphdr, th_ack) + 4 + - (ip->ip_hl*4) > ret) { - return -1; - } - /* TCP */ - tcp = (struct tcphdr *)((ip->ip_hl*4) + (char *)ip); - - /* tell the caller which one we've found */ - src->ip.sin_family = AF_INET; - src->ip.sin_addr.s_addr = ip->ip_src.s_addr; - src->ip.sin_port = tcp->th_sport; - dst->ip.sin_family = AF_INET; - dst->ip.sin_addr.s_addr = ip->ip_dst.s_addr; - dst->ip.sin_port = tcp->th_dport; - *ack_seq = tcp->th_ack; - *seq = tcp->th_seq; - if (window != NULL) { - *window = tcp->th_win; - } - if (rst != NULL) { - *rst = tcp->th_flags & TH_RST; - } - - return 0; -#ifndef ETHERTYPE_IP6 -#define ETHERTYPE_IP6 0x86dd -#endif - } else if (eth->ether_type == htons(ETHERTYPE_IP6)) { - /* IP6 */ - ip6 = (struct ip6_hdr *)(eth+1); - - /* we only want TCP */ - if (ip6->ip6_nxt != IPPROTO_TCP) { - return -1; - } - - /* TCP */ - tcp = (struct tcphdr *)(ip6+1); - - /* tell the caller which one we've found */ - src->ip6.sin6_family = AF_INET6; - src->ip6.sin6_port = tcp->th_sport; - src->ip6.sin6_addr = ip6->ip6_src; - - dst->ip6.sin6_family = AF_INET6; - dst->ip6.sin6_port = tcp->th_dport; - dst->ip6.sin6_addr = ip6->ip6_dst; - - *ack_seq = tcp->th_ack; - *seq = tcp->th_seq; - if (window != NULL) { - *window = tcp->th_win; - } - if (rst != NULL) { - *rst = tcp->th_flags & TH_RST; - } - - return 0; - } - - return -1; -} diff --git a/ctdb/common/system_freebsd.c b/ctdb/common/system_freebsd.c deleted file mode 100644 index 5ed6d192e11..00000000000 --- a/ctdb/common/system_freebsd.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - ctdb system specific code to manage raw sockets on freebsd - - Copyright (C) Ronnie Sahlberg 2007 - Copyright (C) Andrew Tridgell 2007 - Copyright (C) Marc Dequènes (Duck) 2009 - Copyright (C) Volker Lendecke 2012 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . - - - This file is a copy of 'common/system_linux.c' adapted for Hurd^W kFreeBSD - needs, and inspired by 'common/system_aix.c' for the pcap usage. -*/ - -#include "replace.h" -#include "system/network.h" -#include "system/filesys.h" -#include "system/wait.h" - -#include "lib/util/debug.h" -#include "lib/util/blocking.h" - -#include "protocol/protocol.h" - -#include -#include -#include -#include - -#include "common/logging.h" -#include "common/system.h" -#include "common/system_socket.h" - -#ifndef ETHERTYPE_IP6 -#define ETHERTYPE_IP6 0x86dd -#endif - -/* - This function is used to open a raw socket to capture from - */ -int ctdb_sys_open_capture_socket(const char *iface, void **private_data) -{ - pcap_t *pt; - - pt=pcap_open_live(iface, 100, 0, 0, NULL); - if (pt == NULL) { - DEBUG(DEBUG_CRIT,("Failed to open capture device %s\n", iface)); - return -1; - } - *((pcap_t **)private_data) = pt; - - return pcap_fileno(pt); -} - -/* This function is used to close the capture socket - */ -int ctdb_sys_close_capture_socket(void *private_data) -{ - pcap_t *pt = (pcap_t *)private_data; - pcap_close(pt); - return 0; -} - - -/* - called when the raw socket becomes readable - */ -int ctdb_sys_read_tcp_packet(int s, void *private_data, - ctdb_sock_addr *src, ctdb_sock_addr *dst, - uint32_t *ack_seq, uint32_t *seq, - int *rst, uint16_t *window) -{ - int ret; -#define RCVPKTSIZE 100 - char pkt[RCVPKTSIZE]; - struct ether_header *eth; - struct ip *ip; - struct ip6_hdr *ip6; - struct tcphdr *tcp; - - ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC); - if (ret < sizeof(*eth)+sizeof(*ip)) { - return -1; - } - - ZERO_STRUCTP(src); - ZERO_STRUCTP(dst); - - /* Ethernet */ - eth = (struct ether_header *)pkt; - - /* we want either IPv4 or IPv6 */ - if (ntohs(eth->ether_type) == ETHERTYPE_IP) { - /* IP */ - ip = (struct ip *)(eth+1); - - /* We only want IPv4 packets */ - if (ip->ip_v != 4) { - return -1; - } - /* Dont look at fragments */ - if ((ntohs(ip->ip_off)&0x1fff) != 0) { - return -1; - } - /* we only want TCP */ - if (ip->ip_p != IPPROTO_TCP) { - return -1; - } - - /* make sure its not a short packet */ - if (offsetof(struct tcphdr, th_ack) + 4 + - (ip->ip_hl*4) + sizeof(*eth) > ret) { - return -1; - } - /* TCP */ - tcp = (struct tcphdr *)((ip->ip_hl*4) + (char *)ip); - - /* tell the caller which one we've found */ - src->ip.sin_family = AF_INET; - src->ip.sin_addr.s_addr = ip->ip_src.s_addr; - src->ip.sin_port = tcp->th_sport; - dst->ip.sin_family = AF_INET; - dst->ip.sin_addr.s_addr = ip->ip_dst.s_addr; - dst->ip.sin_port = tcp->th_dport; - *ack_seq = tcp->th_ack; - *seq = tcp->th_seq; - if (window != NULL) { - *window = tcp->th_win; - } - if (rst != NULL) { - *rst = tcp->th_flags & TH_RST; - } - - return 0; - } else if (ntohs(eth->ether_type) == ETHERTYPE_IP6) { - /* IP6 */ - ip6 = (struct ip6_hdr *)(eth+1); - - /* we only want TCP */ - if (ip6->ip6_nxt != IPPROTO_TCP) { - return -1; - } - - /* TCP */ - tcp = (struct tcphdr *)(ip6+1); - - /* tell the caller which one we've found */ - src->ip6.sin6_family = AF_INET6; - src->ip6.sin6_port = tcp->th_sport; - src->ip6.sin6_addr = ip6->ip6_src; - - dst->ip6.sin6_family = AF_INET6; - dst->ip6.sin6_port = tcp->th_dport; - dst->ip6.sin6_addr = ip6->ip6_dst; - - *ack_seq = tcp->th_ack; - *seq = tcp->th_seq; - if (window != NULL) { - *window = tcp->th_win; - } - if (rst != NULL) { - *rst = tcp->th_flags & TH_RST; - } - - return 0; - } - - return -1; -} diff --git a/ctdb/common/system_gnu.c b/ctdb/common/system_gnu.c deleted file mode 100644 index 2b81bd9cef3..00000000000 --- a/ctdb/common/system_gnu.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - ctdb system specific code to manage raw sockets on linux - - Copyright (C) Ronnie Sahlberg 2007 - Copyright (C) Andrew Tridgell 2007 - Copyright (C) Marc Dequènes (Duck) 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . - - - This file is a copy of 'common/system_linux.c' adapted for Hurd needs, - and inspired by 'common/system_aix.c' for the pcap usage. -*/ - -#include "replace.h" -#include "system/network.h" -#include "system/filesys.h" -#include "system/wait.h" - -#include "lib/util/debug.h" -#include "lib/util/blocking.h" - -#include "protocol/protocol.h" - -#include -#include -#include -#include - -#include "common/logging.h" -#include "common/system.h" -#include "common/system_socket.h" - -#ifndef ETHERTYPE_IP6 -#define ETHERTYPE_IP6 0x86dd -#endif - -/* - This function is used to open a raw socket to capture from - */ -int ctdb_sys_open_capture_socket(const char *iface, void **private_data) -{ - pcap_t *pt; - - pt=pcap_open_live(iface, 100, 0, 0, NULL); - if (pt == NULL) { - DEBUG(DEBUG_CRIT,("Failed to open capture device %s\n", iface)); - return -1; - } - *((pcap_t **)private_data) = pt; - - return pcap_fileno(pt); -} - -/* This function is used to close the capture socket - */ -int ctdb_sys_close_capture_socket(void *private_data) -{ - pcap_t *pt = (pcap_t *)private_data; - pcap_close(pt); - return 0; -} - - -/* - called when the raw socket becomes readable - */ -int ctdb_sys_read_tcp_packet(int s, void *private_data, - ctdb_sock_addr *src, ctdb_sock_addr *dst, - uint32_t *ack_seq, uint32_t *seq, - int *rst, uint16_t *window) -{ - int ret; -#define RCVPKTSIZE 100 - char pkt[RCVPKTSIZE]; - struct ether_header *eth; - struct iphdr *ip; - struct ip6_hdr *ip6; - struct tcphdr *tcp; - - ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC); - if (ret < sizeof(*eth)+sizeof(*ip)) { - return -1; - } - - ZERO_STRUCTP(src); - ZERO_STRUCTP(dst); - - /* Ethernet */ - eth = (struct ether_header *)pkt; - - /* we want either IPv4 or IPv6 */ - if (ntohs(eth->ether_type) == ETHERTYPE_IP) { - /* IP */ - ip = (struct iphdr *)(eth+1); - - /* We only want IPv4 packets */ - if (ip->version != 4) { - return -1; - } - /* Dont look at fragments */ - if ((ntohs(ip->frag_off)&0x1fff) != 0) { - return -1; - } - /* we only want TCP */ - if (ip->protocol != IPPROTO_TCP) { - return -1; - } - - /* make sure its not a short packet */ - if (offsetof(struct tcphdr, ack_seq) + 4 + - (ip->ihl*4) + sizeof(*eth) > ret) { - return -1; - } - /* TCP */ - tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip); - - /* tell the caller which one we've found */ - src->ip.sin_family = AF_INET; - src->ip.sin_addr.s_addr = ip->saddr; - src->ip.sin_port = tcp->source; - dst->ip.sin_family = AF_INET; - dst->ip.sin_addr.s_addr = ip->daddr; - dst->ip.sin_port = tcp->dest; - *ack_seq = tcp->ack_seq; - *seq = tcp->seq; - if (window != NULL) { - *window = tcp->window; - } - if (rst != NULL) { - *rst = tcp->rst; - } - - return 0; - } else if (ntohs(eth->ether_type) == ETHERTYPE_IP6) { - /* IP6 */ - ip6 = (struct ip6_hdr *)(eth+1); - - /* we only want TCP */ - if (ip6->ip6_nxt != IPPROTO_TCP) { - return -1; - } - - /* TCP */ - tcp = (struct tcphdr *)(ip6+1); - - /* tell the caller which one we've found */ - src->ip6.sin6_family = AF_INET6; - src->ip6.sin6_port = tcp->source; - src->ip6.sin6_addr = ip6->ip6_src; - - dst->ip6.sin6_family = AF_INET6; - dst->ip6.sin6_port = tcp->dest; - dst->ip6.sin6_addr = ip6->ip6_dst; - - *ack_seq = tcp->ack_seq; - *seq = tcp->seq; - if (window != NULL) { - *window = tcp->window; - } - if (rst != NULL) { - *rst = tcp->rst; - } - - return 0; - } - - return -1; -} diff --git a/ctdb/common/system_kfreebsd.c b/ctdb/common/system_kfreebsd.c deleted file mode 100644 index 700dde15d45..00000000000 --- a/ctdb/common/system_kfreebsd.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - ctdb system specific code to manage raw sockets on linux - - Copyright (C) Ronnie Sahlberg 2007 - Copyright (C) Andrew Tridgell 2007 - Copyright (C) Marc Dequènes (Duck) 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . - - - This file is a copy of 'common/system_linux.c' adapted for Hurd^W kFreeBSD - needs, and inspired by 'common/system_aix.c' for the pcap usage. -*/ - -#include "replace.h" -#include "system/network.h" -#include "system/filesys.h" -#include "system/wait.h" - -#include "lib/util/debug.h" -#include "lib/util/blocking.h" - -#include "protocol/protocol.h" - -#include -#include -#include -#include - -#include "common/logging.h" -#include "common/system.h" -#include "common/system_socket.h" - -/* - This function is used to open a raw socket to capture from - */ -int ctdb_sys_open_capture_socket(const char *iface, void **private_data) -{ - pcap_t *pt; - - pt=pcap_open_live(iface, 100, 0, 0, NULL); - if (pt == NULL) { - DEBUG(DEBUG_CRIT,("Failed to open capture device %s\n", iface)); - return -1; - } - *((pcap_t **)private_data) = pt; - - return pcap_fileno(pt); -} - -/* This function is used to close the capture socket - */ -int ctdb_sys_close_capture_socket(void *private_data) -{ - pcap_t *pt = (pcap_t *)private_data; - pcap_close(pt); - return 0; -} - - -/* - called when the raw socket becomes readable - */ -int ctdb_sys_read_tcp_packet(int s, void *private_data, - ctdb_sock_addr *src, ctdb_sock_addr *dst, - uint32_t *ack_seq, uint32_t *seq, - int *rst, uint16_t *window) -{ - int ret; -#define RCVPKTSIZE 100 - char pkt[RCVPKTSIZE]; - struct ether_header *eth; - struct iphdr *ip; - struct ip6_hdr *ip6; - struct tcphdr *tcp; - - ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC); - if (ret < sizeof(*eth)+sizeof(*ip)) { - return -1; - } - - ZERO_STRUCTP(src); - ZERO_STRUCTP(dst); - - /* Ethernet */ - eth = (struct ether_header *)pkt; - - /* we want either IPv4 or IPv6 */ - if (ntohs(eth->ether_type) == ETHERTYPE_IP) { - /* IP */ - ip = (struct iphdr *)(eth+1); - - /* We only want IPv4 packets */ - if (ip->version != 4) { - return -1; - } - /* Dont look at fragments */ - if ((ntohs(ip->frag_off)&0x1fff) != 0) { - return -1; - } - /* we only want TCP */ - if (ip->protocol != IPPROTO_TCP) { - return -1; - } - - /* make sure its not a short packet */ - if (offsetof(struct tcphdr, ack_seq) + 4 + - (ip->ihl*4) + sizeof(*eth) > ret) { - return -1; - } - /* TCP */ - tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip); - - /* tell the caller which one we've found */ - src->ip.sin_family = AF_INET; - src->ip.sin_addr.s_addr = ip->saddr; - src->ip.sin_port = tcp->source; - dst->ip.sin_family = AF_INET; - dst->ip.sin_addr.s_addr = ip->daddr; - dst->ip.sin_port = tcp->dest; - *ack_seq = tcp->ack_seq; - *seq = tcp->seq; - if (window != NULL) { - *window = tcp->window; - } - if (rst != NULL) { - *rst = tcp->rst; - } - - return 0; - } else if (ntohs(eth->ether_type) == ETHERTYPE_IP6) { - /* IP6 */ - ip6 = (struct ip6_hdr *)(eth+1); - - /* we only want TCP */ - if (ip6->ip6_nxt != IPPROTO_TCP) { - return -1; - } - - /* TCP */ - tcp = (struct tcphdr *)(ip6+1); - - /* tell the caller which one we've found */ - src->ip6.sin6_family = AF_INET6; - src->ip6.sin6_port = tcp->source; - src->ip6.sin6_addr = ip6->ip6_src; - - dst->ip6.sin6_family = AF_INET6; - dst->ip6.sin6_port = tcp->dest; - dst->ip6.sin6_addr = ip6->ip6_dst; - - *ack_seq = tcp->ack_seq; - *seq = tcp->seq; - if (window != NULL) { - *window = tcp->window; - } - if (rst != NULL) { - *rst = tcp->rst; - } - - return 0; - } - - return -1; -} diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c deleted file mode 100644 index c8b072054f4..00000000000 --- a/ctdb/common/system_linux.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - ctdb system specific code to manage raw sockets on linux - - Copyright (C) Ronnie Sahlberg 2007 - Copyright (C) Andrew Tridgell 2007 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, see . -*/ - -#include "replace.h" -#include "system/network.h" -#include "system/filesys.h" -#include "system/wait.h" - -#include "lib/util/debug.h" -#include "lib/util/blocking.h" - -#include "protocol/protocol.h" - -#include -#include -#include -#include -#include -#include - -#include "common/logging.h" -#include "common/system.h" -#include "common/system_socket.h" - -#ifndef ETHERTYPE_IP6 -#define ETHERTYPE_IP6 0x86dd -#endif - -/* - This function is used to open a raw socket to capture from - */ -int ctdb_sys_open_capture_socket(const char *iface, void **private_data) -{ - int s, ret; - - /* Open a socket to capture all traffic */ - s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (s == -1) { - DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n")); - return -1; - } - - DEBUG(DEBUG_DEBUG, (__location__ " Created RAW SOCKET FD:%d for tcp tickle\n", s)); - - ret = set_blocking(s, false); - if (ret != 0) { - DEBUG(DEBUG_ERR, - (__location__ - " failed to set socket non-blocking (%s)\n", - strerror(errno))); - close(s); - return -1; - } - - set_close_on_exec(s); - - return s; -} - -/* - This function is used to do any additional cleanup required when closing - a capture socket. - Note that the socket itself is closed automatically in the caller. - */ -int ctdb_sys_close_capture_socket(void *private_data) -{ - return 0; -} - - -/* - called when the raw socket becomes readable - */ -int ctdb_sys_read_tcp_packet(int s, void *private_data, - ctdb_sock_addr *src, ctdb_sock_addr *dst, - uint32_t *ack_seq, uint32_t *seq, - int *rst, uint16_t *window) -{ - int ret; -#define RCVPKTSIZE 100 - char pkt[RCVPKTSIZE]; - struct ether_header *eth; - struct iphdr *ip; - struct ip6_hdr *ip6; - struct tcphdr *tcp; - - ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC); - if (ret < sizeof(*eth)+sizeof(*ip)) { - return -1; - } - - ZERO_STRUCTP(src); - ZERO_STRUCTP(dst); - - /* Ethernet */ - eth = (struct ether_header *)pkt; - - /* we want either IPv4 or IPv6 */ - if (ntohs(eth->ether_type) == ETHERTYPE_IP) { - /* IP */ - ip = (struct iphdr *)(eth+1); - - /* We only want IPv4 packets */ - if (ip->version != 4) { - return -1; - } - /* Dont look at fragments */ - if ((ntohs(ip->frag_off)&0x1fff) != 0) { - return -1; - } - /* we only want TCP */ - if (ip->protocol != IPPROTO_TCP) { - return -1; - } - - /* make sure its not a short packet */ - if (offsetof(struct tcphdr, ack_seq) + 4 + - (ip->ihl*4) + sizeof(*eth) > ret) { - return -1; - } - /* TCP */ - tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip); - - /* tell the caller which one we've found */ - src->ip.sin_family = AF_INET; - src->ip.sin_addr.s_addr = ip->saddr; - src->ip.sin_port = tcp->source; - dst->ip.sin_family = AF_INET; - dst->ip.sin_addr.s_addr = ip->daddr; - dst->ip.sin_port = tcp->dest; - *ack_seq = tcp->ack_seq; - *seq = tcp->seq; - if (window != NULL) { - *window = tcp->window; - } - if (rst != NULL) { - *rst = tcp->rst; - } - - return 0; - } else if (ntohs(eth->ether_type) == ETHERTYPE_IP6) { - /* IP6 */ - ip6 = (struct ip6_hdr *)(eth+1); - - /* we only want TCP */ - if (ip6->ip6_nxt != IPPROTO_TCP) { - return -1; - } - - /* TCP */ - tcp = (struct tcphdr *)(ip6+1); - - /* tell the caller which one we've found */ - src->ip6.sin6_family = AF_INET6; - src->ip6.sin6_port = tcp->source; - src->ip6.sin6_addr = ip6->ip6_src; - - dst->ip6.sin6_family = AF_INET6; - dst->ip6.sin6_port = tcp->dest; - dst->ip6.sin6_addr = ip6->ip6_dst; - - *ack_seq = tcp->ack_seq; - *seq = tcp->seq; - if (window != NULL) { - *window = tcp->window; - } - if (rst != NULL) { - *rst = tcp->rst; - } - - return 0; - } - - return -1; -} diff --git a/ctdb/common/system_socket.c b/ctdb/common/system_socket.c index ea371281efe..d8627fd61fc 100644 --- a/ctdb/common/system_socket.c +++ b/ctdb/common/system_socket.c @@ -55,6 +55,7 @@ #endif #include "lib/util/debug.h" +#include "lib/util/blocking.h" #include "protocol/protocol.h" @@ -677,3 +678,297 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, return 0; } + +/* + * Packet capture + * + * If AF_PACKET is available then use a raw socket otherwise use pcap. + * wscript has checked to make sure that pcap is available if needed. + */ + +#ifdef HAVE_AF_PACKET + +/* + * This function is used to open a raw socket to capture from + */ +int ctdb_sys_open_capture_socket(const char *iface, void **private_data) +{ + int s, ret; + + /* Open a socket to capture all traffic */ + s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); + if (s == -1) { + DBG_ERR("Failed to open raw socket\n"); + return -1; + } + + DBG_DEBUG("Created RAW SOCKET FD:%d for tcp tickle\n", s); + + ret = set_blocking(s, false); + if (ret != 0) { + DBG_ERR("Failed to set socket non-blocking (%s)\n", + strerror(errno)); + close(s); + return -1; + } + + set_close_on_exec(s); + + return s; +} + +/* + * This function is used to do any additional cleanup required when closing + * a capture socket. + * Note that the socket itself is closed automatically in the caller. + */ +int ctdb_sys_close_capture_socket(void *private_data) +{ + return 0; +} + + +/* + * called when the raw socket becomes readable + */ +int ctdb_sys_read_tcp_packet(int s, void *private_data, + ctdb_sock_addr *src, + ctdb_sock_addr *dst, + uint32_t *ack_seq, + uint32_t *seq, + int *rst, + uint16_t *window) +{ + int ret; +#define RCVPKTSIZE 100 + char pkt[RCVPKTSIZE]; + struct ether_header *eth; + struct iphdr *ip; + struct ip6_hdr *ip6; + struct tcphdr *tcp; + + ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC); + if (ret < sizeof(*eth)+sizeof(*ip)) { + return -1; + } + + ZERO_STRUCTP(src); + ZERO_STRUCTP(dst); + + /* Ethernet */ + eth = (struct ether_header *)pkt; + + /* we want either IPv4 or IPv6 */ + if (ntohs(eth->ether_type) == ETHERTYPE_IP) { + /* IP */ + ip = (struct iphdr *)(eth+1); + + /* We only want IPv4 packets */ + if (ip->version != 4) { + return -1; + } + /* Dont look at fragments */ + if ((ntohs(ip->frag_off)&0x1fff) != 0) { + return -1; + } + /* we only want TCP */ + if (ip->protocol != IPPROTO_TCP) { + return -1; + } + + /* make sure its not a short packet */ + if (offsetof(struct tcphdr, th_ack) + 4 + + (ip->ihl*4) + sizeof(*eth) > ret) { + return -1; + } + /* TCP */ + tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip); + + /* tell the caller which one we've found */ + src->ip.sin_family = AF_INET; + src->ip.sin_addr.s_addr = ip->saddr; + src->ip.sin_port = tcp->th_sport; + dst->ip.sin_family = AF_INET; + dst->ip.sin_addr.s_addr = ip->daddr; + dst->ip.sin_port = tcp->th_dport; + *ack_seq = tcp->th_ack; + *seq = tcp->th_seq; + if (window != NULL) { + *window = tcp->th_win; + } + if (rst != NULL) { + *rst = tcp->th_flags & TH_RST; + } + + return 0; + } else if (ntohs(eth->ether_type) == ETHERTYPE_IP6) { + /* IP6 */ + ip6 = (struct ip6_hdr *)(eth+1); + + /* we only want TCP */ + if (ip6->ip6_nxt != IPPROTO_TCP) { + return -1; + } + + /* TCP */ + tcp = (struct tcphdr *)(ip6+1); + + /* tell the caller which one we've found */ + src->ip6.sin6_family = AF_INET6; + src->ip6.sin6_port = tcp->th_sport; + src->ip6.sin6_addr = ip6->ip6_src; + + dst->ip6.sin6_family = AF_INET6; + dst->ip6.sin6_port = tcp->th_dport; + dst->ip6.sin6_addr = ip6->ip6_dst; + + *ack_seq = tcp->th_ack; + *seq = tcp->th_seq; + if (window != NULL) { + *window = tcp->th_win; + } + if (rst != NULL) { + *rst = tcp->th_flags & TH_RST; + } + + return 0; + } + + return -1; +} + +#else /* HAVE_AF_PACKET */ + +#include + +int ctdb_sys_open_capture_socket(const char *iface, void **private_data) +{ + pcap_t *pt; + + pt=pcap_open_live(iface, 100, 0, 0, NULL); + if (pt == NULL) { + DBG_ERR("Failed to open capture device %s\n", iface); + return -1; + } + *((pcap_t **)private_data) = pt; + + return pcap_fileno(pt); +} + +int ctdb_sys_close_capture_socket(void *private_data) +{ + pcap_t *pt = (pcap_t *)private_data; + pcap_close(pt); + return 0; +} + +int ctdb_sys_read_tcp_packet(int s, + void *private_data, + ctdb_sock_addr *src, + ctdb_sock_addr *dst, + uint32_t *ack_seq, + uint32_t *seq, + int *rst, + uint16_t *window) +{ + int ret; + struct ether_header *eth; + struct ip *ip; + struct ip6_hdr *ip6; + struct tcphdr *tcp; + struct ctdb_killtcp_connection *conn; + struct pcap_pkthdr pkthdr; + const u_char *buffer; + pcap_t *pt = (pcap_t *)private_data; + + buffer=pcap_next(pt, &pkthdr); + if (buffer==NULL) { + return -1; + } + + ZERO_STRUCTP(src); + ZERO_STRUCTP(dst); + + /* Ethernet */ + eth = (struct ether_header *)buffer; + + /* we want either IPv4 or IPv6 */ + if (eth->ether_type == htons(ETHERTYPE_IP)) { + /* IP */ + ip = (struct ip *)(eth+1); + + /* We only want IPv4 packets */ + if (ip->ip_v != 4) { + return -1; + } + /* Dont look at fragments */ + if ((ntohs(ip->ip_off)&0x1fff) != 0) { + return -1; + } + /* we only want TCP */ + if (ip->ip_p != IPPROTO_TCP) { + return -1; + } + + /* make sure its not a short packet */ + if (offsetof(struct tcphdr, th_ack) + 4 + + (ip->ip_hl*4) > ret) { + return -1; + } + /* TCP */ + tcp = (struct tcphdr *)((ip->ip_hl*4) + (char *)ip); + + /* tell the caller which one we've found */ + src->ip.sin_family = AF_INET; + src->ip.sin_addr.s_addr = ip->ip_src.s_addr; + src->ip.sin_port = tcp->th_sport; + dst->ip.sin_family = AF_INET; + dst->ip.sin_addr.s_addr = ip->ip_dst.s_addr; + dst->ip.sin_port = tcp->th_dport; + *ack_seq = tcp->th_ack; + *seq = tcp->th_seq; + if (window != NULL) { + *window = tcp->th_win; + } + if (rst != NULL) { + *rst = tcp->th_flags & TH_RST; + } + + return 0; + } else if (eth->ether_type == htons(ETHERTYPE_IP6)) { + /* IP6 */ + ip6 = (struct ip6_hdr *)(eth+1); + + /* we only want TCP */ + if (ip6->ip6_nxt != IPPROTO_TCP) { + return -1; + } + + /* TCP */ + tcp = (struct tcphdr *)(ip6+1); + + /* tell the caller which one we've found */ + src->ip6.sin6_family = AF_INET6; + src->ip6.sin6_port = tcp->th_sport; + src->ip6.sin6_addr = ip6->ip6_src; + + dst->ip6.sin6_family = AF_INET6; + dst->ip6.sin6_port = tcp->th_dport; + dst->ip6.sin6_addr = ip6->ip6_dst; + + *ack_seq = tcp->th_ack; + *seq = tcp->th_seq; + if (window != NULL) { + *window = tcp->th_win; + } + if (rst != NULL) { + *rst = tcp->th_flags & TH_RST; + } + + return 0; + } + + return -1; +} + +#endif /* HAVE_AF_PACKET */ diff --git a/ctdb/common/system_socket.h b/ctdb/common/system_socket.h index 5f49bb985bd..eb2c6f7b6ae 100644 --- a/ctdb/common/system_socket.h +++ b/ctdb/common/system_socket.h @@ -37,4 +37,15 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, uint32_t ack, int rst); +int ctdb_sys_open_capture_socket(const char *iface, void **private_data); +int ctdb_sys_close_capture_socket(void *private_data); +int ctdb_sys_read_tcp_packet(int s, + void *private_data, + ctdb_sock_addr *src, + ctdb_sock_addr *dst, + uint32_t *ack_seq, + uint32_t *seq, + int *rst, + uint16_t *window); + #endif /* __CTDB_SYSTEM_SOCKET_H__ */ diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c index 981293554b0..7881268a9af 100644 --- a/ctdb/tools/ctdb.c +++ b/ctdb/tools/ctdb.c @@ -40,7 +40,6 @@ #include "protocol/protocol.h" #include "protocol/protocol_api.h" #include "protocol/protocol_util.h" -#include "common/system.h" #include "common/system_socket.h" #include "client/client.h" #include "client/client_sync.h" diff --git a/ctdb/tools/ctdb_killtcp.c b/ctdb/tools/ctdb_killtcp.c index d7cd51a7cb3..f352c9bdae6 100644 --- a/ctdb/tools/ctdb_killtcp.c +++ b/ctdb/tools/ctdb_killtcp.c @@ -30,7 +30,6 @@ #include "protocol/protocol_util.h" #include "common/db_hash.h" -#include "common/system.h" #include "common/system_socket.h" #include "common/logging.h" diff --git a/ctdb/wscript b/ctdb/wscript index ec828389c9e..fb3f277da01 100644 --- a/ctdb/wscript +++ b/ctdb/wscript @@ -380,23 +380,9 @@ def build(bld): deps='replace talloc tevent tdb') ib_deps = ' ctdb-ib rdmacm ibverbs' - if sys.platform.startswith('linux'): - CTDB_SYSTEM_SRC = bld.SUBDIR('common', 'system_linux.c') - elif sys.platform.startswith('aix'): - CTDB_SYSTEM_SRC = bld.SUBDIR('common', 'system_aix.c') - elif sys.platform.startswith('freebsd'): - CTDB_SYSTEM_SRC = bld.SUBDIR('common', 'system_freebsd.c') - elif sys.platform.startswith('gnukfreebsd'): - CTDB_SYSTEM_SRC = bld.SUBDIR('common', 'system_kfreebsd.c') - elif sys.platform == 'gnu': - CTDB_SYSTEM_SRC = bld.SUBDIR('common', 'system_gnu.c') - else: - Logs.error("Platform %s not supported" % sys.platform) - bld.SAMBA_SUBSYSTEM('ctdb-system', source=bld.SUBDIR('common', - 'system_socket.c system.c') + - CTDB_SYSTEM_SRC, + 'system_socket.c system.c'), includes='include', deps='replace talloc tevent tdb pcap samba-util')