1122687Sbms/* 2122687Sbms * Copyright (c) 2003 Bruce M. Simpson. 3122687Sbms * All rights reserved 4122687Sbms * 5122687Sbms * Redistribution and use in source and binary forms, with or without 6122687Sbms * modification, are permitted provided that the following conditions 7122687Sbms * are met: 8122687Sbms * 1. Redistributions of source code must retain the above copyright 9122687Sbms * notice, this list of conditions and the following disclaimer. 10122687Sbms * 2. Redistributions in binary form must reproduce the above copyright 11122687Sbms * notice, this list of conditions and the following disclaimer in the 12122687Sbms * documentation and/or other materials provided with the distribution. 13122687Sbms * 3. All advertising materials mentioning features or use of this software 14122687Sbms * must display the following acknowledgement: 15122687Sbms * This product includes software developed by Bruce M. Simpson. 16122687Sbms * 4. Neither the name of Bruce M. Simpson nor the names of other 17122687Sbms * contributors may be used to endorse or promote products derived 18122687Sbms * from this software without specific prior written permission. 19122687Sbms * 20122687Sbms * THIS SOFTWARE IS PROVIDED BY BRUCE M. SIMPSON AND AFFILIATES 21122687Sbms * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22122687Sbms * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23122687Sbms * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRUCE M. SIMPSON OR CONTRIBUTORS 24122687Sbms * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25122687Sbms * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26122687Sbms * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27122687Sbms * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28122687Sbms * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29122687Sbms * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30122687Sbms * POSSIBILITY OF SUCH DAMAGE. 31122687Sbms */ 32122687Sbms 33122687Sbms#include <sys/cdefs.h> 34122687Sbms__FBSDID("$FreeBSD$"); 35122687Sbms 36122687Sbms#include "namespace.h" 37122687Sbms#include <sys/param.h> 38122687Sbms#include <sys/sysctl.h> 39122687Sbms#include <sys/ioctl.h> 40122687Sbms#include <sys/socket.h> 41122687Sbms#include <net/if.h> 42122687Sbms#include <net/if_dl.h> 43122687Sbms#include <net/route.h> 44122687Sbms 45122687Sbms#include <errno.h> 46122687Sbms#include <ifaddrs.h> 47122687Sbms#include <stdlib.h> 48122687Sbms#include <string.h> 49122687Sbms#include "un-namespace.h" 50122687Sbms 51122687Sbms#define SALIGN (sizeof(long) - 1) 52122687Sbms#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \ 53122687Sbms (SALIGN + 1)) 54122687Sbms#define MAX_SYSCTL_TRY 5 55122687Sbms#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) 56122687Sbms 57122687Sbmsint 58122687Sbmsgetifmaddrs(struct ifmaddrs **pif) 59122687Sbms{ 60122687Sbms int icnt = 1; 61122687Sbms int dcnt = 0; 62122687Sbms int ntry = 0; 63122687Sbms size_t len; 64122687Sbms size_t needed; 65122687Sbms int mib[6]; 66122687Sbms int i; 67122687Sbms char *buf; 68122687Sbms char *data; 69122687Sbms char *next; 70122687Sbms char *p; 71122687Sbms struct ifma_msghdr *ifmam; 72122687Sbms struct ifmaddrs *ifa, *ift; 73122687Sbms struct rt_msghdr *rtm; 74122687Sbms struct sockaddr *sa; 75122687Sbms 76122687Sbms mib[0] = CTL_NET; 77122687Sbms mib[1] = PF_ROUTE; 78122687Sbms mib[2] = 0; /* protocol */ 79122687Sbms mib[3] = 0; /* wildcard address family */ 80122687Sbms mib[4] = NET_RT_IFMALIST; 81122687Sbms mib[5] = 0; /* no flags */ 82122687Sbms do { 83122687Sbms if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) 84122687Sbms return (-1); 85122687Sbms if ((buf = malloc(needed)) == NULL) 86122687Sbms return (-1); 87122687Sbms if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { 88122687Sbms if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { 89122687Sbms free(buf); 90122687Sbms return (-1); 91122687Sbms } 92122687Sbms free(buf); 93122687Sbms buf = NULL; 94122687Sbms } 95122687Sbms } while (buf == NULL); 96122687Sbms 97122687Sbms for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 98122687Sbms rtm = (struct rt_msghdr *)(void *)next; 99122687Sbms if (rtm->rtm_version != RTM_VERSION) 100122687Sbms continue; 101122687Sbms switch (rtm->rtm_type) { 102122687Sbms case RTM_NEWMADDR: 103122687Sbms ifmam = (struct ifma_msghdr *)(void *)rtm; 104122687Sbms if ((ifmam->ifmam_addrs & RTA_IFA) == 0) 105122687Sbms break; 106122687Sbms icnt++; 107122687Sbms p = (char *)(ifmam + 1); 108122687Sbms for (i = 0; i < RTAX_MAX; i++) { 109122687Sbms if ((RTA_MASKS & ifmam->ifmam_addrs & 110122687Sbms (1 << i)) == 0) 111122687Sbms continue; 112122687Sbms sa = (struct sockaddr *)(void *)p; 113122687Sbms len = SA_RLEN(sa); 114122687Sbms dcnt += len; 115122687Sbms p += len; 116122687Sbms } 117122687Sbms break; 118122687Sbms } 119122687Sbms } 120122687Sbms 121122687Sbms data = malloc(sizeof(struct ifmaddrs) * icnt + dcnt); 122122687Sbms if (data == NULL) { 123122687Sbms free(buf); 124122687Sbms return (-1); 125122687Sbms } 126122687Sbms 127122687Sbms ifa = (struct ifmaddrs *)(void *)data; 128122687Sbms data += sizeof(struct ifmaddrs) * icnt; 129122687Sbms 130122687Sbms memset(ifa, 0, sizeof(struct ifmaddrs) * icnt); 131122687Sbms ift = ifa; 132122687Sbms 133122687Sbms for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { 134122687Sbms rtm = (struct rt_msghdr *)(void *)next; 135122687Sbms if (rtm->rtm_version != RTM_VERSION) 136122687Sbms continue; 137122687Sbms 138122687Sbms switch (rtm->rtm_type) { 139122687Sbms case RTM_NEWMADDR: 140122687Sbms ifmam = (struct ifma_msghdr *)(void *)rtm; 141122687Sbms if ((ifmam->ifmam_addrs & RTA_IFA) == 0) 142122687Sbms break; 143122687Sbms 144122687Sbms p = (char *)(ifmam + 1); 145122687Sbms for (i = 0; i < RTAX_MAX; i++) { 146122687Sbms if ((RTA_MASKS & ifmam->ifmam_addrs & 147122687Sbms (1 << i)) == 0) 148122687Sbms continue; 149122687Sbms sa = (struct sockaddr *)(void *)p; 150122687Sbms len = SA_RLEN(sa); 151122687Sbms switch (i) { 152122687Sbms case RTAX_GATEWAY: 153122687Sbms ift->ifma_lladdr = 154122687Sbms (struct sockaddr *)(void *)data; 155122687Sbms memcpy(data, p, len); 156122687Sbms data += len; 157122687Sbms break; 158122687Sbms 159122687Sbms case RTAX_IFP: 160122687Sbms ift->ifma_name = 161122687Sbms (struct sockaddr *)(void *)data; 162122687Sbms memcpy(data, p, len); 163122687Sbms data += len; 164122687Sbms break; 165122687Sbms 166122687Sbms case RTAX_IFA: 167122687Sbms ift->ifma_addr = 168122687Sbms (struct sockaddr *)(void *)data; 169122687Sbms memcpy(data, p, len); 170122687Sbms data += len; 171122687Sbms break; 172122687Sbms 173122687Sbms default: 174122687Sbms data += len; 175122687Sbms break; 176122687Sbms } 177122687Sbms p += len; 178122687Sbms } 179122687Sbms ift->ifma_next = ift + 1; 180122687Sbms ift = ift->ifma_next; 181122687Sbms break; 182122687Sbms } 183122687Sbms } 184122687Sbms 185122687Sbms free(buf); 186122687Sbms 187122687Sbms if (ift > ifa) { 188122687Sbms ift--; 189122687Sbms ift->ifma_next = NULL; 190122687Sbms *pif = ifa; 191122687Sbms } else { 192122687Sbms *pif = NULL; 193122687Sbms free(ifa); 194122687Sbms } 195122687Sbms return (0); 196122687Sbms} 197122687Sbms 198122687Sbmsvoid 199122687Sbmsfreeifmaddrs(struct ifmaddrs *ifmp) 200122687Sbms{ 201122687Sbms 202122687Sbms free(ifmp); 203122687Sbms} 204