diff --git a/Makefile.am b/Makefile.am index 2e2ac0b..6561dd0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,15 @@ include $(top_srcdir)/rules.mk ACLOCAL_AMFLAGS = -I m4 -AM_MAKEFLAGS=CONFIG_PREFIX:=$(DESTDIR)$(atlas_measurementdir) CC=$(CC) +AM_MAKEFLAGS=CONFIG_PREFIX:=$(DESTDIR)$(atlas_measurementdir) CC=$(CC) \ + atlas_datadir='$(atlas_datadir)' \ + atlas_libexecdir='$(atlas_libexecdir)' \ + atlas_measurementdir='$(atlas_measurementdir)' \ + atlas_scriptsdir='$(atlas_scriptsdir)' \ + atlas_rundir='$(atlas_rundir)' \ + atlas_spooldir='$(atlas_spooldir)' \ + atlas_sysconfdir='$(atlas_sysconfdir)' \ + tmpdir='$(tmpdir)' SUBDIRS = bin config probe-busybox/libevent-2.1.11-stable probe-busybox . # Add pedantic target for stricter compilation (probe-busybox only) diff --git a/bin/Makefile.am b/bin/Makefile.am index cfb0508..ce1fd7b 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -7,7 +7,6 @@ atlas_scripts_SCRIPTS = \ arch/$(probe_scripts_path)/$(probe_scripts_path)-ATLAS.sh \ arch/$(probe_scripts_path)/$(probe_scripts_path)-common.sh \ arch/$(probe_scripts_path)/$(probe_scripts_path)-reginit.sh \ - arch/linux/linux-functions.sh \ array.lib.sh \ atlas_log.lib.sh \ class.lib.sh \ @@ -20,6 +19,12 @@ atlas_scripts_SCRIPTS = \ reginit.sh \ resolvconf +atlas_scripts_SCRIPTS += arch/linux/linux-functions.sh + +if PROBE_TYPE_FREEBSD +atlas_scripts_SCRIPTS += arch/freebsd/freebsd-functions.sh +endif + CLEANFILES = \ paths.lib.sh \ common.sh \ diff --git a/bin/arch/freebsd/freebsd-functions.sh.in b/bin/arch/freebsd/freebsd-functions.sh.in index 832772a..9b884f7 100644 --- a/bin/arch/freebsd/freebsd-functions.sh.in +++ b/bin/arch/freebsd/freebsd-functions.sh.in @@ -1,29 +1,70 @@ -# FreeBSD specific functions +# FreeBSD specific functions. +# +# The bulk of the helpers are plain wrappers around the measurement applets +# and are not Linux specific; source them and override what differs. +. $ATLAS_SCRIPTS/linux-functions.sh -# Get ethernet address for FreeBSD -get_ether_addr() +# No /proc/buddyinfo on FreeBSD; the software probe does not use it. +buddyinfo() +{ + : +} + +do_buddyinfo() { - # FreeBSD way to get ethernet address - ifconfig | grep -E "^[a-z0-9]+:" | grep -v lo0 | head -1 | awk '{print $1}' | sed 's/://' + : } -# FreeBSD specific process management -findpid_ssh() +epoch() +{ + date "+%s" +} + +# sha256sum(1) is a GNU coreutils name; base FreeBSD ships sha256(1). +hash_ssh_pubkey() +{ + hash=$(sed < "$1" "s/^ssh-rsa *\([^ ]*\).*/\1/" | + tr -d "\n" | sha256 -q) + expr "$hash" : "\(.\{16\}\)" +} + +get_ether_addr() { - pgrep -f "sshd.*$1" + ETHER_ADDR=$(ifconfig | awk "/^[[:space:]]*ether /{print \$2; exit}") + export ETHER_ADDR + ETHER_SCANNED=$(echo "$ETHER_ADDR" | sed -e "s/://g") + export ETHER_SCANNED } +# pidof(1) is Linux; use pgrep(1). kill_perds() { - pkill -f "perd.*$1" + for p in perd eperd eooqd + do + pkill -9 -x "$p" 2>/dev/null + done + return 0 } -kill_ssh() +sos() { - pkill -f "sshd.*$1" + boot=$(sysctl -n kern.boottime | sed -e "s/.*sec = \([0-9]*\).*/\1/") + UPTIME=$(($(date "+%s") - boot)) + INFO="$1" + if [ -n "$INFO" ]; then INFO="$INFO."; fi + evping -e -c 2 "${INFO}U$UPTIME.M$ETHER_SCANNED.sos.atlas.ripe.net" } -kill_telnetd() +set_date_from_currenttime_txt() { - pkill -f "telnetd.*$1" + if [ -f $STATUS_DIR/currenttime.txt ] + then + t=$(cat $STATUS_DIR/currenttime.txt) + echo Setting time to $t + date -f "%Y-%m-%dT%H:%M:%SZ" -u "$t" + D=$(epoch) + echo "RESULT 9004 done $D after setting time from currenttime.txt to $t" >> $DATA_NEW_DIR/simpleping + else + echo no file $STATUS_DIR/currenttime.txt + fi } diff --git a/bin/config.sh.in b/bin/config.sh.in index 03de064..66b2848 100644 --- a/bin/config.sh.in +++ b/bin/config.sh.in @@ -51,7 +51,7 @@ get_sub_arch() # DEVICE_NAME is used as a reference for which OS specific scripts should be invoked under 'bin/arch/'. The software probe has already been migrated to used the new 'generic' scripts, therefore for software probes the device name should be 'generic', otherwise it should be the autotools probe_type assigned during build. SUB_ARCH=`get_sub_arch` -if [ "$SUB_ARCH" != "" ]; then +if [ "$SUB_ARCH" != "" ] && [ "`get_arch`" != 'freebsd' ]; then DEVICE_NAME="generic" else DEVICE_NAME=$PROBE_TYPE diff --git a/probe-busybox/coreutils/dfrm.c b/probe-busybox/coreutils/dfrm.c index f7d0503..e02b50a 100644 --- a/probe-busybox/coreutils/dfrm.c +++ b/probe-busybox/coreutils/dfrm.c @@ -78,10 +78,10 @@ int dfrm_main(int argc, char *argv[]) printf(DBQ(bsize) ": %ld, " DBQ(blocks) ": %ld, " DBQ(bfree) ": %ld, " DBQ(free) ": %ld", (long)sb.f_bsize, (long)sb.f_blocks, (long)sb.f_bfree, - (long)sb.f_bfree*(sb.f_bsize/1024)); + (long)((uint64_t)sb.f_bfree * sb.f_bsize / 1024)); printf(" }\n"); - avail= sb.f_bavail*(sb.f_bsize/1024); + avail= (uint64_t)sb.f_bavail * sb.f_bsize / 1024; limit= strtoul(limit_str, &check, 10); if (check[0] != '\0') diff --git a/probe-busybox/eperd/ping.c b/probe-busybox/eperd/ping.c index a407256..473d13a 100644 --- a/probe-busybox/eperd/ping.c +++ b/probe-busybox/eperd/ping.c @@ -437,9 +437,6 @@ static void ping_cb(int result, unsigned bytes, int psize, if (strcmp(namebuf1, namebuf2) != 0) { - printf("loc_sin6: %s\n", namebuf1); - - printf("loc_sa: %s\n", namebuf2); /* Ensure we don't overflow the line buffer */ { @@ -740,6 +737,10 @@ static void ping_xmit(struct pingstate *host) getsockname(host->socket, (struct sockaddr *)&host->loc_sin6, &host->loc_socklen); + fixup_loc_sockname(host->af, + (struct sockaddr *)&host->sin6, + host->socklen, &host->loc_sin6, + &host->loc_socklen); if (host->resp_file_out) { write_response(host->resp_file_out, @@ -778,6 +779,9 @@ static void ping_xmit(struct pingstate *host) host->loc_socklen= sizeof(host->loc_sin6); getsockname(host->socket, (struct sockaddr *)&host->loc_sin6, &host->loc_socklen); + fixup_loc_sockname(host->af, + (struct sockaddr *)&host->sin6, host->socklen, + &host->loc_sin6, &host->loc_socklen); if (host->response_in) { @@ -1687,6 +1691,10 @@ static void ping_start2(void *state) getsockname(pingstate->socket, (struct sockaddr *)&pingstate->loc_sin6, &pingstate->loc_socklen); + fixup_loc_sockname(pingstate->af, + (struct sockaddr *)&pingstate->sin6, + pingstate->socklen, &pingstate->loc_sin6, + &pingstate->loc_socklen); if (pingstate->resp_file_out) { write_response(pingstate->resp_file_out, diff --git a/probe-busybox/eperd/traceroute.c b/probe-busybox/eperd/traceroute.c index cdff930..aee2eb3 100644 --- a/probe-busybox/eperd/traceroute.c +++ b/probe-busybox/eperd/traceroute.c @@ -4910,6 +4910,13 @@ static int create_socket(struct trtstate *state, int do_tcp) { crondlog(DIE9 "getsockname failed"); } + if (!state->response_in) + { + fixup_loc_sockname(state->sin6.sin6_family, + (struct sockaddr *)&state->sin6, + state->socklen, &state->loc_sin6, + &state->loc_socklen); + } } if (state->resp_file_out) { diff --git a/probe-busybox/include/libbb.h b/probe-busybox/include/libbb.h index 45dbdd5..0000eb9 100644 --- a/probe-busybox/include/libbb.h +++ b/probe-busybox/include/libbb.h @@ -472,6 +472,8 @@ extern int get_timesync(void); extern int gettime_mono(struct timespec *tsp); extern char *atlas_get_version_json_str(void); extern int bind_interface(int socket, int af, char *name); +extern void fixup_loc_sockname(int af, const struct sockaddr *dst, + socklen_t dstlen, struct sockaddr_in6 *loc, socklen_t *loclen); extern int atlas_check_addr(const struct sockaddr *sa, socklen_t len); extern char *atlas_name_macro(char *str); extern int atlas_tests(void); diff --git a/probe-busybox/libbb/Kbuild.src b/probe-busybox/libbb/Kbuild.src index 10bd039..71024a9 100644 --- a/probe-busybox/libbb/Kbuild.src +++ b/probe-busybox/libbb/Kbuild.src @@ -33,6 +33,7 @@ lib-y += atlas_write_response.o # #lib-y += bb_strtod.o lib-y += bb_strtonum.o lib-y += bind_interface.o +lib-y += fixup_sockname.o # lib-y += change_identity.o # lib-y += chomp.o lib-y += compare_string_array.o diff --git a/probe-busybox/libbb/fixup_sockname.c b/probe-busybox/libbb/fixup_sockname.c new file mode 100644 index 0000000..8a083c6 --- /dev/null +++ b/probe-busybox/libbb/fixup_sockname.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 RIPE NCC + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + */ + +#include "libbb.h" +#include + +/* + * connect(2) on a raw socket does not select a source address on all + * platforms, leaving getsockname(2) reporting the unspecified address. + * Ask the routing table the same question with a throwaway connected UDP + * socket. A no-op where the address is already known. + */ +void fixup_loc_sockname(int af, const struct sockaddr *dst, socklen_t dstlen, + struct sockaddr_in6 *loc, socklen_t *loclen) +{ + union + { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } probe; + socklen_t len; + int s; + + if (af == AF_INET) + { + if (((struct sockaddr_in *)loc)->sin_addr.s_addr != + htonl(INADDR_ANY)) + { + return; + } + } + else if (!IN6_IS_ADDR_UNSPECIFIED(&loc->sin6_addr)) + return; + + if (dstlen == 0 || dstlen > sizeof(probe)) + return; + + memset(&probe, '\0', sizeof(probe)); + memcpy(&probe, dst, dstlen); + if (af == AF_INET) + probe.sin.sin_port= htons(9); + else + probe.sin6.sin6_port= htons(9); + + s= socket(af, SOCK_DGRAM, 0); + if (s == -1) + return; + if (connect(s, &probe.sa, dstlen) == 0) + { + len= sizeof(*loc); + if (getsockname(s, (struct sockaddr *)loc, &len) == 0) + *loclen= len; + } + close(s); +} diff --git a/probe-busybox/networking/rptaddrs.c b/probe-busybox/networking/rptaddrs.c index 4b90d84..299003a 100644 --- a/probe-busybox/networking/rptaddrs.c +++ b/probe-busybox/networking/rptaddrs.c @@ -45,6 +45,13 @@ #include #include "portable_networking.h" +#ifdef __FreeBSD__ +#include +#include +#include +#include +#endif + #define IPV4_ROUTE_FILE "/proc/net/route" #define IF_INET6_FILE "/proc/net/if_inet6" #define IPV6_ROUTE_FILE "/proc/net/ipv6_route" @@ -244,6 +251,183 @@ static FILE *setup_cache(char *cache_name) #define MAX_INF 10 + +#ifdef __FreeBSD__ +/* + * SIOCGIFCONF returns variable-length records on BSD and the routing table + * lives in sysctl(NET_RT_DUMP), not /proc. + */ + +#ifndef SA_SIZE +#define SA_SIZE(sa) \ + ((!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ + sizeof(long) : \ + 1 + ((((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1))) +#endif + +static void rt_get_addrs(int addrs, struct sockaddr *sa, + struct sockaddr **rti) +{ + int i; + + for (i= 0; iifa_next) + { + if (ifa->ifa_addr == NULL || + ifa->ifa_addr->sa_family != AF_INET) + { + continue; + } + + sin= (struct sockaddr_in *)ifa->ifa_addr; + inet_ntop(AF_INET, &sin->sin_addr, addrstr, sizeof(addrstr)); + + in_addr.s_addr= 0; + if (ifa->ifa_netmask != NULL) + { + sin= (struct sockaddr_in *)ifa->ifa_netmask; + in_addr= sin->sin_addr; + } + inet_ntop(AF_INET, &in_addr, maskstr, sizeof(maskstr)); + + fprintf(of, "%s{ " DBQ(inet-addr) ": " DBQ(%s) ", " + DBQ(netmask) ": " DBQ(%s) ", " + DBQ(interface) ": " DBQ(%s) " }", + first ? "" : ", ", addrstr, maskstr, ifa->ifa_name); + first= 0; + } + freeifaddrs(ifap); + + fprintf(of, " ]"); + + mib[0]= CTL_NET; + mib[1]= PF_ROUTE; + mib[2]= 0; + mib[3]= AF_INET; + mib[4]= NET_RT_DUMP; + mib[5]= 0; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1) + { + report_err("NET_RT_DUMP size failed"); + return -1; + } + buf= malloc(needed); + if (buf == NULL) + { + report_err("malloc failed"); + return -1; + } + if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1) + { + report_err("NET_RT_DUMP failed"); + free(buf); + return -1; + } + + fprintf(of, ", " DBQ(inet-routes) ": [ "); + first= 1; + lim= buf + needed; + for (next= buf; next < lim; next += rtm->rtm_msglen) + { + rtm= (struct rt_msghdr *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + if (!(rtm->rtm_flags & RTF_UP)) + continue; + + rt_get_addrs(rtm->rtm_addrs, (struct sockaddr *)(rtm + 1), + rti); + + if (rti[RTAX_DST] == NULL || + rti[RTAX_DST]->sa_family != AF_INET) + { + continue; + } + sin= (struct sockaddr_in *)rti[RTAX_DST]; + inet_ntop(AF_INET, &sin->sin_addr, addrstr, sizeof(addrstr)); + + /* Netmask sockaddrs are truncated; absent bytes are zero. */ + in_addr.s_addr= 0; + if (rtm->rtm_flags & RTF_HOST) + in_addr.s_addr= 0xffffffff; + else if (rti[RTAX_NETMASK] != NULL && + rti[RTAX_NETMASK]->sa_len > + offsetof(struct sockaddr_in, sin_addr)) + { + n= rti[RTAX_NETMASK]->sa_len - + offsetof(struct sockaddr_in, sin_addr); + if (n > sizeof(in_addr)) + n= sizeof(in_addr); + memcpy(&in_addr, (char *)rti[RTAX_NETMASK] + + offsetof(struct sockaddr_in, sin_addr), n); + } + inet_ntop(AF_INET, &in_addr, maskstr, sizeof(maskstr)); + + in_addr.s_addr= 0; + if (rti[RTAX_GATEWAY] != NULL && + rti[RTAX_GATEWAY]->sa_family == AF_INET) + { + in_addr= ((struct sockaddr_in *)rti[RTAX_GATEWAY])-> + sin_addr; + } + inet_ntop(AF_INET, &in_addr, nhstr, sizeof(nhstr)); + + if (if_indextoname(rtm->rtm_index, ifname) == NULL) + { + ifname[0]= (char)0x3f; + ifname[1]= (char)0; + } + + fprintf(of, "%s{ " DBQ(destination) ": " DBQ(%s) ", " + DBQ(netmask) ": " DBQ(%s) ", " + DBQ(next-hop) ": " DBQ(%s) ", " + DBQ(interface) ": " DBQ(%s) " }", + first ? "" : ", ", addrstr, maskstr, nhstr, ifname); + first= 0; + } + free(buf); + + fprintf(of, " ]"); + + return 0; +} + +#else /* !__FreeBSD__ */ static int setup_ipv4_rpt(FILE *of) { size_t i; @@ -338,6 +522,8 @@ static int setup_ipv4_rpt(FILE *of) return 0; } +#endif /* __FreeBSD__ */ + static int setup_dhcpv4(FILE *of) { int found;