/
niceSOFT
/
inetutils
Обзор
Документация
Войти
/
niceSOFT
/
inetutils
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
ping/ping_common.c
308 строк
6 KB
Simon Josefsson
maint: Run 'make update-copyright'
20 янв 2026, 11:50
Не верифицирован
20 янв 2026, 11:50
1ce61cd
Код
Авторство
О чём код?
/* Copyright (C) 2005-2026 Free Software Foundation, Inc. This file is part of GNU Inetutils. GNU Inetutils is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GNU Inetutils 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see `http://www.gnu.org/licenses/'. */ #include <config.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <xalloc.h> #include <attribute.h> #include <timespec.h> #include "ping_common.h" extern unsigned char *data_buffer; extern size_t data_length; static void _ping_freebuf (PING * p); extern unsigned int options; size_t ping_cvt_number (const char *optarg, size_t maxval, int allow_zero) { char *p; unsigned long int n; n = strtoul (optarg, &p, 0); if (*p) error (EXIT_FAILURE, 0, "invalid value (`%s' near `%s')", optarg, p); if (n == 0 && !allow_zero) error (EXIT_FAILURE, 0, "option value too small: %s", optarg); if (maxval && n > maxval) error (EXIT_FAILURE, 0, "option value too big: %s", optarg); return n; } void init_data_buffer (unsigned char *pat, size_t len) { size_t i = 0; unsigned char *p; if (data_length == 0) return; data_buffer = xmalloc (data_length); if (pat) { for (p = data_buffer; p < data_buffer + data_length; p++) { *p = pat[i]; if (++i >= len) i = 0; } } else { for (i = 0; i < data_length; i++) data_buffer[i] = i; } } void decode_pattern (const char *text, int *pattern_len, unsigned char *pattern_data) { int i, c, off; for (i = 0; *text && i < *pattern_len; i++) { if (sscanf (text, "%2x%n", &c, &off) != 1) error (EXIT_FAILURE, 0, "error in pattern near %s", text); text += off; pattern_data[i] = c; } *pattern_len = i; } double nabs (double a) { return (a < 0) ? -a : a; } double nsqrt (double a, double prec) { double x0, x1; if (a < 0) return 0; if (a < prec) return 0; x1 = a / 2; do { x0 = x1; x1 = (x0 + a / x0) / 2; } while (nabs (x1 - x0) > prec); return x1; } int is_normed_time (n_time t) { /* A set MSB indicates non-normalised time standard. */ return (t & (1UL << 31)) ? 0 : 1; } const char * ping_cvt_time (char *buf, size_t buflen, n_time t) { n_time t_red; t_red = t & ((1UL << 31) - 1); if (is_normed_time (t)) snprintf (buf, buflen, "%u", t_red); else snprintf (buf, buflen, "<%u>", t_red); return buf; } int _ping_setbuf (PING *p, bool use_ipv6) { if (!p->ping_buffer) { p->ping_buffer = malloc (_PING_BUFLEN (p, use_ipv6)); if (!p->ping_buffer) return -1; } if (!p->ping_cktab) { p->ping_cktab = malloc (p->ping_cktab_size); if (!p->ping_cktab) return -1; memset (p->ping_cktab, 0, p->ping_cktab_size); } return 0; } int ping_set_data (PING *p, void *data, size_t off, size_t len, bool use_ipv6) { icmphdr_t *icmp; if (_ping_setbuf (p, use_ipv6)) return -1; if (p->ping_datalen < off + len) return -1; icmp = (icmphdr_t *) p->ping_buffer; memcpy (icmp->icmp_data + off, data, len); return 0; } void ping_set_count (PING *ping, size_t count) { ping->ping_count = count; } void ping_set_sockopt (PING *ping, int opt, void *val, int valsize) { setsockopt (ping->ping_fd, SOL_SOCKET, opt, (char *) &val, valsize); } void ping_set_interval (PING *ping, size_t interval) { ping->ping_interval = interval; } void _ping_freebuf (PING *p) { if (p->ping_buffer) { free (p->ping_buffer); p->ping_buffer = NULL; } if (p->ping_cktab) { free (p->ping_cktab); p->ping_cktab = NULL; } } void ping_unset_data (PING *p) { _ping_freebuf (p); } bool ping_timeout_p (struct timespec *start_time, int timeout) { if (timeout == -1) return false; return timespec_sub (current_timespec (), *start_time).tv_sec >= timeout; } char * ipaddr2str (struct sockaddr *from, socklen_t fromlen) { int err; size_t len; char *buf, ipstr[INET6_ADDRSTRLEN], hoststr[256]; err = getnameinfo (from, fromlen, ipstr, sizeof (ipstr), NULL, 0, NI_NUMERICHOST); if (err) { const char *errmsg; if (err == EAI_SYSTEM) errmsg = strerror (errno); else errmsg = gai_strerror (err); fprintf (stderr, "ping: getnameinfo: %s\n", errmsg); return xstrdup ("unknown"); } if (options & OPT_NUMERIC) return xstrdup (ipstr); err = getnameinfo (from, fromlen, hoststr, sizeof (hoststr), NULL, 0, #ifdef NI_IDN NI_IDN | NI_NAMEREQD #else NI_NAMEREQD #endif ); if (err) return xstrdup (ipstr); len = strlen (ipstr) + strlen (hoststr) + 4; /* Pair of parentheses, a space and a NUL. */ buf = xmalloc (len); snprintf (buf, len, "%s (%s)", hoststr, ipstr); return buf; } char * sinaddr2str (struct in_addr ina) { struct hostent *hp; if (options & OPT_NUMERIC) return xstrdup (inet_ntoa (ina)); hp = gethostbyaddr ((char *) &ina, sizeof (ina), AF_INET); if (hp == NULL) return xstrdup (inet_ntoa (ina)); else { char *buf, *ipstr; int len; ipstr = inet_ntoa (ina); len = strlen (ipstr) + 1; if (hp->h_name) len += strlen (hp->h_name) + 4; /* parentheses, space, and NUL */ buf = xmalloc (len); if (hp->h_name) snprintf (buf, len, "%s (%s)", hp->h_name, ipstr); else snprintf (buf, len, "%s", ipstr); return buf; } }