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