4 Copyright (C) Ronnie Sahlberg 2007
5 Copyright (C) Andrew Tridgell 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "system/network.h"
23 #include "system/filesys.h"
24 #include "system/wait.h"
25 #include "../include/ctdb_private.h"
26 #include "lib/events/events.h"
27 #include <net/ethernet.h>
28 #include <net/if_arp.h>
33 send gratuitous arp reply after we have taken over an ip address
35 saddr is the address we are trying to claim
36 iface is the interface name we will be using to claim the address
38 int ctdb_sys_send_arp(const struct sockaddr_in *saddr, const char *iface)
42 struct ether_header *eh;
44 struct ifreq if_hwaddr;
45 unsigned char buffer[64]; /*minimum eth frame size */
48 /* for now, we only handle AF_INET addresses */
49 if (saddr->sin_family != AF_INET) {
50 DEBUG(0,(__location__ " not an ipv4 address (family is %u)\n", saddr->sin_family));
54 s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_ARP));
56 DEBUG(0,(__location__ " failed to open raw socket\n"));
60 /* get the mac address */
61 strcpy(if_hwaddr.ifr_name, iface);
62 ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
65 DEBUG(0,(__location__ " ioctl failed\n"));
68 if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) {
69 DEBUG(3,("Ignoring loopback arp request\n"));
73 if (if_hwaddr.ifr_hwaddr.sa_family != AF_LOCAL) {
76 DEBUG(0,(__location__ " not an ethernet address family (0x%x)\n",
77 if_hwaddr.ifr_hwaddr.sa_family));
82 memset(buffer, 0 , 64);
83 eh = (struct ether_header *)buffer;
84 memset(eh->ether_dhost, 0xff, ETH_ALEN);
85 memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
86 eh->ether_type = htons(ETHERTYPE_ARP);
88 ah = (struct arphdr *)&buffer[sizeof(struct ether_header)];
89 ah->ar_hrd = htons(ARPHRD_ETHER);
90 ah->ar_pro = htons(ETH_P_IP);
91 ah->ar_hln = ETH_ALEN;
94 /* send a gratious arp */
95 ah->ar_op = htons(ARPOP_REQUEST);
97 memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
99 memcpy(ptr, &saddr->sin_addr, 4);
101 memset(ptr, 0, ETH_ALEN);
103 memcpy(ptr, &saddr->sin_addr, 4);
106 strncpy(sa.sa_data, iface, sizeof(sa.sa_data));
107 ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
110 DEBUG(0,(__location__ " failed sendto\n"));
114 /* send unsolicited arp reply broadcast */
115 ah->ar_op = htons(ARPOP_REPLY);
116 ptr = (char *)&ah[1];
117 memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
119 memcpy(ptr, &saddr->sin_addr, 4);
121 memcpy(ptr, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
123 memcpy(ptr, &saddr->sin_addr, 4);
126 strncpy(sa.sa_data, iface, sizeof(sa.sa_data));
127 ret = sendto(s, buffer, 64, 0, &sa, sizeof(sa));
129 DEBUG(0,(__location__ " failed sendto\n"));
139 uint16 checksum for n bytes
141 static uint32_t uint16_checksum(uint16_t *data, size_t n)
145 sum += (uint32_t)ntohs(*data);
150 sum += (uint32_t)ntohs(*(uint8_t *)data);
156 simple TCP checksum - assumes data is multiple of 2 bytes long
158 static uint16_t tcp_checksum(uint16_t *data, size_t n, struct iphdr *ip)
160 uint32_t sum = uint16_checksum(data, n);
162 sum += uint16_checksum((uint16_t *)&ip->saddr, sizeof(ip->saddr));
163 sum += uint16_checksum((uint16_t *)&ip->daddr, sizeof(ip->daddr));
164 sum += ip->protocol + n;
165 sum = (sum & 0xFFFF) + (sum >> 16);
166 sum = (sum & 0xFFFF) + (sum >> 16);
176 Send tcp segment from the specified IP/port to the specified
179 This is used to trigger the receiving host into sending its own ACK,
180 which should trigger early detection of TCP reset by the client
183 This can also be used to send RST segments (if rst is true) and also
184 if correct seq and ack numbers are provided.
186 int ctdb_sys_send_tcp(const struct sockaddr_in *dest,
187 const struct sockaddr_in *src,
188 uint32_t seq, uint32_t ack, int rst)
197 /* for now, we only handle AF_INET addresses */
198 if (src->sin_family != AF_INET || dest->sin_family != AF_INET) {
199 DEBUG(0,(__location__ " not an ipv4 address\n"));
203 s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
205 DEBUG(0,(__location__ " failed to open raw socket (%s)\n",
210 ret = setsockopt(s, SOL_IP, IP_HDRINCL, &one, sizeof(one));
212 DEBUG(0,(__location__ " failed to setup IP headers (%s)\n",
220 pkt.ip.ihl = sizeof(pkt.ip)/4;
221 pkt.ip.tot_len = htons(sizeof(pkt));
223 pkt.ip.protocol = IPPROTO_TCP;
224 pkt.ip.saddr = src->sin_addr.s_addr;
225 pkt.ip.daddr = dest->sin_addr.s_addr;
228 pkt.tcp.source = src->sin_port;
229 pkt.tcp.dest = dest->sin_port;
231 pkt.tcp.ack_seq = ack;
236 pkt.tcp.doff = sizeof(pkt.tcp)/4;
237 pkt.tcp.window = htons(1234);
238 pkt.tcp.check = tcp_checksum((uint16_t *)&pkt.tcp, sizeof(pkt.tcp), &pkt.ip);
240 ret = sendto(s, &pkt, sizeof(pkt), 0, dest, sizeof(*dest));
241 if (ret != sizeof(pkt)) {
242 DEBUG(0,(__location__ " failed sendto (%s)\n", strerror(errno)));
253 see if we currently have an interface with the given IP
255 we try to bind to it, and if that fails then we don't have that IP
258 bool ctdb_sys_have_ip(const char *ip)
260 struct sockaddr_in sin;
265 inet_aton(ip, &sin.sin_addr);
266 sin.sin_family = AF_INET;
267 s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
271 ret = bind(s, (struct sockaddr *)&sin, sizeof(sin));
276 static void ctdb_wait_handler(struct event_context *ev, struct timed_event *te,
277 struct timeval yt, void *p)
279 uint32_t *timed_out = (uint32_t *)p;
283 /* This function is used to kill (RST) the specified tcp connection.
285 This function is not asynchronous and will block until the operation
286 was successful or it timesout.
288 int ctdb_sys_kill_tcp(struct event_context *ev,
289 const struct sockaddr_in *dst,
290 const struct sockaddr_in *src)
294 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
295 #define RCVPKTSIZE 100
296 char pkt[RCVPKTSIZE];
297 struct ether_header *eth;
301 /* Open a socket to capture all traffic */
302 s=socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
304 DEBUG(0,(__location__ " failed to open raw socket\n"));
308 /* We wait for up to 1 second for the ACK coming back */
310 event_add_timed(ev, tmp_ctx, timeval_current_ofs(1, 0), ctdb_wait_handler, &timedout);
312 /* Send a tickle ack to probe what the real seq/ack numbers are */
313 ctdb_sys_send_tcp(dst, src, 0, 0, 0);
315 /* Wait until we either time out or we succeeds in sending the RST */
316 while (timedout==0) {
319 ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC);
320 if (ret < sizeof(*eth)+sizeof(*ip)) {
325 eth = (struct ether_header *)pkt;
326 /* We only want IP packets */
327 if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
332 ip = (struct iphdr *)(eth+1);
333 /* We only want IPv4 packets */
334 if (ip->version != 4) {
337 /* Dont look at fragments */
338 if ((ntohs(ip->frag_off)&0x1fff) != 0) {
341 /* we only want TCP */
342 if (ip->protocol != IPPROTO_TCP) {
346 /* We only want packets sent from the guy we tickled */
347 if (ip->saddr != dst->sin_addr.s_addr) {
350 /* We only want packets sent to us */
351 if (ip->daddr != src->sin_addr.s_addr) {
355 /* make sure its not a short packet */
356 if (offsetof(struct tcphdr, ack_seq) + 4 +
357 (ip->ihl*4) + sizeof(*eth) > ret) {
362 tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip);
364 /* We only want replies from the port we tickled */
365 if (tcp->source != dst->sin_port) {
368 if (tcp->dest != src->sin_port) {
372 ctdb_sys_send_tcp(dst, src, tcp->ack_seq, tcp->seq, 1);
375 talloc_free(tmp_ctx);
381 talloc_free(tmp_ctx);
382 DEBUG(0,(__location__ " timedout waiting for tickle ack reply\n"));