summaryrefslogtreecommitdiff
path: root/rdns_scan/zmap4rdns/lib/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'rdns_scan/zmap4rdns/lib/util.c')
-rw-r--r--rdns_scan/zmap4rdns/lib/util.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/rdns_scan/zmap4rdns/lib/util.c b/rdns_scan/zmap4rdns/lib/util.c
new file mode 100644
index 0000000..0a1403f
--- /dev/null
+++ b/rdns_scan/zmap4rdns/lib/util.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2021 Regents of the University of Michigan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include "util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "includes.h"
+#include "xalloc.h"
+
+#include <errno.h>
+#include <unistd.h>
+#include <sched.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+#include "../lib/logger.h"
+
+#define MAX_SPLITS 128
+
+int max_int(int a, int b)
+{
+ if (a >= b) {
+ return a;
+ }
+ return b;
+}
+
+void enforce_range(const char *name, int v, int min, int max)
+{
+ if (check_range(v, min, max) == EXIT_FAILURE) {
+ log_fatal("zmap", "argument `%s' must be between %d and %d\n",
+ name, min, max);
+ }
+}
+
+void split_string(const char *in, int *len, const char ***results)
+{
+ const char **fields = xcalloc(MAX_SPLITS, sizeof(const char *));
+ int retvlen = 0;
+ const char *currloc = in;
+ // parse csv into a set of strings
+ while (1) {
+ assert(retvlen < MAX_SPLITS);
+ size_t len = strcspn(currloc, ", ");
+ if (len == 0) {
+ currloc++;
+ } else {
+ char *new = xmalloc(len + 1);
+ strncpy(new, currloc, len);
+ new[len] = '\0';
+ fields[retvlen++] = new;
+ assert(fields[retvlen - 1]);
+ }
+ if (len == strlen(currloc)) {
+ break;
+ }
+ currloc += len;
+ }
+ *results = fields;
+ *len = retvlen;
+}
+
+void fprintw(FILE *f, const char *s, size_t w)
+{
+ if (strlen(s) <= w) {
+ fprintf(f, "%s", s);
+ return;
+ }
+ // process each line individually in order to
+ // respect existing line breaks in string.
+ char *news = strdup(s);
+ char *pch = strtok(news, "\n");
+ while (pch) {
+ if (strlen(pch) <= w) {
+ printf("%s\n", pch);
+ pch = strtok(NULL, "\n");
+ continue;
+ }
+ char *t = pch;
+ while (strlen(t)) {
+ size_t numchars = 0; // number of chars to print
+ char *tmp = t;
+ while (1) {
+ size_t new = strcspn(tmp, " ") + 1;
+ if (new == strlen(tmp) || new > w) {
+ // there are no spaces in the string,
+ // so, just print the entire thing on
+ // one line;
+ numchars += new;
+ break;
+ } else if (numchars + new > w) {
+ // if we added any more, we'd be over w
+ // chars so time to print the line and
+ // move on to the next.
+ break;
+ } else {
+ tmp += (size_t) new;
+ numchars += new;
+ }
+ }
+ fprintf(f, "%.*s\n", (int)numchars, t);
+ t += (size_t)numchars;
+ if (t > pch + (size_t)strlen(pch)) {
+ break;
+ }
+ }
+ pch = strtok(NULL, "\n");
+ }
+ free(news);
+}
+
+uint32_t parse_max_hosts(char *max_targets)
+{
+ char *end;
+ errno = 0;
+ double v = strtod(max_targets, &end);
+ if (end == max_targets || errno != 0) {
+ log_fatal("argparse", "can't convert max-targets to a number");
+ }
+ if (end[0] == '%' && end[1] == '\0') {
+ // treat as percentage
+ v = v * ((unsigned long long int)1 << 32) / 100.;
+ } else if (end[0] != '\0') {
+ log_fatal("eargparse", "extra characters after max-targets");
+ }
+ if (v <= 0) {
+ return 0;
+ } else if (v >= ((unsigned long long int)1 << 32)) {
+ return 0xFFFFFFFF;
+ } else {
+ return v;
+ }
+}
+
+// pretty print elapsed (or estimated) number of seconds
+void time_string(uint32_t time, int est, char *buf, size_t len)
+{
+ int y = time / 31556736;
+ int d = (time % 31556736) / 86400;
+ int h = (time % 86400) / 3600;
+ int m = (time % 3600) / 60;
+ int s = time % 60;
+
+ if (est) {
+ if (y > 0) {
+ snprintf(buf, len, "%d years", y);
+ } else if (d > 9) {
+ snprintf(buf, len, "%dd", d);
+ } else if (d > 0) {
+ snprintf(buf, len, "%dd%02dh", d, h);
+ } else if (h > 9) {
+ snprintf(buf, len, "%dh", h);
+ } else if (h > 0) {
+ snprintf(buf, len, "%dh%02dm", h, m);
+ } else if (m > 9) {
+ snprintf(buf, len, "%dm", m);
+ } else if (m > 0) {
+ snprintf(buf, len, "%dm%02ds", m, s);
+ } else {
+ snprintf(buf, len, "%ds", s);
+ }
+ } else {
+ if (d > 0) {
+ snprintf(buf, len, "%dd%d:%02d:%02d", d, h, m, s);
+ } else if (h > 0) {
+ snprintf(buf, len, "%d:%02d:%02d", h, m, s);
+ } else {
+ snprintf(buf, len, "%d:%02d", m, s);
+ }
+ }
+}
+
+// pretty print quantities
+void number_string(uint32_t n, char *buf, size_t len)
+{
+ int figs = 0;
+ if (n < 1000) {
+ snprintf(buf, len, "%u ", n);
+ } else if (n < 1000000) {
+ if (n < 10000) {
+ figs = 2;
+ } else if (n < 100000) {
+ figs = 1;
+ }
+ snprintf(buf, len, "%0.*f K", figs, (float)n / 1000.);
+ } else {
+ if (figs < 10000000) {
+ figs = 2;
+ } else if (figs < 100000000) {
+ figs = 1;
+ }
+ snprintf(buf, len, "%0.*f M", figs, (float)n / 1000000.);
+ }
+}
+
+int parse_mac(macaddr_t *out, char *in)
+{
+ if (strlen(in) < MAC_ADDR_LEN * 3 - 1)
+ return 0;
+ char octet[4];
+ octet[2] = '\0';
+ for (int i = 0; i < MAC_ADDR_LEN; i++) {
+ if (i < MAC_ADDR_LEN - 1 && in[i * 3 + 2] != ':') {
+ return 0;
+ }
+ strncpy(octet, &in[i * 3], 2);
+ char *err = NULL;
+ long b = strtol(octet, &err, 16);
+ if (err && *err != '\0') {
+ return 0;
+ }
+ out[i] = b & 0xFF;
+ }
+ return 1;
+}
+
+int check_range(int v, int min, int max)
+{
+ if (v < min || v > max) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+int file_exists(char *name)
+{
+ FILE *file = fopen(name, "r");
+ if (!file)
+ return 0;
+ fclose(file);
+ return 1;
+}
+
+#if defined(__APPLE__)
+#include <uuid/uuid.h>
+#endif
+
+int drop_privs()
+{
+ struct passwd *pw;
+ if (geteuid() != 0) {
+ /* Not root */
+ return EXIT_SUCCESS;
+ }
+ if ((pw = getpwnam("nobody")) != NULL) {
+ if (setuid(pw->pw_uid) == 0) {
+ return EXIT_SUCCESS; // success
+ }
+ }
+ return EXIT_FAILURE;
+}
+
+#if defined(__APPLE__)
+
+#include <mach/thread_act.h>
+
+int set_cpu(uint32_t core)
+{
+ mach_port_t tid = pthread_mach_thread_np(pthread_self());
+ struct thread_affinity_policy policy;
+ policy.affinity_tag = core;
+ kern_return_t ret = thread_policy_set(tid, THREAD_AFFINITY_POLICY,
+ (thread_policy_t)&policy,
+ THREAD_AFFINITY_POLICY_COUNT);
+ if (ret != KERN_SUCCESS) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+#elif defined(__DragonFly__)
+
+#include <sys/usched.h>
+
+int set_cpu(uint32_t core)
+{
+ if (usched_set(getpid(), USCHED_SET_CPU, &core, sizeof(core)) != 0) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+#elif defined(__NetBSD__)
+
+int set_cpu(uint32_t core)
+{
+ cpuset_t *cpuset = cpuset_create();
+ if (cpuset == NULL) {
+ return EXIT_FAILURE;
+ }
+ cpuset_zero(cpuset);
+ cpuset_set(core, cpuset);
+ cpuset_destroy(cpuset);
+
+ if (pthread_setaffinity_np(pthread_self(), cpuset_size(cpuset),
+ cpuset) != 0) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+#else
+
+#if defined(__FreeBSD__)
+#include <sys/param.h>
+#include <sys/cpuset.h>
+#include <pthread_np.h>
+#define cpu_set_t cpuset_t
+#endif
+
+int set_cpu(uint32_t core)
+{
+ cpu_set_t cpuset;
+ CPU_ZERO(&cpuset);
+ CPU_SET(core, &cpuset);
+
+ if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t),
+ &cpuset) != 0) {
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+#endif