2 ctdb system specific code to manage raw sockets on linux
4 Copyright (C) Ronnie Sahlberg 2007
5 Copyright (C) Andrew Tridgell 2007
6 Copyright (C) Marc Dequènes (Duck) 2009
7 Copyright (C) Volker Lendecke 2012
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, see <http://www.gnu.org/licenses/>.
26 * Use BSD struct tcphdr field names for portability. Modern glibc
27 * makes them available by default via <netinet/tcp.h> but older glibc
28 * requires __FAVOR_BSD to be defined.
30 * __FAVOR_BSD is normally defined in <features.h> if _DEFAULT_SOURCE
31 * (new) or _BSD_SOURCE (now deprecated) is set and _GNU_SOURCE is not
32 * set. Including "replace.h" above causes <features.h> to be
33 * indirectly included and this will not set __FAVOR_BSD because
34 * _GNU_SOURCE is set in Samba's "config.h" (which is included by
37 * Therefore, set __FAVOR_BSD by hand below.
40 #include "system/network.h"
42 #ifdef HAVE_NETINET_IF_ETHER_H
43 #include <netinet/if_ether.h>
45 #ifdef HAVE_NETINET_IP6_H
46 #include <netinet/ip6.h>
48 #ifdef HAVE_NETINET_ICMP6_H
49 #include <netinet/icmp6.h>
51 #ifdef HAVE_LINUX_IF_PACKET_H
52 #include <linux/if_packet.h>
56 #define ETHERTYPE_IP6 0x86dd
59 #include "lib/util/debug.h"
60 #include "lib/util/blocking.h"
62 #include "protocol/protocol.h"
64 #include "common/logging.h"
65 #include "common/system_socket.h"
68 uint16 checksum for n bytes
70 static uint32_t uint16_checksum(uint8_t *data
, size_t n
)
76 memcpy(&value
, data
, 2);
77 sum
+= (uint32_t)ntohs(value
);
82 sum
+= (uint32_t)ntohs(*data
);
88 * See if the given IP is currently on an interface
90 bool ctdb_sys_have_ip(ctdb_sock_addr
*_addr
)
94 ctdb_sock_addr __addr
= *_addr
;
95 ctdb_sock_addr
*addr
= &__addr
;
96 socklen_t addrlen
= 0;
98 switch (addr
->sa
.sa_family
) {
100 addr
->ip
.sin_port
= 0;
101 addrlen
= sizeof(struct sockaddr_in
);
104 addr
->ip6
.sin6_port
= 0;
105 addrlen
= sizeof(struct sockaddr_in6
);
109 s
= socket(addr
->sa
.sa_family
, SOCK_STREAM
, IPPROTO_TCP
);
114 ret
= bind(s
, (struct sockaddr
*)addr
, addrlen
);
121 * simple TCP checksum - assumes data is multiple of 2 bytes long
123 static uint16_t ip_checksum(uint8_t *data
, size_t n
, struct ip
*ip
)
125 uint32_t sum
= uint16_checksum(data
, n
);
128 sum
+= uint16_checksum((uint8_t *)&ip
->ip_src
, sizeof(ip
->ip_src
));
129 sum
+= uint16_checksum((uint8_t *)&ip
->ip_dst
, sizeof(ip
->ip_dst
));
131 sum
= (sum
& 0xFFFF) + (sum
>> 16);
132 sum
= (sum
& 0xFFFF) + (sum
>> 16);
141 static uint16_t ip6_checksum(uint8_t *data
, size_t n
, struct ip6_hdr
*ip6
)
148 sum
+= uint16_checksum((uint8_t *)&ip6
->ip6_src
, 16);
149 sum
+= uint16_checksum((uint8_t *)&ip6
->ip6_dst
, 16);
152 phdr
[0] = len
& UINT16_MAX
;
153 phdr
[1] = (len
>> 16) & UINT16_MAX
;
154 /* ip6_nxt is only 8 bits, so fits comfortably into a uint16_t */
155 phdr
[2] = htons(ip6
->ip6_nxt
);
156 sum
+= uint16_checksum((uint8_t *)phdr
, sizeof(phdr
));
158 sum
+= uint16_checksum(data
, n
);
160 sum
= (sum
& 0xFFFF) + (sum
>> 16);
161 sum
= (sum
& 0xFFFF) + (sum
>> 16);
171 * Send gratuitous ARP request/reply or IPv6 neighbor advertisement
174 #ifdef HAVE_PACKETSOCKET
177 * Create IPv4 ARP requests/replies or IPv6 neighbour advertisement
181 #define ARP_STRUCT_SIZE sizeof(struct ether_header) + \
182 sizeof(struct ether_arp)
184 #define IP6_NA_STRUCT_SIZE sizeof(struct ether_header) + \
185 sizeof(struct ip6_hdr) + \
186 sizeof(struct nd_neighbor_advert) + \
187 sizeof(struct nd_opt_hdr) + \
188 sizeof(struct ether_addr)
190 #define ARP_BUFFER_SIZE MAX(ARP_STRUCT_SIZE, 64)
192 #define IP6_NA_BUFFER_SIZE MAX(IP6_NA_STRUCT_SIZE, 64)
194 static int arp_build(uint8_t *buffer
,
196 const struct sockaddr_in
*addr
,
197 const struct ether_addr
*hwaddr
,
199 struct ether_addr
**ether_dhost
,
202 size_t l
= ARP_BUFFER_SIZE
;
203 struct ether_header
*eh
;
204 struct ether_arp
*ea
;
207 if (addr
->sin_family
!= AF_INET
) {
215 memset(buffer
, 0 , l
);
217 eh
= (struct ether_header
*)buffer
;
218 memset(eh
->ether_dhost
, 0xff, ETH_ALEN
);
219 memcpy(eh
->ether_shost
, hwaddr
, ETH_ALEN
);
220 eh
->ether_type
= htons(ETHERTYPE_ARP
);
222 ea
= (struct ether_arp
*)(buffer
+ sizeof(struct ether_header
));
224 ah
->ar_hrd
= htons(ARPHRD_ETHER
);
225 ah
->ar_pro
= htons(ETH_P_IP
);
226 ah
->ar_hln
= ETH_ALEN
;
227 ah
->ar_pln
= sizeof(ea
->arp_spa
);
230 ah
->ar_op
= htons(ARPOP_REQUEST
);
231 memcpy(ea
->arp_sha
, hwaddr
, ETH_ALEN
);
232 memcpy(ea
->arp_spa
, &addr
->sin_addr
, sizeof(ea
->arp_spa
));
233 memset(ea
->arp_tha
, 0, ETH_ALEN
);
234 memcpy(ea
->arp_tpa
, &addr
->sin_addr
, sizeof(ea
->arp_tpa
));
236 ah
->ar_op
= htons(ARPOP_REPLY
);
237 memcpy(ea
->arp_sha
, hwaddr
, ETH_ALEN
);
238 memcpy(ea
->arp_spa
, &addr
->sin_addr
, sizeof(ea
->arp_spa
));
239 memcpy(ea
->arp_tha
, hwaddr
, ETH_ALEN
);
240 memcpy(ea
->arp_tpa
, &addr
->sin_addr
, sizeof(ea
->arp_tpa
));
243 *ether_dhost
= (struct ether_addr
*)eh
->ether_dhost
;
248 static int ip6_na_build(uint8_t *buffer
,
250 const struct sockaddr_in6
*addr
,
251 const struct ether_addr
*hwaddr
,
252 struct ether_addr
**ether_dhost
,
255 size_t l
= IP6_NA_BUFFER_SIZE
;
256 struct ether_header
*eh
;
258 struct nd_neighbor_advert
*nd_na
;
259 struct nd_opt_hdr
*nd_oh
;
260 struct ether_addr
*ea
;
263 if (addr
->sin6_family
!= AF_INET6
) {
271 memset(buffer
, 0 , l
);
273 eh
= (struct ether_header
*)buffer
;
275 * Ethernet multicast: 33:33:00:00:00:01 (see RFC2464,
276 * section 7) - note memset 0 above!
278 eh
->ether_dhost
[0] = 0x33;
279 eh
->ether_dhost
[1] = 0x33;
280 eh
->ether_dhost
[5] = 0x01;
281 memcpy(eh
->ether_shost
, hwaddr
, ETH_ALEN
);
282 eh
->ether_type
= htons(ETHERTYPE_IP6
);
284 ip6
= (struct ip6_hdr
*)(buffer
+ sizeof(struct ether_header
));
285 ip6
->ip6_vfc
= 6 << 4;
286 ip6
->ip6_plen
= htons(sizeof(struct nd_neighbor_advert
) +
287 sizeof(struct nd_opt_hdr
) +
289 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
291 ip6
->ip6_src
= addr
->sin6_addr
;
292 /* all-nodes multicast */
294 ret
= inet_pton(AF_INET6
, "ff02::1", &ip6
->ip6_dst
);
299 nd_na
= (struct nd_neighbor_advert
*)(buffer
+
300 sizeof(struct ether_header
) +
301 sizeof(struct ip6_hdr
));
302 nd_na
->nd_na_type
= ND_NEIGHBOR_ADVERT
;
303 nd_na
->nd_na_code
= 0;
304 nd_na
->nd_na_flags_reserved
= ND_NA_FLAG_OVERRIDE
;
305 nd_na
->nd_na_target
= addr
->sin6_addr
;
307 /* Option: Target link-layer address */
308 nd_oh
= (struct nd_opt_hdr
*)(buffer
+
309 sizeof(struct ether_header
) +
310 sizeof(struct ip6_hdr
) +
311 sizeof(struct nd_neighbor_advert
));
312 nd_oh
->nd_opt_type
= ND_OPT_TARGET_LINKADDR
;
313 nd_oh
->nd_opt_len
= 1; /* multiple of 8 octets */
315 ea
= (struct ether_addr
*)(buffer
+
316 sizeof(struct ether_header
) +
317 sizeof(struct ip6_hdr
) +
318 sizeof(struct nd_neighbor_advert
) +
319 sizeof(struct nd_opt_hdr
));
320 memcpy(ea
, hwaddr
, ETH_ALEN
);
322 nd_na
->nd_na_cksum
= ip6_checksum((uint8_t *)nd_na
,
323 ntohs(ip6
->ip6_plen
),
326 *ether_dhost
= (struct ether_addr
*)eh
->ether_dhost
;
331 int ctdb_sys_send_arp(const ctdb_sock_addr
*addr
, const char *iface
)
334 struct sockaddr_ll sall
= {0};
335 struct ifreq if_hwaddr
= {
340 uint8_t buffer
[MAX(ARP_BUFFER_SIZE
, IP6_NA_BUFFER_SIZE
)];
346 struct ether_addr
*hwaddr
= NULL
;
347 struct ether_addr
*ether_dhost
= NULL
;
351 s
= socket(AF_PACKET
, SOCK_RAW
, 0);
354 DBG_ERR("Failed to open raw socket\n");
357 DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s
);
360 strlcpy(ifr
.ifr_name
, iface
, sizeof(ifr
.ifr_name
));
361 if (ioctl(s
, SIOCGIFINDEX
, &ifr
) < 0) {
363 DBG_ERR("Interface '%s' not found\n", iface
);
367 /* Get MAC address */
368 strlcpy(if_hwaddr
.ifr_name
, iface
, sizeof(if_hwaddr
.ifr_name
));
369 ret
= ioctl(s
, SIOCGIFHWADDR
, &if_hwaddr
);
372 DBG_ERR("ioctl failed\n");
375 if (ARPHRD_LOOPBACK
== if_hwaddr
.ifr_hwaddr
.sa_family
) {
377 D_DEBUG("Ignoring loopback arp request\n");
380 if (if_hwaddr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
382 DBG_ERR("Not an ethernet address family (0x%x)\n",
383 if_hwaddr
.ifr_hwaddr
.sa_family
);
387 /* Set up most of destination address structure */
388 sall
.sll_family
= AF_PACKET
;
389 sall
.sll_halen
= sizeof(struct ether_addr
);
390 sall
.sll_protocol
= htons(ETH_P_ALL
);
391 sall
.sll_ifindex
= ifr
.ifr_ifindex
;
394 hwaddr
= (struct ether_addr
*)if_hwaddr
.ifr_hwaddr
.sa_data
;
396 switch (addr
->ip
.sin_family
) {
398 /* Send gratuitous ARP */
399 ret
= arp_build(buffer
,
407 DBG_ERR("Failed to build ARP request\n");
411 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
417 (struct sockaddr
*)&sall
,
421 DBG_ERR("Failed sendto\n");
425 /* Send unsolicited ARP reply */
426 ret
= arp_build(buffer
,
434 DBG_ERR("Failed to build ARP reply\n");
438 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
444 (struct sockaddr
*)&sall
,
448 DBG_ERR("Failed sendto\n");
456 ret
= ip6_na_build(buffer
,
463 DBG_ERR("Failed to build IPv6 neighbor advertisement\n");
467 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
473 (struct sockaddr
*)&sall
,
477 DBG_ERR("Failed sendto\n");
486 DBG_ERR("Not an ipv4/ipv6 address (family is %u)\n",
487 addr
->ip
.sin_family
);
498 #else /* HAVE_PACKETSOCKET */
500 int ctdb_sys_send_arp(const ctdb_sock_addr
*addr
, const char *iface
)
502 /* Not implemented */
506 #endif /* HAVE_PACKETSOCKET */
509 #define IP4_TCP_BUFFER_SIZE sizeof(struct ip) + \
510 sizeof(struct tcphdr)
512 #define IP6_TCP_BUFFER_SIZE sizeof(struct ip6_hdr) + \
513 sizeof(struct tcphdr)
515 static int tcp4_build(uint8_t *buf
,
517 const struct sockaddr_in
*src
,
518 const struct sockaddr_in
*dst
,
524 size_t l
= IP4_TCP_BUFFER_SIZE
;
530 if (l
!= sizeof(*ip4pkt
)) {
538 ip4pkt
= (void *)buf
;
539 memset(ip4pkt
, 0, l
);
542 ip4pkt
->ip
.ip_hl
= sizeof(ip4pkt
->ip
)/sizeof(uint32_t);
543 ip4pkt
->ip
.ip_len
= htons(sizeof(ip4pkt
));
544 ip4pkt
->ip
.ip_ttl
= 255;
545 ip4pkt
->ip
.ip_p
= IPPROTO_TCP
;
546 ip4pkt
->ip
.ip_src
.s_addr
= src
->sin_addr
.s_addr
;
547 ip4pkt
->ip
.ip_dst
.s_addr
= dst
->sin_addr
.s_addr
;
548 ip4pkt
->ip
.ip_sum
= 0;
550 ip4pkt
->tcp
.th_sport
= src
->sin_port
;
551 ip4pkt
->tcp
.th_dport
= dst
->sin_port
;
552 ip4pkt
->tcp
.th_seq
= seq
;
553 ip4pkt
->tcp
.th_ack
= ack
;
554 ip4pkt
->tcp
.th_flags
= 0;
555 ip4pkt
->tcp
.th_flags
|= TH_ACK
;
557 ip4pkt
->tcp
.th_flags
|= TH_RST
;
559 ip4pkt
->tcp
.th_off
= sizeof(ip4pkt
->tcp
)/sizeof(uint32_t);
560 /* this makes it easier to spot in a sniffer */
561 ip4pkt
->tcp
.th_win
= htons(1234);
562 ip4pkt
->tcp
.th_sum
= ip_checksum((uint8_t *)&ip4pkt
->tcp
,
570 static int tcp6_build(uint8_t *buf
,
572 const struct sockaddr_in6
*src
,
573 const struct sockaddr_in6
*dst
,
579 size_t l
= IP6_TCP_BUFFER_SIZE
;
585 if (l
!= sizeof(*ip6pkt
)) {
593 ip6pkt
= (void *)buf
;
594 memset(ip6pkt
, 0, l
);
596 ip6pkt
->ip6
.ip6_vfc
= 6 << 4;
597 ip6pkt
->ip6
.ip6_plen
= htons(sizeof(struct tcphdr
));
598 ip6pkt
->ip6
.ip6_nxt
= IPPROTO_TCP
;
599 ip6pkt
->ip6
.ip6_hlim
= 64;
600 ip6pkt
->ip6
.ip6_src
= src
->sin6_addr
;
601 ip6pkt
->ip6
.ip6_dst
= dst
->sin6_addr
;
603 ip6pkt
->tcp
.th_sport
= src
->sin6_port
;
604 ip6pkt
->tcp
.th_dport
= dst
->sin6_port
;
605 ip6pkt
->tcp
.th_seq
= seq
;
606 ip6pkt
->tcp
.th_ack
= ack
;
607 ip6pkt
->tcp
.th_flags
= 0;
608 ip6pkt
->tcp
.th_flags
|= TH_ACK
;
610 ip6pkt
->tcp
.th_flags
|= TH_RST
;
612 ip6pkt
->tcp
.th_off
= sizeof(ip6pkt
->tcp
)/sizeof(uint32_t);
613 /* this makes it easier to spot in a sniffer */
614 ip6pkt
->tcp
.th_win
= htons(1234);
615 ip6pkt
->tcp
.th_sum
= ip6_checksum((uint8_t *)&ip6pkt
->tcp
,
624 * Send tcp segment from the specified IP/port to the specified
625 * destination IP/port.
627 * This is used to trigger the receiving host into sending its own ACK,
628 * which should trigger early detection of TCP reset by the client
631 * This can also be used to send RST segments (if rst is true) and also
632 * if correct seq and ack numbers are provided.
634 int ctdb_sys_send_tcp(const ctdb_sock_addr
*dest
,
635 const ctdb_sock_addr
*src
,
640 uint8_t buf
[MAX(IP4_TCP_BUFFER_SIZE
, IP6_TCP_BUFFER_SIZE
)];
645 struct sockaddr_in6 tmpdest
= { 0 };
648 switch (src
->ip
.sin_family
) {
650 ret
= tcp4_build(buf
,
659 DBG_ERR("Failed to build TCP packet (%d)\n", ret
);
663 /* open a raw socket to send this segment from */
664 s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
666 DBG_ERR("Failed to open raw socket (%s)\n",
671 ret
= setsockopt(s
, IPPROTO_IP
, IP_HDRINCL
, &one
, sizeof(one
));
673 DBG_ERR("Failed to setup IP headers (%s)\n",
683 (const struct sockaddr
*)&dest
->ip
,
688 D_ERR("Failed sendto (%s)\n", strerror(saved_errno
));
691 if ((size_t)ret
!= len
) {
692 DBG_ERR("Failed sendto - didn't send full packet\n");
698 ret
= tcp6_build(buf
,
707 DBG_ERR("Failed to build TCP packet (%d)\n", ret
);
711 s
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_RAW
);
713 DBG_ERR("Failed to open sending socket\n");
718 * sendto() on an IPv6 raw socket requires the port to
719 * be either 0 or a protocol value
722 tmpdest
.sin6_port
= 0;
728 (const struct sockaddr
*)&tmpdest
,
733 D_ERR("Failed sendto (%s)\n", strerror(saved_errno
));
736 if ((size_t)ret
!= len
) {
737 DBG_ERR("Failed sendto - didn't send full packet\n");
743 DBG_ERR("Not an ipv4/v6 address\n");
753 * If AF_PACKET is available then use a raw socket otherwise use pcap.
754 * wscript has checked to make sure that pcap is available if needed.
757 static int tcp4_extract(const uint8_t *ip_pkt
,
759 struct sockaddr_in
*src
,
760 struct sockaddr_in
*dst
,
767 const struct tcphdr
*tcp
;
769 if (pktlen
< sizeof(struct ip
)) {
773 ip
= (const struct ip
*)ip_pkt
;
779 /* Don't look at fragments */
780 if ((ntohs(ip
->ip_off
)&0x1fff) != 0) {
784 if (ip
->ip_p
!= IPPROTO_TCP
) {
788 /* Ensure there is enough of the packet to gather required fields */
790 (ip
->ip_hl
* sizeof(uint32_t)) + offsetof(struct tcphdr
, th_sum
)) {
794 tcp
= (const struct tcphdr
*)(ip_pkt
+ (ip
->ip_hl
* sizeof(uint32_t)));
796 src
->sin_family
= AF_INET
;
797 src
->sin_addr
.s_addr
= ip
->ip_src
.s_addr
;
798 src
->sin_port
= tcp
->th_sport
;
800 dst
->sin_family
= AF_INET
;
801 dst
->sin_addr
.s_addr
= ip
->ip_dst
.s_addr
;
802 dst
->sin_port
= tcp
->th_dport
;
804 *ack_seq
= tcp
->th_ack
;
806 if (window
!= NULL
) {
807 *window
= tcp
->th_win
;
810 *rst
= tcp
->th_flags
& TH_RST
;
816 static int tcp6_extract(const uint8_t *ip_pkt
,
818 struct sockaddr_in6
*src
,
819 struct sockaddr_in6
*dst
,
825 const struct ip6_hdr
*ip6
;
826 const struct tcphdr
*tcp
;
828 /* Ensure there is enough of the packet to gather required fields */
829 if (pktlen
< sizeof(struct ip6_hdr
) + offsetof(struct tcphdr
, th_sum
)) {
833 ip6
= (const struct ip6_hdr
*)ip_pkt
;
836 if ((ip6
->ip6_vfc
>> 4) != 6){
841 if (ip6
->ip6_nxt
!= IPPROTO_TCP
) {
845 tcp
= (const struct tcphdr
*)(ip_pkt
+ sizeof(struct ip6_hdr
));
847 src
->sin6_family
= AF_INET6
;
848 src
->sin6_port
= tcp
->th_sport
;
849 src
->sin6_addr
= ip6
->ip6_src
;
851 dst
->sin6_family
= AF_INET6
;
852 dst
->sin6_port
= tcp
->th_dport
;
853 dst
->sin6_addr
= ip6
->ip6_dst
;
855 *ack_seq
= tcp
->th_ack
;
857 if (window
!= NULL
) {
858 *window
= tcp
->th_win
;
861 *rst
= tcp
->th_flags
& TH_RST
;
868 #ifdef HAVE_AF_PACKET
871 * This function is used to open a raw socket to capture from
873 int ctdb_sys_open_capture_socket(const char *iface
, void **private_data
)
877 /* Open a socket to capture all traffic */
878 s
= socket(AF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
880 DBG_ERR("Failed to open raw socket\n");
884 DBG_DEBUG("Created RAW SOCKET FD:%d for tcp tickle\n", s
);
886 ret
= set_blocking(s
, false);
888 DBG_ERR("Failed to set socket non-blocking (%s)\n",
894 set_close_on_exec(s
);
900 * This function is used to do any additional cleanup required when closing
902 * Note that the socket itself is closed automatically in the caller.
904 int ctdb_sys_close_capture_socket(void *private_data
)
911 * called when the raw socket becomes readable
913 int ctdb_sys_read_tcp_packet(int s
, void *private_data
,
922 uint8_t pkt
[100]; /* Large enough for simple ACK/RST packets */
923 struct ether_header
*eth
;
926 nread
= recv(s
, pkt
, sizeof(pkt
), MSG_TRUNC
);
930 if ((size_t)nread
< sizeof(*eth
)) {
938 eth
= (struct ether_header
*)pkt
;
940 /* we want either IPv4 or IPv6 */
941 if (ntohs(eth
->ether_type
) == ETHERTYPE_IP
) {
942 ret
= tcp4_extract(pkt
+ sizeof(struct ether_header
),
943 (size_t)nread
- sizeof(struct ether_header
),
952 } else if (ntohs(eth
->ether_type
) == ETHERTYPE_IP6
) {
953 ret
= tcp6_extract(pkt
+ sizeof(struct ether_header
),
954 (size_t)nread
- sizeof(struct ether_header
),
967 #else /* HAVE_AF_PACKET */
971 int ctdb_sys_open_capture_socket(const char *iface
, void **private_data
)
975 pt
=pcap_open_live(iface
, 100, 0, 0, NULL
);
977 DBG_ERR("Failed to open capture device %s\n", iface
);
980 *((pcap_t
**)private_data
) = pt
;
982 return pcap_fileno(pt
);
985 int ctdb_sys_close_capture_socket(void *private_data
)
987 pcap_t
*pt
= (pcap_t
*)private_data
;
992 int ctdb_sys_read_tcp_packet(int s
,
1002 struct ether_header
*eth
;
1003 struct pcap_pkthdr pkthdr
;
1004 const u_char
*buffer
;
1005 pcap_t
*pt
= (pcap_t
*)private_data
;
1007 buffer
=pcap_next(pt
, &pkthdr
);
1016 eth
= (struct ether_header
*)buffer
;
1018 /* we want either IPv4 or IPv6 */
1019 if (eth
->ether_type
== htons(ETHERTYPE_IP
)) {
1020 ret
= tcp4_extract(buffer
+ sizeof(struct ether_header
),
1021 (size_t)(pkthdr
.caplen
-
1022 sizeof(struct ether_header
)),
1031 } else if (eth
->ether_type
== htons(ETHERTYPE_IP6
)) {
1032 ret
= tcp6_extract(buffer
+ sizeof(struct ether_header
),
1033 (size_t)(pkthdr
.caplen
-
1034 sizeof(struct ether_header
)),
1047 #endif /* HAVE_AF_PACKET */