112518Sjnimeh/*-
212518Sjnimeh * SPDX-License-Identifier: BSD-3-Clause
312518Sjnimeh *
412518Sjnimeh * Copyright (c) 1983, 1988, 1993
512518Sjnimeh *	The Regents of the University of California.  All rights reserved.
612518Sjnimeh *
712518Sjnimeh * Redistribution and use in source and binary forms, with or without
812518Sjnimeh * modification, are permitted provided that the following conditions
912518Sjnimeh * are met:
1012518Sjnimeh * 1. Redistributions of source code must retain the above copyright
1112518Sjnimeh *    notice, this list of conditions and the following disclaimer.
1212518Sjnimeh * 2. Redistributions in binary form must reproduce the above copyright
1312518Sjnimeh *    notice, this list of conditions and the following disclaimer in the
1412518Sjnimeh *    documentation and/or other materials provided with the distribution.
1512518Sjnimeh * 3. Neither the name of the University nor the names of its contributors
1612518Sjnimeh *    may be used to endorse or promote products derived from this software
1712518Sjnimeh *    without specific prior written permission.
1812518Sjnimeh *
1912518Sjnimeh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2012518Sjnimeh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2112518Sjnimeh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2212518Sjnimeh * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2312518Sjnimeh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2412518Sjnimeh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2512518Sjnimeh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2612518Sjnimeh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2712518Sjnimeh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2812518Sjnimeh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2912518Sjnimeh * SUCH DAMAGE.
3012518Sjnimeh */
3112518Sjnimeh
3212518Sjnimeh#include <sys/param.h>
3312518Sjnimeh#include <sys/protosw.h>
3412518Sjnimeh#include <sys/socket.h>
3512518Sjnimeh#include <sys/socketvar.h>
3612518Sjnimeh#include <sys/sysctl.h>
3712518Sjnimeh#include <sys/time.h>
3812518Sjnimeh
3912518Sjnimeh#include <net/if.h>
4012518Sjnimeh#include <net/if_dl.h>
4112518Sjnimeh#include <arpa/inet.h>
4212518Sjnimeh#include <ifaddrs.h>
4312518Sjnimeh#include <libutil.h>
4412518Sjnimeh#include <netdb.h>
4512518Sjnimeh#include <stdbool.h>
4612518Sjnimeh#include <stdint.h>
4712518Sjnimeh#include <stdio.h>
4812518Sjnimeh#include <stdlib.h>
4912518Sjnimeh#include <stdbool.h>
5012518Sjnimeh#include <string.h>
5112518Sjnimeh#include <sysexits.h>
5212826Sjnimeh#include <unistd.h>
5312518Sjnimeh#include <err.h>
5412518Sjnimeh#include <libxo/xo.h>
5512518Sjnimeh#include "netstat.h"
5612518Sjnimeh#include "common.h"
5712518Sjnimeh
5812518Sjnimehconst char *
5912518Sjnimehfmt_flags(const struct bits *p, int f)
6012518Sjnimeh{
6112518Sjnimeh	static char name[33];
6212518Sjnimeh	char *flags;
6312518Sjnimeh
6412518Sjnimeh	for (flags = name; p->b_mask; p++)
6512518Sjnimeh		if (p->b_mask & f)
6612518Sjnimeh			*flags++ = p->b_val;
6712518Sjnimeh	*flags = '\0';
6812518Sjnimeh	return (name);
6912518Sjnimeh}
7012518Sjnimeh
7112518Sjnimehvoid
7212518Sjnimehprint_flags_generic(int flags, const struct bits *pbits, const char *format,
7312518Sjnimeh    const char *tag_name)
7412518Sjnimeh{
7512518Sjnimeh	const struct bits *p;
7612518Sjnimeh	char tag_fmt[64];
7712518Sjnimeh
7812518Sjnimeh	xo_emit(format, fmt_flags(pbits, flags));
7912518Sjnimeh
8012518Sjnimeh	snprintf(tag_fmt, sizeof(tag_fmt), "{le:%s/%%s}", tag_name);
8112518Sjnimeh	xo_open_list(tag_name);
8212518Sjnimeh	for (p = pbits; p->b_mask; p++)
8312518Sjnimeh		if (p->b_mask & flags)
8412518Sjnimeh			xo_emit(tag_fmt, p->b_name);
8512518Sjnimeh	xo_close_list(tag_name);
8612518Sjnimeh}
8712518Sjnimeh
8812518Sjnimehstruct ifmap_entry *
8912518Sjnimehprepare_ifmap(size_t *pifmap_size)
9012518Sjnimeh{
9112518Sjnimeh	int ifindex = 0, size;
9212518Sjnimeh	struct ifaddrs *ifap, *ifa;
9312518Sjnimeh	struct sockaddr_dl *sdl;
9412518Sjnimeh
9512518Sjnimeh	struct ifmap_entry *ifmap = NULL;
9612518Sjnimeh	int ifmap_size = 0;
9712518Sjnimeh
9812518Sjnimeh	/*
9912518Sjnimeh	 * Retrieve interface list at first
10012518Sjnimeh	 * since we need #ifindex -> if_xname match
10112518Sjnimeh	 */
10212518Sjnimeh	if (getifaddrs(&ifap) != 0)
10312518Sjnimeh		err(EX_OSERR, "getifaddrs");
10412518Sjnimeh
10512518Sjnimeh	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
10612518Sjnimeh
10712518Sjnimeh		if (ifa->ifa_addr->sa_family != AF_LINK)
10812518Sjnimeh			continue;
10912518Sjnimeh
11012518Sjnimeh		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
11112518Sjnimeh		ifindex = sdl->sdl_index;
11212518Sjnimeh
11312518Sjnimeh		if (ifindex >= ifmap_size) {
11412518Sjnimeh			size = roundup2(ifindex + 1, 32) *
11512518Sjnimeh			    sizeof(struct ifmap_entry);
11612518Sjnimeh			if ((ifmap = realloc(ifmap, size)) == NULL)
11712518Sjnimeh				errx(2, "realloc(%d) failed", size);
11812518Sjnimeh			memset(&ifmap[ifmap_size], 0,
11912518Sjnimeh			    size - ifmap_size *
12012518Sjnimeh			    sizeof(struct ifmap_entry));
12112518Sjnimeh
12212518Sjnimeh			ifmap_size = roundup2(ifindex + 1, 32);
12312518Sjnimeh		}
12412518Sjnimeh
12512518Sjnimeh		if (*ifmap[ifindex].ifname != '\0')
12612518Sjnimeh			continue;
12712518Sjnimeh
12812518Sjnimeh		strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ);
12912518Sjnimeh	}
13012518Sjnimeh
13112518Sjnimeh	freeifaddrs(ifap);
13212518Sjnimeh
13312518Sjnimeh	*pifmap_size = ifmap_size;
13412518Sjnimeh
13512518Sjnimeh	return (ifmap);
13612518Sjnimeh}
13712518Sjnimeh
13812518Sjnimeh