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
= {{{0}}};
333 uint8_t buffer
[MAX(ARP_BUFFER_SIZE
, IP6_NA_BUFFER_SIZE
)];
334 struct ifreq ifr
= {{{0}}};
335 struct ether_addr
*hwaddr
= NULL
;
336 struct ether_addr
*ether_dhost
= NULL
;
340 s
= socket(AF_PACKET
, SOCK_RAW
, 0);
343 DBG_ERR("Failed to open raw socket\n");
346 DBG_DEBUG("Created SOCKET FD:%d for sending arp\n", s
);
349 strlcpy(ifr
.ifr_name
, iface
, sizeof(ifr
.ifr_name
));
350 if (ioctl(s
, SIOCGIFINDEX
, &ifr
) < 0) {
352 DBG_ERR("Interface '%s' not found\n", iface
);
356 /* Get MAC address */
357 strlcpy(if_hwaddr
.ifr_name
, iface
, sizeof(if_hwaddr
.ifr_name
));
358 ret
= ioctl(s
, SIOCGIFHWADDR
, &if_hwaddr
);
361 DBG_ERR("ioctl failed\n");
364 if (ARPHRD_LOOPBACK
== if_hwaddr
.ifr_hwaddr
.sa_family
) {
366 D_DEBUG("Ignoring loopback arp request\n");
369 if (if_hwaddr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
371 DBG_ERR("Not an ethernet address family (0x%x)\n",
372 if_hwaddr
.ifr_hwaddr
.sa_family
);
376 /* Set up most of destination address structure */
377 sall
.sll_family
= AF_PACKET
;
378 sall
.sll_halen
= sizeof(struct ether_addr
);
379 sall
.sll_protocol
= htons(ETH_P_ALL
);
380 sall
.sll_ifindex
= ifr
.ifr_ifindex
;
383 hwaddr
= (struct ether_addr
*)if_hwaddr
.ifr_hwaddr
.sa_data
;
385 switch (addr
->ip
.sin_family
) {
387 /* Send gratuitous ARP */
388 ret
= arp_build(buffer
,
396 DBG_ERR("Failed to build ARP request\n");
400 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
406 (struct sockaddr
*)&sall
,
410 DBG_ERR("Failed sendto\n");
414 /* Send unsolicited ARP reply */
415 ret
= arp_build(buffer
,
423 DBG_ERR("Failed to build ARP reply\n");
427 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
433 (struct sockaddr
*)&sall
,
437 DBG_ERR("Failed sendto\n");
445 ret
= ip6_na_build(buffer
,
452 DBG_ERR("Failed to build IPv6 neighbor advertisment\n");
456 memcpy(&sall
.sll_addr
[0], ether_dhost
, sall
.sll_halen
);
462 (struct sockaddr
*)&sall
,
466 DBG_ERR("Failed sendto\n");
475 DBG_ERR("Not an ipv4/ipv6 address (family is %u)\n",
476 addr
->ip
.sin_family
);
487 #else /* HAVE_PACKETSOCKET */
489 int ctdb_sys_send_arp(const ctdb_sock_addr
*addr
, const char *iface
)
491 /* Not implemented */
495 #endif /* HAVE_PACKETSOCKET */
498 #define IP4_TCP_BUFFER_SIZE sizeof(struct ip) + \
499 sizeof(struct tcphdr)
501 #define IP6_TCP_BUFFER_SIZE sizeof(struct ip6_hdr) + \
502 sizeof(struct tcphdr)
504 static int tcp4_build(uint8_t *buf
,
506 const struct sockaddr_in
*src
,
507 const struct sockaddr_in
*dst
,
513 size_t l
= IP4_TCP_BUFFER_SIZE
;
519 if (l
!= sizeof(*ip4pkt
)) {
527 ip4pkt
= (void *)buf
;
528 memset(ip4pkt
, 0, l
);
531 ip4pkt
->ip
.ip_hl
= sizeof(ip4pkt
->ip
)/sizeof(uint32_t);
532 ip4pkt
->ip
.ip_len
= htons(sizeof(ip4pkt
));
533 ip4pkt
->ip
.ip_ttl
= 255;
534 ip4pkt
->ip
.ip_p
= IPPROTO_TCP
;
535 ip4pkt
->ip
.ip_src
.s_addr
= src
->sin_addr
.s_addr
;
536 ip4pkt
->ip
.ip_dst
.s_addr
= dst
->sin_addr
.s_addr
;
537 ip4pkt
->ip
.ip_sum
= 0;
539 ip4pkt
->tcp
.th_sport
= src
->sin_port
;
540 ip4pkt
->tcp
.th_dport
= dst
->sin_port
;
541 ip4pkt
->tcp
.th_seq
= seq
;
542 ip4pkt
->tcp
.th_ack
= ack
;
543 ip4pkt
->tcp
.th_flags
= 0;
544 ip4pkt
->tcp
.th_flags
|= TH_ACK
;
546 ip4pkt
->tcp
.th_flags
|= TH_RST
;
548 ip4pkt
->tcp
.th_off
= sizeof(ip4pkt
->tcp
)/sizeof(uint32_t);
549 /* this makes it easier to spot in a sniffer */
550 ip4pkt
->tcp
.th_win
= htons(1234);
551 ip4pkt
->tcp
.th_sum
= ip_checksum((uint16_t *)&ip4pkt
->tcp
,
559 static int tcp6_build(uint8_t *buf
,
561 const struct sockaddr_in6
*src
,
562 const struct sockaddr_in6
*dst
,
568 size_t l
= IP6_TCP_BUFFER_SIZE
;
574 if (l
!= sizeof(*ip6pkt
)) {
582 ip6pkt
= (void *)buf
;
583 memset(ip6pkt
, 0, l
);
585 ip6pkt
->ip6
.ip6_vfc
= 6 << 4;
586 ip6pkt
->ip6
.ip6_plen
= htons(sizeof(struct tcphdr
));
587 ip6pkt
->ip6
.ip6_nxt
= IPPROTO_TCP
;
588 ip6pkt
->ip6
.ip6_hlim
= 64;
589 ip6pkt
->ip6
.ip6_src
= src
->sin6_addr
;
590 ip6pkt
->ip6
.ip6_dst
= dst
->sin6_addr
;
592 ip6pkt
->tcp
.th_sport
= src
->sin6_port
;
593 ip6pkt
->tcp
.th_dport
= dst
->sin6_port
;
594 ip6pkt
->tcp
.th_seq
= seq
;
595 ip6pkt
->tcp
.th_ack
= ack
;
596 ip6pkt
->tcp
.th_flags
= 0;
597 ip6pkt
->tcp
.th_flags
|= TH_ACK
;
599 ip6pkt
->tcp
.th_flags
|= TH_RST
;
601 ip6pkt
->tcp
.th_off
= sizeof(ip6pkt
->tcp
)/sizeof(uint32_t);
602 /* this makes it easier to spot in a sniffer */
603 ip6pkt
->tcp
.th_win
= htons(1234);
604 ip6pkt
->tcp
.th_sum
= ip6_checksum((uint16_t *)&ip6pkt
->tcp
,
613 * Send tcp segment from the specified IP/port to the specified
614 * destination IP/port.
616 * This is used to trigger the receiving host into sending its own ACK,
617 * which should trigger early detection of TCP reset by the client
620 * This can also be used to send RST segments (if rst is true) and also
621 * if correct seq and ack numbers are provided.
623 int ctdb_sys_send_tcp(const ctdb_sock_addr
*dest
,
624 const ctdb_sock_addr
*src
,
629 uint8_t buf
[MAX(IP4_TCP_BUFFER_SIZE
, IP6_TCP_BUFFER_SIZE
)];
634 struct sockaddr_in6 tmpdest
= { 0 };
637 switch (src
->ip
.sin_family
) {
639 ret
= tcp4_build(buf
,
648 DBG_ERR("Failed to build TCP packet (%d)\n", ret
);
652 /* open a raw socket to send this segment from */
653 s
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
);
655 DBG_ERR("Failed to open raw socket (%s)\n",
660 ret
= setsockopt(s
, IPPROTO_IP
, IP_HDRINCL
, &one
, sizeof(one
));
662 DBG_ERR("Failed to setup IP headers (%s)\n",
672 (const struct sockaddr
*)&dest
->ip
,
677 D_ERR("Failed sendto (%s)\n", strerror(saved_errno
));
683 ret
= tcp6_build(buf
,
692 DBG_ERR("Failed to build TCP packet (%d)\n", ret
);
696 s
= socket(AF_INET6
, SOCK_RAW
, IPPROTO_RAW
);
698 DBG_ERR("Failed to open sending socket\n");
703 * sendto() on an IPv6 raw socket requires the port to
704 * be either 0 or a protocol value
707 tmpdest
.sin6_port
= 0;
713 (const struct sockaddr
*)&tmpdest
,
719 D_ERR("Failed sendto (%s)\n", strerror(saved_errno
));
725 DBG_ERR("Not an ipv4/v6 address\n");
735 * If AF_PACKET is available then use a raw socket otherwise use pcap.
736 * wscript has checked to make sure that pcap is available if needed.
739 static int tcp4_extract(const uint8_t *ip_pkt
,
741 struct sockaddr_in
*src
,
742 struct sockaddr_in
*dst
,
749 const struct tcphdr
*tcp
;
751 if (pktlen
< sizeof(struct ip
)) {
755 ip
= (const struct ip
*)ip_pkt
;
761 /* Don't look at fragments */
762 if ((ntohs(ip
->ip_off
)&0x1fff) != 0) {
766 if (ip
->ip_p
!= IPPROTO_TCP
) {
770 /* Ensure there is enough of the packet to gather required fields */
772 (ip
->ip_hl
* sizeof(uint32_t)) + offsetof(struct tcphdr
, th_sum
)) {
776 tcp
= (const struct tcphdr
*)(ip_pkt
+ (ip
->ip_hl
* sizeof(uint32_t)));
778 src
->sin_family
= AF_INET
;
779 src
->sin_addr
.s_addr
= ip
->ip_src
.s_addr
;
780 src
->sin_port
= tcp
->th_sport
;
782 dst
->sin_family
= AF_INET
;
783 dst
->sin_addr
.s_addr
= ip
->ip_dst
.s_addr
;
784 dst
->sin_port
= tcp
->th_dport
;
786 *ack_seq
= tcp
->th_ack
;
788 if (window
!= NULL
) {
789 *window
= tcp
->th_win
;
792 *rst
= tcp
->th_flags
& TH_RST
;
798 static int tcp6_extract(const uint8_t *ip_pkt
,
800 struct sockaddr_in6
*src
,
801 struct sockaddr_in6
*dst
,
807 const struct ip6_hdr
*ip6
;
808 const struct tcphdr
*tcp
;
810 /* Ensure there is enough of the packet to gather required fields */
811 if (pktlen
< sizeof(struct ip6_hdr
) + offsetof(struct tcphdr
, th_sum
)) {
815 ip6
= (const struct ip6_hdr
*)ip_pkt
;
818 if ((ip6
->ip6_vfc
>> 4) != 6){
823 if (ip6
->ip6_nxt
!= IPPROTO_TCP
) {
827 tcp
= (const struct tcphdr
*)(ip_pkt
+ sizeof(struct ip6_hdr
));
829 src
->sin6_family
= AF_INET6
;
830 src
->sin6_port
= tcp
->th_sport
;
831 src
->sin6_addr
= ip6
->ip6_src
;
833 dst
->sin6_family
= AF_INET6
;
834 dst
->sin6_port
= tcp
->th_dport
;
835 dst
->sin6_addr
= ip6
->ip6_dst
;
837 *ack_seq
= tcp
->th_ack
;
839 if (window
!= NULL
) {
840 *window
= tcp
->th_win
;
843 *rst
= tcp
->th_flags
& TH_RST
;
850 #ifdef HAVE_AF_PACKET
853 * This function is used to open a raw socket to capture from
855 int ctdb_sys_open_capture_socket(const char *iface
, void **private_data
)
859 /* Open a socket to capture all traffic */
860 s
= socket(AF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
862 DBG_ERR("Failed to open raw socket\n");
866 DBG_DEBUG("Created RAW SOCKET FD:%d for tcp tickle\n", s
);
868 ret
= set_blocking(s
, false);
870 DBG_ERR("Failed to set socket non-blocking (%s)\n",
876 set_close_on_exec(s
);
882 * This function is used to do any additional cleanup required when closing
884 * Note that the socket itself is closed automatically in the caller.
886 int ctdb_sys_close_capture_socket(void *private_data
)
893 * called when the raw socket becomes readable
895 int ctdb_sys_read_tcp_packet(int s
, void *private_data
,
904 uint8_t pkt
[100]; /* Large enough for simple ACK/RST packets */
905 struct ether_header
*eth
;
908 nread
= recv(s
, pkt
, sizeof(pkt
), MSG_TRUNC
);
909 if (nread
< sizeof(*eth
)) {
917 eth
= (struct ether_header
*)pkt
;
919 /* we want either IPv4 or IPv6 */
920 if (ntohs(eth
->ether_type
) == ETHERTYPE_IP
) {
921 ret
= tcp4_extract(pkt
+ sizeof(struct ether_header
),
922 (size_t)nread
- sizeof(struct ether_header
),
931 } else if (ntohs(eth
->ether_type
) == ETHERTYPE_IP6
) {
932 ret
= tcp6_extract(pkt
+ sizeof(struct ether_header
),
933 (size_t)nread
- sizeof(struct ether_header
),
946 #else /* HAVE_AF_PACKET */
950 int ctdb_sys_open_capture_socket(const char *iface
, void **private_data
)
954 pt
=pcap_open_live(iface
, 100, 0, 0, NULL
);
956 DBG_ERR("Failed to open capture device %s\n", iface
);
959 *((pcap_t
**)private_data
) = pt
;
961 return pcap_fileno(pt
);
964 int ctdb_sys_close_capture_socket(void *private_data
)
966 pcap_t
*pt
= (pcap_t
*)private_data
;
971 int ctdb_sys_read_tcp_packet(int s
,
981 struct ether_header
*eth
;
982 struct pcap_pkthdr pkthdr
;
983 const u_char
*buffer
;
984 pcap_t
*pt
= (pcap_t
*)private_data
;
986 buffer
=pcap_next(pt
, &pkthdr
);
995 eth
= (struct ether_header
*)buffer
;
997 /* we want either IPv4 or IPv6 */
998 if (eth
->ether_type
== htons(ETHERTYPE_IP
)) {
999 ret
= tcp4_extract(buffer
+ sizeof(struct ether_header
),
1000 (size_t)(pkthdr
.caplen
-
1001 sizeof(struct ether_header
)),
1010 } else if (eth
->ether_type
== htons(ETHERTYPE_IP6
)) {
1011 ret
= tcp6_extract(buffer
+ sizeof(struct ether_header
),
1012 (size_t)(pkthdr
.caplen
-
1013 sizeof(struct ether_header
)),
1026 #endif /* HAVE_AF_PACKET */