1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-10 01:18:15 +03:00

ctdb-common: Move capture_socket functions to ctdb_socket.[ch]

The system_<os>.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_<os>.c files.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
This commit is contained in:
Martin Schwenke 2018-06-28 21:12:04 +10:00 committed by Martin Schwenke
parent eafcc98b03
commit fa94a49dbb
11 changed files with 307 additions and 1015 deletions

View File

@ -22,15 +22,6 @@
#include <talloc.h>
/* From system_<os>.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);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <netinet/if_ether.h>
#include <netinet/ip6.h>
#include <net/if_arp.h>
#include <sys/ndd_var.h>
#include <sys/kinfo.h>
#include <pcap.h>
#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;i<count;i++) {
if ( (ndd[i].ndd_type != NDD_ETHER)
&& (ndd[i].ndd_type != NDD_ISO88023) ) {
continue;
}
if (ndd[i].ndd_addrlen != 6) {
continue;
}
if (!(ndd[i].ndd_flags&NDD_UP)) {
continue;
}
if ( strcmp(device_name, ndd[i].ndd_name)
&& strcmp(device_name, ndd[i].ndd_alias) ) {
continue;
}
memcpy(mac, ndd[i].ndd_addr, 6);
free(ndd);
return 0;
}
free(ndd);
errno = ENOENT;
return -1;
}
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;
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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 <net/ethernet.h>
#include <netinet/ip6.h>
#include <net/if_arp.h>
#include <pcap.h>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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 <net/ethernet.h>
#include <netinet/ip6.h>
#include <net/if_arp.h>
#include <pcap.h>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
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 <net/ethernet.h>
#include <netinet/ip6.h>
#include <net/if_arp.h>
#include <pcap.h>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <netinet/if_ether.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <net/if_arp.h>
#include <netpacket/packet.h>
#include <sys/prctl.h>
#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;
}

View File

@ -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 <pcap.h>
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 */

View File

@ -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__ */

View File

@ -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"

View File

@ -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"

View File

@ -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')