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(uint16_t *data
, size_t n
)
74 sum
+= (uint32_t)ntohs(*data
);
79 sum
+= (uint32_t)ntohs(*(uint8_t *)data
);
85 * See if the given IP is currently on an interface
87 bool ctdb_sys_have_ip(ctdb_sock_addr
*_addr
)
91 ctdb_sock_addr __addr
= *_addr
;
92 ctdb_sock_addr
*addr
= &__addr
;
93 socklen_t addrlen
= 0;
95 switch (addr
->sa
.sa_family
) {
97 addr
->ip
.sin_port
= 0;
98 addrlen
= sizeof(struct sockaddr_in
);
101 addr
->ip6
.sin6_port
= 0;
102 addrlen
= sizeof(struct sockaddr_in6
);
106 s
= socket(addr
->sa
.sa_family
, SOCK_STREAM
, IPPROTO_TCP
);
111 ret
= bind(s
, (struct sockaddr
*)addr
, addrlen
);
118 * simple TCP checksum - assumes data is multiple of 2 bytes long
120 static uint16_t ip_checksum(uint16_t *data
, size_t n
, struct ip
*ip
)
122 uint32_t sum
= uint16_checksum(data
, n
);
125 sum
+= uint16_checksum((uint16_t *)&ip
->ip_src
, sizeof(ip
->ip_src
));
126 sum
+= uint16_checksum((uint16_t *)&ip
->ip_dst
, sizeof(ip
->ip_dst
));
128 sum
= (sum
& 0xFFFF) + (sum
>> 16);
129 sum
= (sum
& 0xFFFF) + (sum
>> 16);
138 static uint16_t ip6_checksum(uint16_t *data
, size_t n
, struct ip6_hdr
*ip6
)
145 sum
+= uint16_checksum((uint16_t *)(void *)&ip6
->ip6_src
, 16);
146 sum
+= uint16_checksum((uint16_t *)(void *)&ip6
->ip6_dst
, 16);
149 phdr
[0] = len
& UINT16_MAX
;
150 phdr
[1] = (len
>> 16) & UINT16_MAX
;
151 /* ip6_nxt is only 8 bits, so fits comfortably into a uint16_t */
152 phdr
[2] = htons(ip6
->ip6_nxt
);
153 sum
+= uint16_checksum(phdr
, sizeof(phdr
));
155 sum
+= uint16_checksum(data
, n
);
157 sum
= (sum
& 0xFFFF) + (sum
>> 16);
158 sum
= (sum
& 0xFFFF) + (sum
>> 16);
168 * Send gratuitous ARP request/reply or IPv6 neighbor advertisement
171 #ifdef HAVE_PACKETSOCKET
174 * Create IPv4 ARP requests/replies or IPv6 neighbour advertisement
178 #define ARP_STRUCT_SIZE sizeof(struct ether_header) + \
179 sizeof(struct ether_arp)
181 #define IP6_NA_STRUCT_SIZE sizeof(struct ether_header) + \
182 sizeof(struct ip6_hdr) + \
183 sizeof(struct nd_neighbor_advert) + \
184 sizeof(struct nd_opt_hdr) + \
185 sizeof(struct ether_addr)
187 #define ARP_BUFFER_SIZE MAX(ARP_STRUCT_SIZE, 64)
189 #define IP6_NA_BUFFER_SIZE MAX(IP6_NA_STRUCT_SIZE, 64)
191 static int arp_build(uint8_t *buffer
,
193 const struct sockaddr_in
*addr
,
194 const struct ether_addr
*hwaddr
,
196 struct ether_addr
**ether_dhost
,
199 size_t l
= ARP_BUFFER_SIZE
;
200 struct ether_header
*eh
;
201 struct ether_arp
*ea
;
204 if (addr
->sin_family
!= AF_INET
) {
212 memset(buffer
, 0 , l
);
214 eh
= (struct ether_header
*)buffer
;
215 memset(eh
->ether_dhost
, 0xff, ETH_ALEN
);
216 memcpy(eh
->ether_shost
, hwaddr
, ETH_ALEN
);
217 eh
->ether_type
= htons(ETHERTYPE_ARP
);
219 ea
= (struct ether_arp
*)(buffer
+ sizeof(struct ether_header
));
221 ah
->ar_hrd
= htons(ARPHRD_ETHER
);
222 ah
->ar_pro
= htons(ETH_P_IP
);
223 ah
->ar_hln
= ETH_ALEN
;
224 ah
->ar_pln
= sizeof(ea
->arp_spa
);
227 ah
->ar_op
= htons(ARPOP_REQUEST
);
228 memcpy(ea
->arp_sha
, hwaddr
, ETH_ALEN
);
229 memcpy(ea
->arp_spa
, &addr
->sin_addr
, sizeof(ea
->arp_spa
));
230 memset(ea
->arp_tha
, 0, ETH_ALEN
);
231 memcpy(ea
->arp_tpa
, &addr
->sin_addr
, sizeof(ea
->arp_tpa
));
233 ah
->ar_op
= htons(ARPOP_REPLY
);
234 memcpy(ea
->arp_sha
, hwaddr
, ETH_ALEN
);
235 memcpy(ea
->arp_spa
, &addr
->sin_addr
, sizeof(ea
->arp_spa
));
236 memcpy(ea
->arp_tha
, hwaddr
, ETH_ALEN
);
237 memcpy(ea
->arp_tpa
, &addr
->sin_addr
, sizeof(ea
->arp_tpa
));
240 *ether_dhost
= (struct ether_addr
*)eh
->ether_dhost
;
245 static int ip6_na_build(uint8_t *buffer
,
247 const struct sockaddr_in6
*addr
,
248 const struct ether_addr
*hwaddr
,
249 struct ether_addr
**ether_dhost
,
252 size_t l
= IP6_NA_BUFFER_SIZE
;
253 struct ether_header
*eh
;
255 struct nd_neighbor_advert
*nd_na
;
256 struct nd_opt_hdr
*nd_oh
;
257 struct ether_addr
*ea
;
260 if (addr
->sin6_family
!= AF_INET6
) {
268 memset(buffer
, 0 , l
);
270 eh
= (struct ether_header
*)buffer
;
272 * Ethernet multicast: 33:33:00:00:00:01 (see RFC2464,
273 * section 7) - note memset 0 above!
275 eh
->ether_dhost
[0] = 0x33;
276 eh
->ether_dhost
[1] = 0x33;
277 eh
->ether_dhost
[5] = 0x01;
278 memcpy(eh
->ether_shost
, hwaddr
, ETH_ALEN
);
279 eh
->ether_type
= htons(ETHERTYPE_IP6
);
281 ip6
= (struct ip6_hdr
*)(buffer
+ sizeof(struct ether_header
));
282 ip6
->ip6_vfc
= 6 << 4;
283 ip6
->ip6_plen
= htons(sizeof(struct nd_neighbor_advert
) +
284 sizeof(struct nd_opt_hdr
) +
286 ip6
->ip6_nxt
= IPPROTO_ICMPV6
;
288 ip6
->ip6_src
= addr
->sin6_addr
;
289 /* all-nodes multicast */
291 ret
= inet_pton(AF_INET6
, "ff02::1", &ip6
->ip6_dst
);
296 nd_na
= (struct nd_neighbor_advert
*)(buffer
+
297 sizeof(struct ether_header
) +
298 sizeof(struct ip6_hdr
));
299 nd_na
->nd_na_type
= ND_NEIGHBOR_ADVERT
;
300 nd_na
->nd_na_code
= 0;
301 nd_na
->nd_na_flags_reserved
= ND_NA_FLAG_OVERRIDE
;
302 nd_na
->nd_na_target
= addr
->sin6_addr
;
304 /* Option: Target link-layer address */
305 nd_oh
= (struct nd_opt_hdr
*)(buffer
+
306 sizeof(struct ether_header
) +
307 sizeof(struct ip6_hdr
) +
308 sizeof(struct nd_neighbor_advert
));
309 nd_oh
->nd_opt_type
= ND_OPT_TARGET_LINKADDR
;
310 nd_oh
->nd_opt_len
= 1; /* multiple of 8 octets */
312 ea
= (struct ether_addr
*)(buffer
+
313 sizeof(struct ether_header
) +
314 sizeof(struct ip6_hdr
) +
315 sizeof(struct nd_neighbor_advert
) +
316 sizeof(struct nd_opt_hdr
));
317 memcpy(ea
, hwaddr
, ETH_ALEN
);
319 nd_na
->nd_na_cksum
= ip6_checksum((uint16_t *)nd_na
,
320 ntohs(ip6
->ip6_plen
),
323 *ether_dhost
= (struct ether_addr
*)eh
->ether_dhost
;
328 int ctdb_sys_send_arp(const ctdb_sock_addr
*addr
, const char *iface
)
331 struct sockaddr_ll sall
= {0};
332 struct ifreq if_hwaddr
= {
337 uint8_t buffer
[MAX(ARP_BUFFER_SIZE
, IP6_NA_BUFFER_SIZE
)];
343 struct ether_addr
*hwaddr
= NULL
;
344 struct ether_addr
*ether_dhost
= NULL
;
348 s
= socket(AF_PACKET
, SOCK_RAW
, 0);
351 DBG_ERR("Failed to open raw socket\n");
354 DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s
);
357 strlcpy(ifr
.ifr_name
, iface
, sizeof(ifr
.ifr_name
));
358 if (ioctl(s
, SIOCGIFINDEX
, &ifr
) < 0) {
360 DBG_ERR("Interface '%s' not found\n", iface
);
364 /* Get MAC address */
365 strlcpy(if_hwaddr
.ifr_name
, iface
, sizeof(if_hwaddr
.ifr_name
));
366 ret
= ioctl(s
, SIOCGIFHWADDR
, &if_hwaddr
);
369 DBG_ERR("ioctl failed\n");
372 if (ARPHRD_LOOPBACK
== if_hwaddr
.ifr_hwaddr
.sa_family
) {
374 D_DEBUG("Ignoring loopback arp request\n");
377 if (if_hwaddr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
379 DBG_ERR("Not an ethernet address family (0x%x)\n",
380 if_hwaddr
.ifr_hwaddr
.sa_family
);
384 /* Set up most of destination address structure */
385 sall
.sll_family
= AF_PACKET
;
386 sall
.sll_halen
= sizeof(struct ether_addr
);
387 sall
.sll_protocol
= htons(ETH_P_ALL
);
388 sall
.sll_ifindex
= ifr
.ifr_ifindex
;
391 hwaddr
= (struct ether_addr
*)if_hwaddr
.ifr_hwaddr
.sa_data
;
393 switch (addr
->ip
.sin_family
) {
395 /* Send gratuitous ARP */
396 ret
= arp_build(buffer
,
404 DBG_ERR("Failed to build ARP request\n");
408 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
414 (struct sockaddr
*)&sall
,
418 DBG_ERR("Failed sendto\n");
422 /* Send unsolicited ARP reply */
423 ret
= arp_build(buffer
,
431 DBG_ERR("Failed to build ARP reply\n");
435 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
441 (struct sockaddr
*)&sall
,
445 DBG_ERR("Failed sendto\n");
453 ret
= ip6_na_build(buffer
,
460 DBG_ERR("Failed to build IPv6 neighbor advertisment\n");
464 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
470 (struct sockaddr
*)&sall
,
474 DBG_ERR("Failed sendto\n");
483 DBG_ERR("Not an ipv4/ipv6 address (family is %u)\n",
484 addr
->ip
.sin_family
);
495 #else /* HAVE_PACKETSOCKET */
497 int ctdb_sys_send_arp(const ctdb_sock_addr
*addr
, const char *iface
)
499 /* Not implemented */
503 #endif /* HAVE_PACKETSOCKET */
506 #define IP4_TCP_BUFFER_SIZE sizeof(struct ip) + \
507 sizeof(struct tcphdr)
509 #define IP6_TCP_BUFFER_SIZE sizeof(struct ip6_hdr) + \
510 sizeof(struct tcphdr)
512 static int tcp4_build(uint8_t *buf
,
514 const struct sockaddr_in
*src
,
515 const struct sockaddr_in
*dst
,
521 size_t l
= IP4_TCP_BUFFER_SIZE
;
527 if (l
!= sizeof(*ip4pkt
)) {
535 ip4pkt
= (void *)buf
;
536 memset(ip4pkt
, 0, l
);
539 ip4pkt
->ip
.ip_hl
= sizeof(ip4pkt
->ip
)/sizeof(uint32_t);
540 ip4pkt
->ip
.ip_len
= htons(sizeof(ip4pkt
));
541 ip4pkt
->ip
.ip_ttl
= 255;
542 ip4pkt
->ip
.ip_p
= IPPROTO_TCP
;
543 ip4pkt
->ip
.ip_src
.s_addr
= src
->sin_addr
.s_addr
;
544 ip4pkt
->ip
.ip_dst
.s_addr
= dst
->sin_addr
.s_addr
;
545 ip4pkt
->ip
.ip_sum
= 0;
547 ip4pkt
->tcp
.th_sport
= src
->sin_port
;
548 ip4pkt
->tcp
.th_dport
= dst
->sin_port
;
549 ip4pkt
->tcp
.th_seq
= seq
;
550 ip4pkt
->tcp
.th_ack
= ack
;
551 ip4pkt
->tcp
.th_flags
= 0;
552 ip4pkt
->tcp
.th_flags
|= TH_ACK
;
554 ip4pkt
->tcp
.th_flags
|= TH_RST
;
556 ip4pkt
->tcp
.th_off
= sizeof(ip4pkt
->tcp
)/sizeof(uint32_t);
557 /* this makes it easier to spot in a sniffer */
558 ip4pkt
->tcp
.th_win
= htons(1234);
559 ip4pkt
->tcp
.th_sum
= ip_checksum((uint16_t *)&ip4pkt
->tcp
,
567 static int tcp6_build(uint8_t *buf
,
569 const struct sockaddr_in6
*src
,
570 const struct sockaddr_in6
*dst
,
576 size_t l
= IP6_TCP_BUFFER_SIZE
;
582 if (l
!= sizeof(*ip6pkt
)) {
590 ip6pkt
= (void *)buf
;
591 memset(ip6pkt
, 0, l
);
593 ip6pkt
->ip6
.ip6_vfc
= 6 << 4;
594 ip6pkt
->ip6
.ip6_plen
= htons(sizeof(struct tcphdr
));
595 ip6pkt
->ip6
.ip6_nxt
= IPPROTO_TCP
;
596 ip6pkt
->ip6
.ip6_hlim
= 64;
597 ip6pkt
->ip6
.ip6_src
= src
->sin6_addr
;
598 ip6pkt
->ip6
.ip6_dst
= dst
->sin6_addr
;
600 ip6pkt
->tcp
.th_sport
= src
->sin6_port
;
601 ip6pkt
->tcp
.th_dport
= dst
->sin6_port
;
602 ip6pkt
->tcp
.th_seq
= seq
;
603 ip6pkt
->tcp
.th_ack
= ack
;
604 ip6pkt
->tcp
.th_flags
= 0;
605 ip6pkt
->tcp
.th_flags
|= TH_ACK
;
607 ip6pkt
->tcp
.th_flags
|= TH_RST
;
609 ip6pkt
->tcp
.th_off
= sizeof(ip6pkt
->tcp
)/sizeof(uint32_t);
610 /* this makes it easier to spot in a sniffer */
611 ip6pkt
->tcp
.th_win
= htons(1234);
612 ip6pkt
->tcp
.th_sum
= ip6_checksum((uint16_t *)&ip6pkt
->tcp
,
621 * Send tcp segment from the specified IP/port to the specified
622 * destination IP/port.
624 * This is used to trigger the receiving host into sending its own ACK,
625 * which should trigger early detection of TCP reset by the client
628 * This can also be used to send RST segments (if rst is true) and also
629 * if correct seq and ack numbers are provided.
631 int ctdb_sys_send_tcp(const ctdb_sock_addr
*dest
,
632 const ctdb_sock_addr
*src
,
637 uint8_t buf
[MAX(IP4_TCP_BUFFER_SIZE
, IP6_TCP_BUFFER_SIZE
)];
642 struct sockaddr_in6 tmpdest
= { 0 };
645 switch (src
->ip
.sin_family
) {
647 ret
= tcp4_build(buf
,
656 DBG_ERR("Failed to build TCP packet (%d)\n", ret
);
660 /* open a raw socket to send this segment from */
661 s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
663 DBG_ERR("Failed to open raw socket (%s)\n",
668 ret
= setsockopt(s
, IPPROTO_IP
, IP_HDRINCL
, &one
, sizeof(one
));
670 DBG_ERR("Failed to setup IP headers (%s)\n",
680 (const struct sockaddr
*)&dest
->ip
,
685 D_ERR("Failed sendto (%s)\n", strerror(saved_errno
));
691 ret
= tcp6_build(buf
,
700 DBG_ERR("Failed to build TCP packet (%d)\n", ret
);
704 s
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_RAW
);
706 DBG_ERR("Failed to open sending socket\n");
711 * sendto() on an IPv6 raw socket requires the port to
712 * be either 0 or a protocol value
715 tmpdest
.sin6_port
= 0;
721 (const struct sockaddr
*)&tmpdest
,
727 D_ERR("Failed sendto (%s)\n", strerror(saved_errno
));
733 DBG_ERR("Not an ipv4/v6 address\n");
743 * If AF_PACKET is available then use a raw socket otherwise use pcap.
744 * wscript has checked to make sure that pcap is available if needed.
747 static int tcp4_extract(const uint8_t *ip_pkt
,
749 struct sockaddr_in
*src
,
750 struct sockaddr_in
*dst
,
757 const struct tcphdr
*tcp
;
759 if (pktlen
< sizeof(struct ip
)) {
763 ip
= (const struct ip
*)ip_pkt
;
769 /* Don't look at fragments */
770 if ((ntohs(ip
->ip_off
)&0x1fff) != 0) {
774 if (ip
->ip_p
!= IPPROTO_TCP
) {
778 /* Ensure there is enough of the packet to gather required fields */
780 (ip
->ip_hl
* sizeof(uint32_t)) + offsetof(struct tcphdr
, th_sum
)) {
784 tcp
= (const struct tcphdr
*)(ip_pkt
+ (ip
->ip_hl
* sizeof(uint32_t)));
786 src
->sin_family
= AF_INET
;
787 src
->sin_addr
.s_addr
= ip
->ip_src
.s_addr
;
788 src
->sin_port
= tcp
->th_sport
;
790 dst
->sin_family
= AF_INET
;
791 dst
->sin_addr
.s_addr
= ip
->ip_dst
.s_addr
;
792 dst
->sin_port
= tcp
->th_dport
;
794 *ack_seq
= tcp
->th_ack
;
796 if (window
!= NULL
) {
797 *window
= tcp
->th_win
;
800 *rst
= tcp
->th_flags
& TH_RST
;
806 static int tcp6_extract(const uint8_t *ip_pkt
,
808 struct sockaddr_in6
*src
,
809 struct sockaddr_in6
*dst
,
815 const struct ip6_hdr
*ip6
;
816 const struct tcphdr
*tcp
;
818 /* Ensure there is enough of the packet to gather required fields */
819 if (pktlen
< sizeof(struct ip6_hdr
) + offsetof(struct tcphdr
, th_sum
)) {
823 ip6
= (const struct ip6_hdr
*)ip_pkt
;
826 if ((ip6
->ip6_vfc
>> 4) != 6){
831 if (ip6
->ip6_nxt
!= IPPROTO_TCP
) {
835 tcp
= (const struct tcphdr
*)(ip_pkt
+ sizeof(struct ip6_hdr
));
837 src
->sin6_family
= AF_INET6
;
838 src
->sin6_port
= tcp
->th_sport
;
839 src
->sin6_addr
= ip6
->ip6_src
;
841 dst
->sin6_family
= AF_INET6
;
842 dst
->sin6_port
= tcp
->th_dport
;
843 dst
->sin6_addr
= ip6
->ip6_dst
;
845 *ack_seq
= tcp
->th_ack
;
847 if (window
!= NULL
) {
848 *window
= tcp
->th_win
;
851 *rst
= tcp
->th_flags
& TH_RST
;
858 #ifdef HAVE_AF_PACKET
861 * This function is used to open a raw socket to capture from
863 int ctdb_sys_open_capture_socket(const char *iface
, void **private_data
)
867 /* Open a socket to capture all traffic */
868 s
= socket(AF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
870 DBG_ERR("Failed to open raw socket\n");
874 DBG_DEBUG("Created RAW SOCKET FD:%d for tcp tickle\n", s
);
876 ret
= set_blocking(s
, false);
878 DBG_ERR("Failed to set socket non-blocking (%s)\n",
884 set_close_on_exec(s
);
890 * This function is used to do any additional cleanup required when closing
892 * Note that the socket itself is closed automatically in the caller.
894 int ctdb_sys_close_capture_socket(void *private_data
)
901 * called when the raw socket becomes readable
903 int ctdb_sys_read_tcp_packet(int s
, void *private_data
,
912 uint8_t pkt
[100]; /* Large enough for simple ACK/RST packets */
913 struct ether_header
*eth
;
916 nread
= recv(s
, pkt
, sizeof(pkt
), MSG_TRUNC
);
917 if (nread
< sizeof(*eth
)) {
925 eth
= (struct ether_header
*)pkt
;
927 /* we want either IPv4 or IPv6 */
928 if (ntohs(eth
->ether_type
) == ETHERTYPE_IP
) {
929 ret
= tcp4_extract(pkt
+ sizeof(struct ether_header
),
930 (size_t)nread
- sizeof(struct ether_header
),
939 } else if (ntohs(eth
->ether_type
) == ETHERTYPE_IP6
) {
940 ret
= tcp6_extract(pkt
+ sizeof(struct ether_header
),
941 (size_t)nread
- sizeof(struct ether_header
),
954 #else /* HAVE_AF_PACKET */
958 int ctdb_sys_open_capture_socket(const char *iface
, void **private_data
)
962 pt
=pcap_open_live(iface
, 100, 0, 0, NULL
);
964 DBG_ERR("Failed to open capture device %s\n", iface
);
967 *((pcap_t
**)private_data
) = pt
;
969 return pcap_fileno(pt
);
972 int ctdb_sys_close_capture_socket(void *private_data
)
974 pcap_t
*pt
= (pcap_t
*)private_data
;
979 int ctdb_sys_read_tcp_packet(int s
,
989 struct ether_header
*eth
;
990 struct pcap_pkthdr pkthdr
;
991 const u_char
*buffer
;
992 pcap_t
*pt
= (pcap_t
*)private_data
;
994 buffer
=pcap_next(pt
, &pkthdr
);
1003 eth
= (struct ether_header
*)buffer
;
1005 /* we want either IPv4 or IPv6 */
1006 if (eth
->ether_type
== htons(ETHERTYPE_IP
)) {
1007 ret
= tcp4_extract(buffer
+ sizeof(struct ether_header
),
1008 (size_t)(pkthdr
.caplen
-
1009 sizeof(struct ether_header
)),
1018 } else if (eth
->ether_type
== htons(ETHERTYPE_IP6
)) {
1019 ret
= tcp6_extract(buffer
+ sizeof(struct ether_header
),
1020 (size_t)(pkthdr
.caplen
-
1021 sizeof(struct ether_header
)),
1034 #endif /* HAVE_AF_PACKET */