예제 #1
0
char *get_name_by_macaddr(struct ether_addr *mac_addr, int read_opt)
{
	struct bat_host *bat_host = NULL;

	if (read_opt & USE_BAT_HOSTS)
		bat_host = bat_hosts_find_by_mac((char *)mac_addr);

	if (!bat_host)
		host_name = ether_ntoa_long((struct ether_addr *)mac_addr);
	else
		host_name = bat_host->name;

	return host_name;
}
예제 #2
0
파일: ping.c 프로젝트: asriadi/batmand
int ping(char *mesh_iface, int argc, char **argv)
{
	struct icmp_packet_rr icmp_packet_out, icmp_packet_in;
	struct timeval tv;
	struct ether_addr *dst_mac = NULL, *rr_mac = NULL;
	struct bat_host *bat_host, *rr_host;
	ssize_t read_len;
	fd_set read_socket;
	int ret = EXIT_FAILURE, ping_fd = 0, res, optchar, found_args = 1;
	int loop_count = -1, loop_interval = 0, timeout = 1, rr = 0, i;
	unsigned int seq_counter = 0, packets_out = 0, packets_in = 0, packets_loss;
	char *dst_string, *mac_string, *rr_string;
	double time_delta;
	float min = 0.0, max = 0.0, avg = 0.0, mdev = 0.0;
	uint8_t last_rr_cur = 0, last_rr[BAT_RR_LEN][ETH_ALEN];
	size_t packet_len;
	char *debugfs_mnt;
	char icmp_socket[MAX_PATH+1];

	while ((optchar = getopt(argc, argv, "hc:i:t:R")) != -1) {
		switch (optchar) {
		case 'c':
			loop_count = strtol(optarg, NULL , 10);
			if (loop_count < 1)
				loop_count = -1;
			found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
			break;
		case 'h':
			ping_usage();
			return EXIT_SUCCESS;
		case 'i':
			loop_interval = strtol(optarg, NULL , 10);
			if (loop_interval < 1)
				loop_interval = 1;
			found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
			break;
		case 't':
			timeout = strtol(optarg, NULL , 10);
			if (timeout < 1)
				timeout = 1;
			found_args += ((*((char*)(optarg - 1)) == optchar ) ? 1 : 2);
			break;
		case 'R':
			rr = 1;
			found_args++;
			break;
		default:
			ping_usage();
			return EXIT_FAILURE;
		}
	}

	if (argc <= found_args) {
		printf("Error - target mac address or bat-host name not specified\n");
		ping_usage();
		return EXIT_FAILURE;
	}

	dst_string = argv[found_args];
	bat_hosts_init(0);
	bat_host = bat_hosts_find_by_name(dst_string);

	if (bat_host)
		dst_mac = &bat_host->mac_addr;

	if (!dst_mac) {
		dst_mac = ether_aton(dst_string);

		if (!dst_mac) {
			printf("Error - the ping destination is not a mac address or bat-host name: %s\n", dst_string);
			goto out;
		}
	}

	mac_string = ether_ntoa_long(dst_mac);
	signal(SIGINT, sig_handler);
	signal(SIGTERM, sig_handler);

	debugfs_mnt = debugfs_mount(NULL);
	if (!debugfs_mnt) {
		printf("Error - can't mount or find debugfs\n");
		goto out;
	}

	debugfs_make_path(SOCKET_PATH_FMT, mesh_iface, icmp_socket, sizeof(icmp_socket));

	ping_fd = open(icmp_socket, O_RDWR);

	if (ping_fd < 0) {
		printf("Error - can't open a connection to the batman adv kernel module via the socket '%s': %s\n",
				icmp_socket, strerror(errno));
		printf("Check whether the module is loaded and active.\n");
		goto out;
	}

	packet_len = sizeof(struct icmp_packet);

	memcpy(&icmp_packet_out.dst, dst_mac, ETH_ALEN);
	icmp_packet_out.packet_type = BAT_ICMP;
	icmp_packet_out.version = COMPAT_VERSION;
	icmp_packet_out.msg_type = ECHO_REQUEST;
	icmp_packet_out.ttl = 50;
	icmp_packet_out.seqno = 0;

	if (rr) {
		packet_len = sizeof(struct icmp_packet_rr);
		icmp_packet_out.rr_cur = 1;
		memset(&icmp_packet_out.rr, 0, BAT_RR_LEN * ETH_ALEN);
		memset(last_rr, 0, BAT_RR_LEN * ETH_ALEN);
	}

	printf("PING %s (%s) %zu(%zu) bytes of data\n", dst_string, mac_string,
		packet_len, packet_len + 28);

	while (!is_aborted) {
		tv.tv_sec = timeout;
		tv.tv_usec = 0;

		if (loop_count == 0)
			break;

		if (loop_count > 0)
			loop_count--;

		icmp_packet_out.seqno = htons(++seq_counter);

		if (write(ping_fd, (char *)&icmp_packet_out, packet_len) < 0) {
			printf("Error - can't write to batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno));
			goto sleep;
		}

		start_timer();

		FD_ZERO(&read_socket);
		FD_SET(ping_fd, &read_socket);

		res = select(ping_fd + 1, &read_socket, NULL, NULL, &tv);

		if (is_aborted)
			break;

		packets_out++;

		if (res == 0) {
			printf("Reply from host %s timed out\n", dst_string);
			goto sleep;
		}

		if (res < 0)
			goto sleep;

		read_len = read(ping_fd, (char *)&icmp_packet_in, packet_len);

		if (read_len < 0) {
			printf("Error - can't read from batman adv kernel file '%s': %s\n", icmp_socket, strerror(errno));
			goto sleep;
		}

		if ((size_t)read_len < packet_len) {
			printf("Warning - dropping received packet as it is smaller than expected (%zu): %zd\n",
				packet_len, read_len);
			goto sleep;
		}

		switch (icmp_packet_in.msg_type) {
		case ECHO_REPLY:
			time_delta = end_timer();
			printf("%zd bytes from %s icmp_seq=%hu ttl=%d time=%.2f ms",
					read_len, dst_string, ntohs(icmp_packet_in.seqno),
					icmp_packet_in.ttl, time_delta);

			if (read_len == sizeof(struct icmp_packet_rr)) {
				if (last_rr_cur == icmp_packet_in.rr_cur
					&& !memcmp(last_rr, icmp_packet_in.rr, BAT_RR_LEN * ETH_ALEN)) {

					printf("\t(same route)");

				} else {
					printf("\nRR: ");

					for (i = 0; i < BAT_RR_LEN
						&& i < icmp_packet_in.rr_cur; i++) {

						rr_mac = (struct ether_addr *)&icmp_packet_in.rr[i];
						rr_host = bat_hosts_find_by_mac((char *)rr_mac);
						if (rr_host)
							rr_string = rr_host->name;
						else
							rr_string = ether_ntoa_long(rr_mac);
						printf("\t%s\n", rr_string);

						if (memcmp(rr_mac, dst_mac, ETH_ALEN) == 0)
							printf("\t%s\n", rr_string);
					}

					last_rr_cur = icmp_packet_in.rr_cur;
					memcpy(last_rr, icmp_packet_in.rr, BAT_RR_LEN * ETH_ALEN);
				}
			}

			printf("\n");

			if ((time_delta < min) || (min == 0.0))
				min = time_delta;
			if (time_delta > max)
				max = time_delta;
			avg += time_delta;
			mdev += time_delta * time_delta;
			packets_in++;
			break;
		case DESTINATION_UNREACHABLE:
			printf("From %s: Destination Host Unreachable (icmp_seq %hu)\n", dst_string, ntohs(icmp_packet_in.seqno));
			break;
		case TTL_EXCEEDED:
			printf("From %s: Time to live exceeded (icmp_seq %hu)\n", dst_string, ntohs(icmp_packet_in.seqno));
			break;
		case PARAMETER_PROBLEM:
			printf("Error - the batman adv kernel module version (%d) differs from ours (%d)\n",
					icmp_packet_in.ttl, COMPAT_VERSION);
			printf("Please make sure to compatible versions!\n");
			goto out;
		default:
			printf("Unknown message type %d len %zd received\n", icmp_packet_in.msg_type, read_len);
			break;
		}

sleep:
		if (loop_interval > 0)
			sleep(loop_interval);
		else if ((tv.tv_sec != 0) || (tv.tv_usec != 0))
			select(0, NULL, NULL, NULL, &tv);
	}

	if (packets_out == 0)
		packets_loss = 0;
	else
		packets_loss = ((packets_out - packets_in) * 100) / packets_out;

	if (packets_in) {
		avg /= packets_in;
		mdev /= packets_in;
		mdev = mdev - avg * avg;
		if (mdev > 0.0)
			mdev = sqrt(mdev);
		else
			mdev = 0.0;
	} else {
		avg = 0.0;
		mdev = 0.0;
	}

	printf("--- %s ping statistics ---\n", dst_string);
	printf("%u packets transmitted, %u received, %u%% packet loss\n",
		packets_out, packets_in, packets_loss);
	printf("rtt min/avg/max/mdev = %.3f/%.3f/%.3f/%.3f ms\n",
		min, avg, max, mdev);

	ret = EXIT_SUCCESS;

out:
	bat_hosts_free();
	if (ping_fd)
		close(ping_fd);
	return ret;
}
예제 #3
0
int read_file(const char *dir, const char *fname, int read_opt,
	      float orig_timeout, float watch_interval, size_t header_lines)
{
	struct ether_addr *mac_addr;
	struct bat_host *bat_host;
	int res = EXIT_FAILURE;
	float last_seen;
	char full_path[500], *buff_ptr, *space_ptr, extra_char;
	size_t len = 0;
	FILE *fp = NULL;
	size_t line;

	if (read_opt & USE_BAT_HOSTS)
		bat_hosts_init(read_opt);

	strncpy(full_path, dir, strlen(dir));
	full_path[strlen(dir)] = '\0';
	strncat(full_path, fname, sizeof(full_path) - strlen(full_path) - 1);

open:
	line = 0;
	fp = fopen(full_path, "r");

	if (!fp) {
		if (!(read_opt & SILENCE_ERRORS))
			file_open_problem_dbg(dir, fname, full_path);

		goto out;
	}

	if (read_opt & CLR_CONT_READ)
		/* clear screen, set cursor back to 0,0 */
		printf("\033[2J\033[0;0f");

read:
	while (getline(&line_ptr, &len, fp) != -1) {
		if (line++ < header_lines && read_opt & SKIP_HEADER)
			continue;

		/* the buffer will be handled elsewhere */
		if (read_opt & USE_READ_BUFF)
			break;

		/* skip timed out originators */
		if (read_opt & NO_OLD_ORIGS)
			if (sscanf(line_ptr, "%*s %f", &last_seen)
			    && (last_seen > orig_timeout))
				continue;

		if (!(read_opt & USE_BAT_HOSTS)) {
			printf("%s", line_ptr);
			continue;
		}

		/* replace mac addresses with bat host names */
		buff_ptr = line_ptr;

		while ((space_ptr = strchr(buff_ptr, ' ')) != NULL) {

			*space_ptr = '\0';
			extra_char = '\0';

			if (strlen(buff_ptr) == ETH_STR_LEN + 1) {
				extra_char = buff_ptr[ETH_STR_LEN];
				switch (extra_char) {
				case ',':
				case ')':
					buff_ptr[ETH_STR_LEN] = '\0';
					break;
				default:
					extra_char = '\0';
					break;
				}
			}

			if (strlen(buff_ptr) != ETH_STR_LEN)
				goto print_plain_buff;

			mac_addr = ether_aton(buff_ptr);

			if (!mac_addr)
				goto print_plain_buff;

			bat_host = bat_hosts_find_by_mac((char *)mac_addr);

			if (!bat_host)
				goto print_plain_buff;

			if (read_opt & LOG_MODE)
				printf("%s", bat_host->name);
			else
				/* keep table format */
				printf("%17s", bat_host->name);

			goto written;

print_plain_buff:
			printf("%s", buff_ptr);

written:
			if (extra_char != '\0')
				printf("%c", extra_char);

			printf(" ");
			buff_ptr = space_ptr + 1;
		}

		printf("%s", buff_ptr);
	}

	if (read_opt & CONT_READ) {
		usleep(1000000 * watch_interval);
		goto read;
	}

	if (read_opt & CLR_CONT_READ) {
		if (fp)
			fclose(fp);
		usleep(1000000 * watch_interval);
		goto open;
	}

	res = EXIT_SUCCESS;

out:
	if (fp)
		fclose(fp);

	if (read_opt & USE_BAT_HOSTS)
		bat_hosts_free();

	return res;
}
예제 #4
0
static void parse_hosts_file(struct hashtable_t **hash, const char path[], int read_opt)
{
	FILE *fd;
	char *line_ptr = NULL;
	char name[HOST_NAME_MAX_LEN], mac_str[18];
	struct ether_addr *mac_addr;
	struct bat_host *bat_host;
	struct hashtable_t *swaphash;
	size_t len = 0;

	name[0] = mac_str[0] = '\0';

	fd = fopen(path, "r");
	if (!fd)
		return;

	while (getline(&line_ptr, &len, fd) != -1) {
		/* ignore empty lines and comments */
		if ((line_ptr[0] == '\n') || (line_ptr[0] == '#'))
			continue;

		if (sscanf(line_ptr, "%17[^ \t]%49s\n", mac_str, name) != 2) {
			if (read_opt & USE_BAT_HOSTS)
				fprintf(stderr, "Warning - unrecognized bat-host definition: %s", line_ptr);
			continue;
		}

		mac_addr = ether_aton(mac_str);
		if (!mac_addr) {
			if (read_opt & USE_BAT_HOSTS)
				fprintf(stderr, "Warning - invalid mac address in '%s' detected: %s\n", path, mac_str);
			continue;
		}

		bat_host = bat_hosts_find_by_mac((char *)mac_addr);

		/* mac entry already exists - we found a new name for it */
		if (bat_host) {
			/* if the mac addresses and the names are the same we can safely ignore the entry */
			if (strcmp(bat_host->name, name) == 0)
				continue;

			if (read_opt & USE_BAT_HOSTS)
				fprintf(stderr, "Warning - mac already known (changing name from '%s' to '%s'): %s\n",
					bat_host->name, name, mac_str);
			strncpy(bat_host->name, name, HOST_NAME_MAX_LEN - 1);
			continue;
		}

		bat_host = bat_hosts_find_by_name(name);

		/* name entry already exists - we found a new mac address for it */
		if (bat_host) {
			if (read_opt & USE_BAT_HOSTS)
				fprintf(stderr, "Warning - name already known (changing mac from '%s' to '%s'): %s\n",
					ether_ntoa(&bat_host->mac_addr), mac_str, name);
			hash_remove(*hash, bat_host);
			free(bat_host);
		}

		bat_host = malloc(sizeof(struct bat_host));

		if (!bat_host) {
			if (read_opt & USE_BAT_HOSTS)
				fprintf(stderr, "Error - could not allocate memory: %s\n", strerror(errno));
			goto out;
		}

		memcpy(&bat_host->mac_addr, mac_addr, sizeof(struct ether_addr));
		strncpy(bat_host->name, name, HOST_NAME_MAX_LEN - 1);

		hash_add(*hash, bat_host);

		if ((*hash)->elements * 4 > (*hash)->size) {
			swaphash = hash_resize((*hash), (*hash)->size * 2);

			if (swaphash)
				*hash = swaphash;
			else if (read_opt & USE_BAT_HOSTS)
				fprintf(stderr, "Warning - couldn't resize bat hosts hash table\n");
		}
	}

out:
	if (fd)
		fclose(fd);
	if (line_ptr)
		free(line_ptr);
	return;
}