mirror of
https://github.com/Cacti/spine.git
synced 2026-10-23 03:27:10 +09:00
Open and own the required ICMP sockets before permanently dropping setuid root, then parse input without elevated identity. Close-on-exec socket ownership, shared IPv4/IPv6 dispatch and fault-injected identity/capability calls are covered. The owned fixture tests check deny/allow behavior without contacting external devices. Step 2/14 of the complete C17/native-correctness series. Base: the preceding series branch; merge/review in order so this PR shows only its own step. Earlier validation, before this review follow-up, in isolated copied snapshots on Linux arm64: - Clean GCC build and make check: 13 passed, 1 existing prerequisite skips, 0 failures. - ASan/UBSan: 12 passed, 2 existing privilege/allocator-interposition prerequisite skips, 0 failures; no sanitizer findings. - Production source/profile integrity verification against disposable MariaDB and loopback SNMP fixtures passed. - Release archive extracted into a separate source tree and built/tested out of tree; fuzz checks passed. Earlier local profiles retain source hashes for the copied validation tree; GitHub checks validate the published commit. No production database/device, host installation or live privilege change is part of validation. Existing prerequisite skips were retained; no test or finding was suppressed to obtain a pass. Series navigation: [Series index](https://github.com/Cacti/spine/pull/638); [previous step](https://github.com/Cacti/spine/pull/638). [Next step](https://github.com/Cacti/spine/pull/640). Review follow-up (2026-10-09): Restacked on the corrected preceding branches. The SNMP status fix is introduced in #638, the reindex/completion fixes in #640, and focused regression coverage in #650. Restacked tip validation: isolated Linux arm64 build and make check passed (18 passed, 1 setuid prerequisite skip, no failures). GitHub checks validate the updated published commits; earlier profile/archive/sanitizer evidence above belongs to the previous revisions. --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
178 lines
6.6 KiB
C
178 lines
6.6 KiB
C
/*
|
|
ex: set tabstop=4 shiftwidth=4 autoindent:
|
|
+-------------------------------------------------------------------------+
|
|
| Copyright (C) 2004-2026 The Cacti Group |
|
|
| |
|
|
| This program is free software; you can redistribute it and/or |
|
|
| modify it under the terms of the GNU Lesser General Public |
|
|
| License as published by the Free Software Foundation; either |
|
|
| version 2.1 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 Lesser General Public License for more details. |
|
|
| |
|
|
| You should have received a copy of the GNU Lesser General Public |
|
|
| License along with this library; if not, write to the Free Software |
|
|
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
|
|
| 02110-1301, USA |
|
|
| |
|
|
+-------------------------------------------------------------------------+
|
|
| spine: a backend data gatherer for cacti |
|
|
+-------------------------------------------------------------------------+
|
|
| This poller would not have been possible without: |
|
|
| - Larry Adams (current development and enhancements) |
|
|
| - Rivo Nurges (rrd support, mysql poller cache, misc functions) |
|
|
| - RTG (core poller code, pthreads, snmp, autoconf examples) |
|
|
| - Brady Alleman/Doug Warner (threading ideas, implementation details) |
|
|
+-------------------------------------------------------------------------+
|
|
| - Cacti - http://www.cacti.net/ |
|
|
+-------------------------------------------------------------------------+
|
|
*/
|
|
|
|
#ifndef SPINE_PING_H
|
|
#define SPINE_PING_H
|
|
#ifndef ICMP_ECHOREPLY
|
|
#define ICMP_ECHOREPLY 0 /* Echo Reply */
|
|
#endif
|
|
|
|
/* IPv6 pinging needs a raw ICMPv6 socket and the RFC 3542 socket options.
|
|
* Platforms without them keep the previous behavior of reporting IPv6
|
|
* devices as pingable by SNMP only. */
|
|
#if !defined(__CYGWIN__) && defined(AF_INET6) && defined(IPPROTO_ICMPV6) && \
|
|
defined(ICMP6_FILTER) && defined(ICMP6_ECHO_REQUEST) && defined(ICMP6_ECHO_REPLY)
|
|
#define SPINE_HAVE_ICMPV6 1
|
|
#endif
|
|
|
|
#ifndef MSG_WAITALL
|
|
#define MSG_WAITALL 0x100
|
|
#endif
|
|
|
|
#ifdef __CYGWIN__
|
|
struct icmp_ra_addr
|
|
{
|
|
u_int32_t ira_addr;
|
|
u_int32_t ira_preference;
|
|
};
|
|
struct iphdr {
|
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
unsigned int ihl:4;
|
|
unsigned int version:4;
|
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
|
unsigned int version:4;
|
|
unsigned int ihl:4;
|
|
#else
|
|
# error "Please fix <bits/endian.h>"
|
|
#endif
|
|
u_int8_t tos;
|
|
u_int16_t tot_len;
|
|
u_int16_t id;
|
|
u_int16_t frag_off;
|
|
u_int8_t ttl;
|
|
u_int8_t protocol;
|
|
u_int16_t check;
|
|
u_int32_t saddr;
|
|
u_int32_t daddr;
|
|
/*The options start here. */
|
|
};
|
|
struct icmp
|
|
{
|
|
u_int8_t icmp_type; /* type of message, see below */
|
|
u_int8_t icmp_code; /* type sub code */
|
|
u_int16_t icmp_cksum; /* ones complement checksum of struct */
|
|
union
|
|
{
|
|
u_char ih_pptr; /* ICMP_PARAMPROB */
|
|
struct in_addr ih_gwaddr; /* gateway address */
|
|
struct ih_idseq /* echo datagram */
|
|
{
|
|
u_int16_t icd_id;
|
|
u_int16_t icd_seq;
|
|
} ih_idseq;
|
|
u_int32_t ih_void;
|
|
|
|
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
|
|
struct ih_pmtu
|
|
{
|
|
u_int16_t ipm_void;
|
|
u_int16_t ipm_nextmtu;
|
|
} ih_pmtu;
|
|
|
|
struct ih_rtradv
|
|
{
|
|
u_int8_t irt_num_addrs;
|
|
u_int8_t irt_wpa;
|
|
u_int16_t irt_lifetime;
|
|
} ih_rtradv;
|
|
} icmp_hun;
|
|
#define icmp_pptr icmp_hun.ih_pptr
|
|
#define icmp_gwaddr icmp_hun.ih_gwaddr
|
|
#define icmp_id icmp_hun.ih_idseq.icd_id
|
|
#define icmp_seq icmp_hun.ih_idseq.icd_seq
|
|
#define icmp_void icmp_hun.ih_void
|
|
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
|
|
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
|
|
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
|
|
#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
|
|
#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
u_int32_t its_otime;
|
|
u_int32_t its_rtime;
|
|
u_int32_t its_ttime;
|
|
} id_ts;
|
|
struct
|
|
{
|
|
struct ip idi_ip;
|
|
/* options and then 64 bits of data */
|
|
} id_ip;
|
|
struct icmp_ra_addr id_radv;
|
|
u_int32_t id_mask;
|
|
u_int8_t id_data[1];
|
|
} icmp_dun;
|
|
#define icmp_otime icmp_dun.id_ts.its_otime
|
|
#define icmp_rtime icmp_dun.id_ts.its_rtime
|
|
#define icmp_ttime icmp_dun.id_ts.its_ttime
|
|
#define icmp_ip icmp_dun.id_ip.idi_ip
|
|
#define icmp_radv icmp_dun.id_radv
|
|
#define icmp_mask icmp_dun.id_mask
|
|
#define icmp_data icmp_dun.id_data
|
|
};
|
|
|
|
#endif
|
|
|
|
/* Host availability functions */
|
|
/* Classification of a raw ICMP reply. Declared here so the fuzz target can
|
|
* link against the shipped implementation. */
|
|
typedef enum {
|
|
SPINE_ICMP_REPLY_TOO_SHORT = 0, /* shorter than an IP header */
|
|
SPINE_ICMP_REPLY_BAD_HEADER, /* IHL implausible, or no room for the ICMP header */
|
|
SPINE_ICMP_REPLY_NOT_ECHO, /* not an echo reply */
|
|
SPINE_ICMP_REPLY_NOT_OURS, /* echo reply, but not our id/sequence */
|
|
SPINE_ICMP_REPLY_OK
|
|
} spine_icmp_reply_t;
|
|
|
|
extern spine_icmp_reply_t spine_icmp_classify_reply(const unsigned char *reply,
|
|
ssize_t len, uint16_t want_id, uint16_t want_seq, const struct icmp **out_pkt);
|
|
|
|
extern spine_icmp_reply_t spine_icmp_classify_dgram_reply(const unsigned char *reply,
|
|
ssize_t len, uint16_t want_seq, const struct icmp **out_pkt);
|
|
|
|
extern int ping_host(host_t *host, ping_t *ping);
|
|
extern int ping_snmp(host_t *host, ping_t *ping);
|
|
extern int ping_icmp(const host_t *host, ping_t *ping);
|
|
extern int ping_icmp_open_shared(void);
|
|
extern int ping_icmp_shared_available(void);
|
|
extern int ping_udp(const host_t *host, ping_t *ping);
|
|
extern int ping_tcp(const host_t *host, ping_t *ping);
|
|
extern name_t *get_namebyhost(const char *hostname, name_t *name);
|
|
extern void update_host_status(int status, host_t *host, const ping_t *ping, int availability_method);
|
|
extern int init_sockaddr(struct sockaddr_in *name, const char *hostname, int port);
|
|
extern int get_address_type(host_t *host);
|
|
extern unsigned short int get_checksum(void* buf, int len);
|
|
|
|
#endif /* SPINE_PING_H */
|