xref: /freebsd/usr.sbin/ppp/iface.c (revision 2ab5515001905576d4f9642691ae99d3ef672fc7)
18fa6ebe4SBrian Somers /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
48fa6ebe4SBrian Somers  * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
58fa6ebe4SBrian Somers  * All rights reserved.
68fa6ebe4SBrian Somers  *
78fa6ebe4SBrian Somers  * Redistribution and use in source and binary forms, with or without
88fa6ebe4SBrian Somers  * modification, are permitted provided that the following conditions
98fa6ebe4SBrian Somers  * are met:
108fa6ebe4SBrian Somers  * 1. Redistributions of source code must retain the above copyright
118fa6ebe4SBrian Somers  *    notice, this list of conditions and the following disclaimer.
128fa6ebe4SBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
138fa6ebe4SBrian Somers  *    notice, this list of conditions and the following disclaimer in the
148fa6ebe4SBrian Somers  *    documentation and/or other materials provided with the distribution.
158fa6ebe4SBrian Somers  *
168fa6ebe4SBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
178fa6ebe4SBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
188fa6ebe4SBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
198fa6ebe4SBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
208fa6ebe4SBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
218fa6ebe4SBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
228fa6ebe4SBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
238fa6ebe4SBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
248fa6ebe4SBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
258fa6ebe4SBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
268fa6ebe4SBrian Somers  * SUCH DAMAGE.
278fa6ebe4SBrian Somers  */
288fa6ebe4SBrian Somers 
29972a1bcfSBrian Somers #include <sys/param.h>
308fa6ebe4SBrian Somers #include <sys/socket.h>
318fa6ebe4SBrian Somers #include <netinet/in.h>
328fa6ebe4SBrian Somers #include <net/if.h>
338fa6ebe4SBrian Somers #include <net/if_dl.h>
348fa6ebe4SBrian Somers #include <net/route.h>
358fa6ebe4SBrian Somers #include <netinet/in_systm.h>
3630949fd4SBrian Somers #include <netinet/in_var.h>
378fa6ebe4SBrian Somers #include <netinet/ip.h>
3830949fd4SBrian Somers #ifndef NOINET6
3930949fd4SBrian Somers #include <netinet6/nd6.h>
4030949fd4SBrian Somers #endif
418fa6ebe4SBrian Somers #include <sys/un.h>
428fa6ebe4SBrian Somers 
43119386a3SBrian Somers #include <errno.h>
448fa6ebe4SBrian Somers #include <string.h>
456eafd353SBrian Somers #include <stdarg.h>
468fa6ebe4SBrian Somers #include <stdio.h>
478fa6ebe4SBrian Somers #include <stdlib.h>
48119386a3SBrian Somers #include <sys/ioctl.h>
49119386a3SBrian Somers #include <sys/sysctl.h>
508fa6ebe4SBrian Somers #include <termios.h>
518fa6ebe4SBrian Somers #include <unistd.h>
528fa6ebe4SBrian Somers 
535d9e6103SBrian Somers #include "layer.h"
548fa6ebe4SBrian Somers #include "defs.h"
558fa6ebe4SBrian Somers #include "command.h"
568fa6ebe4SBrian Somers #include "mbuf.h"
578fa6ebe4SBrian Somers #include "log.h"
588fa6ebe4SBrian Somers #include "id.h"
598fa6ebe4SBrian Somers #include "timer.h"
608fa6ebe4SBrian Somers #include "fsm.h"
618fa6ebe4SBrian Somers #include "iplist.h"
628fa6ebe4SBrian Somers #include "lqr.h"
638fa6ebe4SBrian Somers #include "hdlc.h"
648fa6ebe4SBrian Somers #include "throughput.h"
658fa6ebe4SBrian Somers #include "slcompress.h"
668fa6ebe4SBrian Somers #include "descriptor.h"
6730949fd4SBrian Somers #include "ncpaddr.h"
688fa6ebe4SBrian Somers #include "ipcp.h"
691d1fc017SBrian Somers #include "filter.h"
708fa6ebe4SBrian Somers #include "lcp.h"
718fa6ebe4SBrian Somers #include "ccp.h"
728fa6ebe4SBrian Somers #include "link.h"
738fa6ebe4SBrian Somers #include "mp.h"
74972a1bcfSBrian Somers #ifndef NORADIUS
75972a1bcfSBrian Somers #include "radius.h"
76972a1bcfSBrian Somers #endif
7730949fd4SBrian Somers #include "ipv6cp.h"
7830949fd4SBrian Somers #include "ncp.h"
798fa6ebe4SBrian Somers #include "bundle.h"
808fa6ebe4SBrian Somers #include "prompt.h"
818fa6ebe4SBrian Somers #include "iface.h"
828fa6ebe4SBrian Somers 
83977e6c08SHajimu UMEMOTO #define IN6MASK128	{{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
84977e6c08SHajimu UMEMOTO 			    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}
85977e6c08SHajimu UMEMOTO static const struct in6_addr in6mask128 = IN6MASK128;
86977e6c08SHajimu UMEMOTO 
878fa6ebe4SBrian Somers 
888fa6ebe4SBrian Somers struct iface *
iface_Create(const char * name)898fa6ebe4SBrian Somers iface_Create(const char *name)
908fa6ebe4SBrian Somers {
9130949fd4SBrian Somers   int mib[6], maxtries, err;
9258a57513SBrian Somers   size_t needed, namelen;
936b457978SBrian Somers   char *buf, *ptr, *end;
948fa6ebe4SBrian Somers   struct if_msghdr *ifm;
958fa6ebe4SBrian Somers   struct ifa_msghdr *ifam;
968fa6ebe4SBrian Somers   struct sockaddr_dl *dl;
976b457978SBrian Somers   struct sockaddr *sa[RTAX_MAX];
988fa6ebe4SBrian Somers   struct iface *iface;
998fa6ebe4SBrian Somers   struct iface_addr *addr;
1008fa6ebe4SBrian Somers 
1018fa6ebe4SBrian Somers   mib[0] = CTL_NET;
1028fa6ebe4SBrian Somers   mib[1] = PF_ROUTE;
1038fa6ebe4SBrian Somers   mib[2] = 0;
1048fa6ebe4SBrian Somers   mib[3] = 0;
1058fa6ebe4SBrian Somers   mib[4] = NET_RT_IFLIST;
1068fa6ebe4SBrian Somers   mib[5] = 0;
1078fa6ebe4SBrian Somers 
108152a4390SBrian Somers   maxtries = 20;
109152a4390SBrian Somers   err = 0;
110152a4390SBrian Somers   do {
111152a4390SBrian Somers     if (maxtries-- == 0 || (err && err != ENOMEM)) {
112152a4390SBrian Somers       fprintf(stderr, "iface_Create: sysctl: %s\n", strerror(err));
113152a4390SBrian Somers       return NULL;
114152a4390SBrian Somers     }
115152a4390SBrian Somers 
1168fa6ebe4SBrian Somers     if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
117c0593e34SBrian Somers       fprintf(stderr, "iface_Create: sysctl: estimate: %s\n",
1188fa6ebe4SBrian Somers                 strerror(errno));
1198fa6ebe4SBrian Somers       return NULL;
1208fa6ebe4SBrian Somers     }
1218fa6ebe4SBrian Somers 
1228fa6ebe4SBrian Somers     if ((buf = (char *)malloc(needed)) == NULL) {
123c0593e34SBrian Somers       fprintf(stderr, "iface_Create: malloc failed: %s\n", strerror(errno));
1248fa6ebe4SBrian Somers       return NULL;
1258fa6ebe4SBrian Somers     }
1268fa6ebe4SBrian Somers 
1278fa6ebe4SBrian Somers     if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
128152a4390SBrian Somers       err = errno;
1298fa6ebe4SBrian Somers       free(buf);
130152a4390SBrian Somers       buf = NULL;
1318fa6ebe4SBrian Somers     }
132152a4390SBrian Somers   } while (buf == NULL);
1338fa6ebe4SBrian Somers 
1348fa6ebe4SBrian Somers   ptr = buf;
1358fa6ebe4SBrian Somers   end = buf + needed;
1368fa6ebe4SBrian Somers   iface = NULL;
13758a57513SBrian Somers   namelen = strlen(name);
1388fa6ebe4SBrian Somers 
1398fa6ebe4SBrian Somers   while (ptr < end && iface == NULL) {
1408fa6ebe4SBrian Somers     ifm = (struct if_msghdr *)ptr;			/* On if_msghdr */
1418fa6ebe4SBrian Somers     if (ifm->ifm_type != RTM_IFINFO)
1428fa6ebe4SBrian Somers       break;
1438fa6ebe4SBrian Somers     dl = (struct sockaddr_dl *)(ifm + 1);		/* Single _dl at end */
14458a57513SBrian Somers     if (dl->sdl_nlen == namelen && !strncmp(name, dl->sdl_data, namelen)) {
1458fa6ebe4SBrian Somers       iface = (struct iface *)malloc(sizeof *iface);
1468fa6ebe4SBrian Somers       if (iface == NULL) {
1478fa6ebe4SBrian Somers         fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno));
148ba01ab64SStephen J. Kiernan 	free(buf);
1498fa6ebe4SBrian Somers         return NULL;
1508fa6ebe4SBrian Somers       }
1518fa6ebe4SBrian Somers       iface->name = strdup(name);
152f2f5156fSBrian Somers       iface->descr = NULL;
1538fa6ebe4SBrian Somers       iface->index = ifm->ifm_index;
154c8b9fb53SBrian Somers       iface->flags = ifm->ifm_flags;
155c8b9fb53SBrian Somers       iface->mtu = 0;
15630949fd4SBrian Somers       iface->addrs = 0;
15730949fd4SBrian Somers       iface->addr = NULL;
1588fa6ebe4SBrian Somers     }
1598fa6ebe4SBrian Somers     ptr += ifm->ifm_msglen;				/* First ifa_msghdr */
1608fa6ebe4SBrian Somers     for (; ptr < end; ptr += ifam->ifam_msglen) {
1618fa6ebe4SBrian Somers       ifam = (struct ifa_msghdr *)ptr;			/* Next if address */
1628fa6ebe4SBrian Somers 
1638fa6ebe4SBrian Somers       if (ifam->ifam_type != RTM_NEWADDR)		/* finished this if */
1648fa6ebe4SBrian Somers         break;
1658fa6ebe4SBrian Somers 
1666b457978SBrian Somers       if (iface != NULL && ifam->ifam_addrs & RTA_IFA) {
1676b457978SBrian Somers         /* Found a configured interface ! */
1686b457978SBrian Somers         iface_ParseHdr(ifam, sa);
1698fa6ebe4SBrian Somers 
17030949fd4SBrian Somers         if (sa[RTAX_IFA] && (sa[RTAX_IFA]->sa_family == AF_INET
17130949fd4SBrian Somers #ifndef NOINET6
17230949fd4SBrian Somers                              || sa[RTAX_IFA]->sa_family == AF_INET6
17330949fd4SBrian Somers #endif
17430949fd4SBrian Somers                              )) {
1756b457978SBrian Somers           /* Record the address */
1768fa6ebe4SBrian Somers 
17730949fd4SBrian Somers           addr = (struct iface_addr *)
17830949fd4SBrian Somers             realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
1798fa6ebe4SBrian Somers           if (addr == NULL)
1808fa6ebe4SBrian Somers             break;
18130949fd4SBrian Somers           iface->addr = addr;
1828fa6ebe4SBrian Somers 
18330949fd4SBrian Somers           addr += iface->addrs;
18430949fd4SBrian Somers           iface->addrs++;
1858fa6ebe4SBrian Somers 
18630949fd4SBrian Somers           ncprange_setsa(&addr->ifa, sa[RTAX_IFA], sa[RTAX_NETMASK]);
1876b457978SBrian Somers           if (sa[RTAX_BRD])
18830949fd4SBrian Somers             ncpaddr_setsa(&addr->peer, sa[RTAX_BRD]);
1896b457978SBrian Somers           else
19030949fd4SBrian Somers             ncpaddr_init(&addr->peer);
1918fa6ebe4SBrian Somers         }
1928fa6ebe4SBrian Somers       }
1938fa6ebe4SBrian Somers     }
1948fa6ebe4SBrian Somers   }
1958fa6ebe4SBrian Somers 
1968fa6ebe4SBrian Somers   free(buf);
1978fa6ebe4SBrian Somers 
1988fa6ebe4SBrian Somers   return iface;
1998fa6ebe4SBrian Somers }
2008fa6ebe4SBrian Somers 
20130949fd4SBrian Somers static int
iface_addr_Zap(const char * name,struct iface_addr * addr,int s)20230949fd4SBrian Somers iface_addr_Zap(const char *name, struct iface_addr *addr, int s)
2038fa6ebe4SBrian Somers {
204*2ab55150SKonrad Witaszczyk   struct ifreq ifr;
20530949fd4SBrian Somers #ifndef NOINET6
206*2ab55150SKonrad Witaszczyk   struct in6_ifreq ifr6;
20730949fd4SBrian Somers #endif
208*2ab55150SKonrad Witaszczyk   struct sockaddr_in *me4;
209*2ab55150SKonrad Witaszczyk   struct sockaddr_storage ssme;
2106cd3353bSEugene Grosbein   int res, saved_errno;
2118fa6ebe4SBrian Somers 
212*2ab55150SKonrad Witaszczyk   ncprange_getsa(&addr->ifa, &ssme, NULL);
21330949fd4SBrian Somers   res = 0;
21430949fd4SBrian Somers 
21530949fd4SBrian Somers   switch (ncprange_family(&addr->ifa)) {
21630949fd4SBrian Somers   case AF_INET:
217*2ab55150SKonrad Witaszczyk     memset(&ifr, '\0', sizeof ifr);
218*2ab55150SKonrad Witaszczyk     strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name - 1);
219*2ab55150SKonrad Witaszczyk     me4 = (struct sockaddr_in *)&ifr.ifr_addr;
22030949fd4SBrian Somers     memcpy(me4, &ssme, sizeof *me4);
22130949fd4SBrian Somers 
222*2ab55150SKonrad Witaszczyk     res = ID0ioctl(s, SIOCDIFADDR, &ifr);
2236cd3353bSEugene Grosbein     saved_errno = errno;
2242ea80d6dSBrian Somers     if (log_IsKept(LogDEBUG)) {
2256cd3353bSEugene Grosbein       char buf[NCP_ASCIIBUFFERSIZE];
2262ea80d6dSBrian Somers 
2272ea80d6dSBrian Somers       snprintf(buf, sizeof buf, "%s", ncprange_ntoa(&addr->ifa));
2282ea80d6dSBrian Somers       log_Printf(LogWARN, "%s: DIFADDR %s -> %s returns %d\n",
229*2ab55150SKonrad Witaszczyk                  ifr.ifr_name, buf, ncpaddr_ntoa(&addr->peer), res);
2302ea80d6dSBrian Somers     }
23130949fd4SBrian Somers     break;
23230949fd4SBrian Somers 
23330949fd4SBrian Somers #ifndef NOINET6
23430949fd4SBrian Somers   case AF_INET6:
235*2ab55150SKonrad Witaszczyk     memset(&ifr6, '\0', sizeof ifr6);
236*2ab55150SKonrad Witaszczyk     strncpy(ifr6.ifr_name, name, sizeof ifr6.ifr_name - 1);
237*2ab55150SKonrad Witaszczyk     memcpy(&ifr6.ifr_addr, &ssme, sizeof ifr6.ifr_addr);
23830949fd4SBrian Somers 
239*2ab55150SKonrad Witaszczyk     res = ID0ioctl(s, SIOCDIFADDR_IN6, &ifr6);
2406cd3353bSEugene Grosbein     saved_errno = errno;
24130949fd4SBrian Somers     break;
24230949fd4SBrian Somers #endif
24330949fd4SBrian Somers   }
24430949fd4SBrian Somers 
24530949fd4SBrian Somers   if (res == -1) {
2466cd3353bSEugene Grosbein     char dst[NCP_ASCIIBUFFERSIZE];
24730949fd4SBrian Somers     const char *end =
24830949fd4SBrian Somers #ifndef NOINET6
24930949fd4SBrian Somers       ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
25030949fd4SBrian Somers #endif
25130949fd4SBrian Somers       "";
25230949fd4SBrian Somers 
25330949fd4SBrian Somers     if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
25430949fd4SBrian Somers       log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s): %s\n",
2556cd3353bSEugene Grosbein                  end, ncprange_ntoa(&addr->ifa), strerror(saved_errno));
25630949fd4SBrian Somers     else {
25730949fd4SBrian Somers       snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
25830949fd4SBrian Somers       log_Printf(LogWARN, "iface rm: ioctl(SIOCDIFADDR%s, %s -> %s): %s\n",
2596cd3353bSEugene Grosbein                  end, ncprange_ntoa(&addr->ifa), dst, strerror(saved_errno));
2608fa6ebe4SBrian Somers     }
2618fa6ebe4SBrian Somers   }
2628fa6ebe4SBrian Somers 
26330949fd4SBrian Somers   return res != -1;
26430949fd4SBrian Somers }
26530949fd4SBrian Somers 
266add3c041SBrian Somers static int
iface_addr_Add(const char * name,struct iface_addr * addr,int s)26730949fd4SBrian Somers iface_addr_Add(const char *name, struct iface_addr *addr, int s)
26830949fd4SBrian Somers {
26930949fd4SBrian Somers   struct ifaliasreq ifra;
27030949fd4SBrian Somers #ifndef NOINET6
27130949fd4SBrian Somers   struct in6_aliasreq ifra6;
27230949fd4SBrian Somers #endif
27330949fd4SBrian Somers   struct sockaddr_in *me4, *msk4, *peer4;
27430949fd4SBrian Somers   struct sockaddr_storage ssme, sspeer, ssmsk;
2756cd3353bSEugene Grosbein   int res, saved_errno;
27630949fd4SBrian Somers 
27730949fd4SBrian Somers   ncprange_getsa(&addr->ifa, &ssme, &ssmsk);
27830949fd4SBrian Somers   ncpaddr_getsa(&addr->peer, &sspeer);
27930949fd4SBrian Somers   res = 0;
28030949fd4SBrian Somers 
28130949fd4SBrian Somers   switch (ncprange_family(&addr->ifa)) {
28230949fd4SBrian Somers   case AF_INET:
28330949fd4SBrian Somers     memset(&ifra, '\0', sizeof ifra);
28430949fd4SBrian Somers     strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
28530949fd4SBrian Somers 
28630949fd4SBrian Somers     me4 = (struct sockaddr_in *)&ifra.ifra_addr;
28730949fd4SBrian Somers     memcpy(me4, &ssme, sizeof *me4);
28830949fd4SBrian Somers 
28930949fd4SBrian Somers     msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
29030949fd4SBrian Somers     memcpy(msk4, &ssmsk, sizeof *msk4);
29130949fd4SBrian Somers 
29230949fd4SBrian Somers     peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
29330949fd4SBrian Somers     if (ncpaddr_family(&addr->peer) == AF_UNSPEC) {
29430949fd4SBrian Somers       peer4->sin_family = AF_INET;
29530949fd4SBrian Somers       peer4->sin_len = sizeof(*peer4);
29630949fd4SBrian Somers       peer4->sin_addr.s_addr = INADDR_NONE;
29730949fd4SBrian Somers     } else
29830949fd4SBrian Somers       memcpy(peer4, &sspeer, sizeof *peer4);
29930949fd4SBrian Somers 
30030949fd4SBrian Somers     res = ID0ioctl(s, SIOCAIFADDR, &ifra);
3016cd3353bSEugene Grosbein     saved_errno = errno;
3022ea80d6dSBrian Somers     if (log_IsKept(LogDEBUG)) {
3036cd3353bSEugene Grosbein       char buf[NCP_ASCIIBUFFERSIZE];
3042ea80d6dSBrian Somers 
3052ea80d6dSBrian Somers       snprintf(buf, sizeof buf, "%s", ncprange_ntoa(&addr->ifa));
3062ea80d6dSBrian Somers       log_Printf(LogWARN, "%s: AIFADDR %s -> %s returns %d\n",
3072ea80d6dSBrian Somers                  ifra.ifra_name, buf, ncpaddr_ntoa(&addr->peer), res);
3082ea80d6dSBrian Somers     }
30930949fd4SBrian Somers     break;
31030949fd4SBrian Somers 
31130949fd4SBrian Somers #ifndef NOINET6
31230949fd4SBrian Somers   case AF_INET6:
31330949fd4SBrian Somers     memset(&ifra6, '\0', sizeof ifra6);
31430949fd4SBrian Somers     strncpy(ifra6.ifra_name, name, sizeof ifra6.ifra_name - 1);
31530949fd4SBrian Somers 
31630949fd4SBrian Somers     memcpy(&ifra6.ifra_addr, &ssme, sizeof ifra6.ifra_addr);
31730949fd4SBrian Somers     memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof ifra6.ifra_prefixmask);
31830949fd4SBrian Somers     if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
31930949fd4SBrian Somers       ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
320977e6c08SHajimu UMEMOTO     else if (memcmp(&((struct sockaddr_in6 *)&ssmsk)->sin6_addr, &in6mask128,
321977e6c08SHajimu UMEMOTO 		    sizeof in6mask128) == 0)
32230949fd4SBrian Somers       memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof ifra6.ifra_dstaddr);
32330949fd4SBrian Somers     ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
32430949fd4SBrian Somers     ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
32530949fd4SBrian Somers 
32630949fd4SBrian Somers     res = ID0ioctl(s, SIOCAIFADDR_IN6, &ifra6);
3276cd3353bSEugene Grosbein     saved_errno = errno;
32830949fd4SBrian Somers     break;
32930949fd4SBrian Somers #endif
33030949fd4SBrian Somers   }
33130949fd4SBrian Somers 
33230949fd4SBrian Somers   if (res == -1) {
3336cd3353bSEugene Grosbein     char dst[NCP_ASCIIBUFFERSIZE];
33430949fd4SBrian Somers     const char *end =
33530949fd4SBrian Somers #ifndef NOINET6
33630949fd4SBrian Somers       ncprange_family(&addr->ifa) == AF_INET6 ? "_IN6" :
33730949fd4SBrian Somers #endif
33830949fd4SBrian Somers       "";
33930949fd4SBrian Somers 
34030949fd4SBrian Somers     if (ncpaddr_family(&addr->peer) == AF_UNSPEC)
34130949fd4SBrian Somers       log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s): %s\n",
3426cd3353bSEugene Grosbein                  end, ncprange_ntoa(&addr->ifa), strerror(saved_errno));
34330949fd4SBrian Somers     else {
34430949fd4SBrian Somers       snprintf(dst, sizeof dst, "%s", ncpaddr_ntoa(&addr->peer));
34546df5aa7SBrian Somers       log_Printf(LogWARN, "iface add: ioctl(SIOCAIFADDR%s, %s -> %s): %s\n",
3466cd3353bSEugene Grosbein                  end, ncprange_ntoa(&addr->ifa), dst, strerror(saved_errno));
34730949fd4SBrian Somers     }
34830949fd4SBrian Somers   }
349add3c041SBrian Somers 
350add3c041SBrian Somers   return res != -1;
35130949fd4SBrian Somers }
35230949fd4SBrian Somers 
353f2f5156fSBrian Somers int
iface_Name(struct iface * iface,const char * name)354f2f5156fSBrian Somers iface_Name(struct iface *iface, const char *name)
355f2f5156fSBrian Somers {
356f2f5156fSBrian Somers   struct ifreq ifr;
357f2f5156fSBrian Somers   int s;
358f2f5156fSBrian Somers   char *newname;
359f2f5156fSBrian Somers 
360f2f5156fSBrian Somers   if ((newname = strdup(name)) == NULL) {
361f2f5156fSBrian Somers     log_Printf(LogWARN, "iface name: strdup failed: %s\n", strerror(errno));
362f2f5156fSBrian Somers     return 0;
363f2f5156fSBrian Somers   }
364f2f5156fSBrian Somers 
365f2f5156fSBrian Somers   if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
366f2f5156fSBrian Somers     log_Printf(LogERROR, "iface name: socket(): %s\n", strerror(errno));
367f2f5156fSBrian Somers     free(newname);
368f2f5156fSBrian Somers     return 0;
369f2f5156fSBrian Somers   }
370f2f5156fSBrian Somers 
371f2f5156fSBrian Somers   strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
372f2f5156fSBrian Somers   ifr.ifr_data = newname;
373f2f5156fSBrian Somers   if (ID0ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
374f2f5156fSBrian Somers     log_Printf(LogWARN, "iface name: ioctl(SIOCSIFNAME, %s -> %s): %s\n",
375f2f5156fSBrian Somers                name, newname, strerror(errno));
376f2f5156fSBrian Somers     free(newname);
377f2f5156fSBrian Somers     return 0;
378f2f5156fSBrian Somers   }
379f2f5156fSBrian Somers 
380f2f5156fSBrian Somers   free(iface->name);
381f2f5156fSBrian Somers   iface->name = newname;
382f2f5156fSBrian Somers 
383f2f5156fSBrian Somers   return 1;
384f2f5156fSBrian Somers }
385f2f5156fSBrian Somers 
386f2f5156fSBrian Somers int
iface_Descr(struct cmdargs const * arg)387f2f5156fSBrian Somers iface_Descr(struct cmdargs const *arg)
388f2f5156fSBrian Somers {
389f2f5156fSBrian Somers   struct ifreq ifr;
390f2f5156fSBrian Somers   struct iface *iface;
391f2f5156fSBrian Somers   size_t sz, len;
392f2f5156fSBrian Somers   int s, n, ifdescr_maxlen;
393f2f5156fSBrian Somers   char *descr;
394f2f5156fSBrian Somers 
395f2f5156fSBrian Somers   sz = sizeof(int);
396f2f5156fSBrian Somers   if (sysctlbyname("net.ifdescr_maxlen", &ifdescr_maxlen, &sz, NULL, 0) < 0) {
397f2f5156fSBrian Somers     log_Printf(LogERROR, "iface descr: sysctl failed: %s\n", strerror(errno));
398f2f5156fSBrian Somers     return 1;
399f2f5156fSBrian Somers   }
400f2f5156fSBrian Somers 
401f2f5156fSBrian Somers   if (ifdescr_maxlen < 1) {
402f2f5156fSBrian Somers     log_Printf(LogERROR, "iface descr: sysctl net.ifdescr_maxlen < 1\n");
403f2f5156fSBrian Somers     return 1;
404f2f5156fSBrian Somers   }
405f2f5156fSBrian Somers 
406f2f5156fSBrian Somers   sz = sizeof(char) * ifdescr_maxlen;
407f2f5156fSBrian Somers   if ((descr = malloc(sz)) == NULL) {
408f2f5156fSBrian Somers     log_Printf(LogERROR, "iface descr: malloc failed: %s\n", strerror(errno));
409f2f5156fSBrian Somers     return 1;
410f2f5156fSBrian Somers   }
411f2f5156fSBrian Somers 
412f2f5156fSBrian Somers   *descr = '\0';
413f2f5156fSBrian Somers   n = arg->argn;
414f2f5156fSBrian Somers   while (n < arg->argc) {
415f2f5156fSBrian Somers     if (n > arg->argn && (len = strlcat(descr, " ", sz)) >= sz)
416f2f5156fSBrian Somers       break;
417f2f5156fSBrian Somers     if ((len = strlcat(descr, arg->argv[n], sz)) >= sz)
418f2f5156fSBrian Somers       break;
419f2f5156fSBrian Somers     ++n;
420f2f5156fSBrian Somers   }
421f2f5156fSBrian Somers   if (len >= sz) {
422f2f5156fSBrian Somers     log_Printf(LogERROR, "iface descr: description exceeds maximum (%d)\n",
423f2f5156fSBrian Somers                ifdescr_maxlen-1);
424f2f5156fSBrian Somers     free(descr);
425f2f5156fSBrian Somers     return 1;
426f2f5156fSBrian Somers   }
427f2f5156fSBrian Somers 
428f2f5156fSBrian Somers   if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
429f2f5156fSBrian Somers     log_Printf(LogERROR, "iface descr: socket(): %s\n", strerror(errno));
430f2f5156fSBrian Somers     free(descr);
431f2f5156fSBrian Somers     return 1;
432f2f5156fSBrian Somers   }
433f2f5156fSBrian Somers 
434f2f5156fSBrian Somers   iface = arg->bundle->iface;
435f2f5156fSBrian Somers   strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
436f2f5156fSBrian Somers   ifr.ifr_buffer.length = strlen(descr) + 1;
437f2f5156fSBrian Somers   ifr.ifr_buffer.buffer = descr;
438f2f5156fSBrian Somers   if (ID0ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) {
439f2f5156fSBrian Somers     log_Printf(LogWARN, "iface descr: ioctl(SIOCSIFDESCR, %s): %s\n",
440f2f5156fSBrian Somers                descr, strerror(errno));
441f2f5156fSBrian Somers     free(descr);
442f2f5156fSBrian Somers     return 1;
443f2f5156fSBrian Somers   }
444f2f5156fSBrian Somers 
445f2f5156fSBrian Somers   free(iface->descr);
446f2f5156fSBrian Somers   iface->descr = descr;
447f2f5156fSBrian Somers 
448f2f5156fSBrian Somers   return 0;
449f2f5156fSBrian Somers }
45030949fd4SBrian Somers 
4518fa6ebe4SBrian Somers void
iface_Clear(struct iface * iface,struct ncp * ncp,int family,int how)45230949fd4SBrian Somers iface_Clear(struct iface *iface, struct ncp *ncp, int family, int how)
4538fa6ebe4SBrian Somers {
4547268c7daSEitan Adler   int af, inskip, in6skip, s4 = -1, s6 = -1, *s;
455057f1760SBrian Somers   unsigned n;
4568fa6ebe4SBrian Somers 
45730949fd4SBrian Somers   if (iface->addrs) {
45830949fd4SBrian Somers     inskip = in6skip = how == IFACE_CLEAR_ALL ? 0 : 1;
4598fa6ebe4SBrian Somers 
46030949fd4SBrian Somers     for (n = 0; n < iface->addrs; n++) {
46130949fd4SBrian Somers       af = ncprange_family(&iface->addr[n].ifa);
46230949fd4SBrian Somers       if (family == 0 || family == af) {
46330949fd4SBrian Somers         if (!iface->addr[n].system && (how & IFACE_SYSTEM))
46430949fd4SBrian Somers           continue;
46530949fd4SBrian Somers         switch (af) {
46630949fd4SBrian Somers         case AF_INET:
46730949fd4SBrian Somers           if (inskip) {
46830949fd4SBrian Somers             inskip = 0;
46930949fd4SBrian Somers             continue;
47030949fd4SBrian Somers           }
47130949fd4SBrian Somers           s = &s4;
47230949fd4SBrian Somers           break;
47330949fd4SBrian Somers 
47430949fd4SBrian Somers #ifndef NOINET6
47530949fd4SBrian Somers         case AF_INET6:
47630949fd4SBrian Somers           if (in6skip) {
47730949fd4SBrian Somers             in6skip = 0;
47830949fd4SBrian Somers             continue;
47930949fd4SBrian Somers           }
48030949fd4SBrian Somers           s = &s6;
48130949fd4SBrian Somers           break;
48230949fd4SBrian Somers #endif
483856cf687SBrian Somers         default:
484856cf687SBrian Somers           continue;
48530949fd4SBrian Somers         }
48630949fd4SBrian Somers 
48730949fd4SBrian Somers         if (*s == -1 && (*s = ID0socket(af, SOCK_DGRAM, 0)) == -1)
48830949fd4SBrian Somers           log_Printf(LogERROR, "iface_Clear: socket(): %s\n", strerror(errno));
48930949fd4SBrian Somers         else if (iface_addr_Zap(iface->name, iface->addr + n, *s)) {
49030949fd4SBrian Somers           ncp_IfaceAddrDeleted(ncp, iface->addr + n);
49130949fd4SBrian Somers           bcopy(iface->addr + n + 1, iface->addr + n,
49230949fd4SBrian Somers                 (iface->addrs - n - 1) * sizeof *iface->addr);
49330949fd4SBrian Somers           iface->addrs--;
49430949fd4SBrian Somers           n--;
49530949fd4SBrian Somers         }
49630949fd4SBrian Somers       }
49730949fd4SBrian Somers     }
49830949fd4SBrian Somers 
4998fa6ebe4SBrian Somers     /* Don't bother realloc()ing - we have little to gain */
50030949fd4SBrian Somers 
50130949fd4SBrian Somers     if (s4)
50230949fd4SBrian Somers       close(s4);
50330949fd4SBrian Somers     if (s6)
50430949fd4SBrian Somers       close(s6);
5058fa6ebe4SBrian Somers   }
506278657c3SBrian Somers }
5078fa6ebe4SBrian Somers 
5088fa6ebe4SBrian Somers int
iface_Add(struct iface * iface,struct ncp * ncp,const struct ncprange * ifa,const struct ncpaddr * peer,int how)50930949fd4SBrian Somers iface_Add(struct iface *iface, struct ncp *ncp, const struct ncprange *ifa,
51030949fd4SBrian Somers           const struct ncpaddr *peer, int how)
5118fa6ebe4SBrian Somers {
512057f1760SBrian Somers   int af, removed, s;
513057f1760SBrian Somers   unsigned n;
514add3c041SBrian Somers   struct ncpaddr ncplocal;
515add3c041SBrian Somers   struct iface_addr *addr, newaddr;
5168fa6ebe4SBrian Somers 
51730949fd4SBrian Somers   af = ncprange_family(ifa);
51830949fd4SBrian Somers   if ((s = ID0socket(af, SOCK_DGRAM, 0)) == -1) {
51930949fd4SBrian Somers     log_Printf(LogERROR, "iface_Add: socket(): %s\n", strerror(errno));
5208fa6ebe4SBrian Somers     return 0;
5218fa6ebe4SBrian Somers   }
52230949fd4SBrian Somers   ncprange_getaddr(ifa, &ncplocal);
52330949fd4SBrian Somers 
52430949fd4SBrian Somers   for (n = 0; n < iface->addrs; n++) {
52584b0fe81SBrian Somers     if (ncprange_contains(&iface->addr[n].ifa, &ncplocal) ||
52684b0fe81SBrian Somers         ncpaddr_equal(&iface->addr[n].peer, peer)) {
527add3c041SBrian Somers       /* Replace this sockaddr */
52830949fd4SBrian Somers       if (!(how & IFACE_FORCE_ADD)) {
52930949fd4SBrian Somers         close(s);
53030949fd4SBrian Somers         return 0;	/* errno = EEXIST; */
53130949fd4SBrian Somers       }
53230949fd4SBrian Somers 
53330949fd4SBrian Somers       if (ncprange_equal(&iface->addr[n].ifa, ifa) &&
53430949fd4SBrian Somers           ncpaddr_equal(&iface->addr[n].peer, peer)) {
53530949fd4SBrian Somers         close(s);
5361de22c3bSBjoern A. Zeeb         ncp_IfaceAddrAdded(ncp, iface->addr + n);
53730949fd4SBrian Somers         return 1;	/* Already there */
53830949fd4SBrian Somers       }
53930949fd4SBrian Somers 
540add3c041SBrian Somers       removed = iface_addr_Zap(iface->name, iface->addr + n, s);
541add3c041SBrian Somers       if (removed)
542add3c041SBrian Somers         ncp_IfaceAddrDeleted(ncp, iface->addr + n);
543add3c041SBrian Somers       ncprange_copy(&iface->addr[n].ifa, ifa);
54430949fd4SBrian Somers       ncpaddr_copy(&iface->addr[n].peer, peer);
545add3c041SBrian Somers       if (!iface_addr_Add(iface->name, iface->addr + n, s)) {
546add3c041SBrian Somers         if (removed) {
547add3c041SBrian Somers           bcopy(iface->addr + n + 1, iface->addr + n,
548add3c041SBrian Somers                 (iface->addrs - n - 1) * sizeof *iface->addr);
549add3c041SBrian Somers           iface->addrs--;
550add3c041SBrian Somers           n--;
551add3c041SBrian Somers         }
552add3c041SBrian Somers         close(s);
553add3c041SBrian Somers         return 0;
554add3c041SBrian Somers       }
55530949fd4SBrian Somers       close(s);
55630949fd4SBrian Somers       ncp_IfaceAddrAdded(ncp, iface->addr + n);
55730949fd4SBrian Somers       return 1;
55830949fd4SBrian Somers     }
55930949fd4SBrian Somers   }
5608fa6ebe4SBrian Somers 
5618fa6ebe4SBrian Somers   addr = (struct iface_addr *)realloc
56230949fd4SBrian Somers     (iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]);
5638fa6ebe4SBrian Somers   if (addr == NULL) {
5648fa6ebe4SBrian Somers     log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
5658fa6ebe4SBrian Somers     close(s);
5668fa6ebe4SBrian Somers     return 0;
5678fa6ebe4SBrian Somers   }
56830949fd4SBrian Somers   iface->addr = addr;
5698fa6ebe4SBrian Somers 
570add3c041SBrian Somers   ncprange_copy(&newaddr.ifa, ifa);
571add3c041SBrian Somers   ncpaddr_copy(&newaddr.peer, peer);
572add3c041SBrian Somers   newaddr.system = !!(how & IFACE_SYSTEM);
573add3c041SBrian Somers   if (!iface_addr_Add(iface->name, &newaddr, s)) {
574add3c041SBrian Somers     close(s);
575add3c041SBrian Somers     return 0;
576add3c041SBrian Somers   }
577add3c041SBrian Somers 
5788fa6ebe4SBrian Somers   if (how & IFACE_ADD_FIRST) {
5798fa6ebe4SBrian Somers     /* Stuff it at the start of our list */
58030949fd4SBrian Somers     n = 0;
58130949fd4SBrian Somers     bcopy(iface->addr, iface->addr + 1, iface->addrs * sizeof *iface->addr);
58230949fd4SBrian Somers   } else
58330949fd4SBrian Somers     n = iface->addrs;
5848fa6ebe4SBrian Somers 
58530949fd4SBrian Somers   iface->addrs++;
586add3c041SBrian Somers   memcpy(iface->addr + n, &newaddr, sizeof(*iface->addr));
5878fa6ebe4SBrian Somers 
58830949fd4SBrian Somers   close(s);
58930949fd4SBrian Somers   ncp_IfaceAddrAdded(ncp, iface->addr + n);
5908fa6ebe4SBrian Somers 
5918fa6ebe4SBrian Somers   return 1;
5928fa6ebe4SBrian Somers }
5938fa6ebe4SBrian Somers 
5948fa6ebe4SBrian Somers int
iface_Delete(struct iface * iface,struct ncp * ncp,const struct ncpaddr * del)59530949fd4SBrian Somers iface_Delete(struct iface *iface, struct ncp *ncp, const struct ncpaddr *del)
5968fa6ebe4SBrian Somers {
59730949fd4SBrian Somers   struct ncpaddr found;
598057f1760SBrian Somers   unsigned n;
599057f1760SBrian Somers   int res, s;
6008fa6ebe4SBrian Somers 
60130949fd4SBrian Somers   if ((s = ID0socket(ncpaddr_family(del), SOCK_DGRAM, 0)) == -1) {
60230949fd4SBrian Somers     log_Printf(LogERROR, "iface_Delete: socket(): %s\n", strerror(errno));
60330949fd4SBrian Somers     return 0;
6048fa6ebe4SBrian Somers   }
6058fa6ebe4SBrian Somers 
60630949fd4SBrian Somers   for (n = res = 0; n < iface->addrs; n++) {
60730949fd4SBrian Somers     ncprange_getaddr(&iface->addr[n].ifa, &found);
60830949fd4SBrian Somers     if (ncpaddr_equal(&found, del)) {
609add3c041SBrian Somers       if (iface_addr_Zap(iface->name, iface->addr + n, s)) {
61030949fd4SBrian Somers         ncp_IfaceAddrDeleted(ncp, iface->addr + n);
61130949fd4SBrian Somers         bcopy(iface->addr + n + 1, iface->addr + n,
61230949fd4SBrian Somers               (iface->addrs - n - 1) * sizeof *iface->addr);
61330949fd4SBrian Somers         iface->addrs--;
61430949fd4SBrian Somers         res = 1;
615add3c041SBrian Somers       }
61630949fd4SBrian Somers       break;
61730949fd4SBrian Somers     }
61830949fd4SBrian Somers   }
61930949fd4SBrian Somers 
62030949fd4SBrian Somers   close(s);
62130949fd4SBrian Somers 
62230949fd4SBrian Somers   return res;
6238fa6ebe4SBrian Somers }
6248fa6ebe4SBrian Somers 
6254e5196e9SBrian Somers #define IFACE_ADDFLAGS 1
6264e5196e9SBrian Somers #define IFACE_DELFLAGS 2
6274e5196e9SBrian Somers 
6284e5196e9SBrian Somers static int
iface_ChangeFlags(const char * ifname,int flags,int how)629dc744e19SBrian Somers iface_ChangeFlags(const char *ifname, int flags, int how)
6304e5196e9SBrian Somers {
6314e5196e9SBrian Somers   struct ifreq ifrq;
63288202a1fSMaxim Sobolev   int s, new_flags;
6334e5196e9SBrian Somers 
63463c6cac9SBrian Somers   s = ID0socket(PF_INET, SOCK_DGRAM, 0);
6354e5196e9SBrian Somers   if (s < 0) {
63653dc037cSBrian Somers     log_Printf(LogERROR, "iface_ChangeFlags: socket: %s\n", strerror(errno));
6374e5196e9SBrian Somers     return 0;
6384e5196e9SBrian Somers   }
6394e5196e9SBrian Somers 
6404e5196e9SBrian Somers   memset(&ifrq, '\0', sizeof ifrq);
641dc744e19SBrian Somers   strncpy(ifrq.ifr_name, ifname, sizeof ifrq.ifr_name - 1);
6424e5196e9SBrian Somers   ifrq.ifr_name[sizeof ifrq.ifr_name - 1] = '\0';
6434e5196e9SBrian Somers   if (ID0ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
64453dc037cSBrian Somers     log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCGIFFLAGS): %s\n",
6454e5196e9SBrian Somers        strerror(errno));
6464e5196e9SBrian Somers     close(s);
6474e5196e9SBrian Somers     return 0;
6484e5196e9SBrian Somers   }
64950be714bSBrian Somers #ifdef __FreeBSD__
65088202a1fSMaxim Sobolev   new_flags = (ifrq.ifr_flags & 0xffff) | (ifrq.ifr_flagshigh << 16);
65150be714bSBrian Somers #else
65250be714bSBrian Somers   new_flags = ifrq.ifr_flags & 0xffff;
65350be714bSBrian Somers #endif
6544e5196e9SBrian Somers 
6554e5196e9SBrian Somers   if (how == IFACE_ADDFLAGS)
65688202a1fSMaxim Sobolev     new_flags |= flags;
6574e5196e9SBrian Somers   else
65888202a1fSMaxim Sobolev     new_flags &= ~flags;
65988202a1fSMaxim Sobolev   ifrq.ifr_flags = new_flags & 0xffff;
66050be714bSBrian Somers #ifdef __FreeBSD__
66188202a1fSMaxim Sobolev   ifrq.ifr_flagshigh = new_flags >> 16;
66250be714bSBrian Somers #endif
6634e5196e9SBrian Somers 
6644e5196e9SBrian Somers   if (ID0ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
66553dc037cSBrian Somers     log_Printf(LogERROR, "iface_ChangeFlags: ioctl(SIOCSIFFLAGS): %s\n",
6664e5196e9SBrian Somers        strerror(errno));
6674e5196e9SBrian Somers     close(s);
6684e5196e9SBrian Somers     return 0;
6694e5196e9SBrian Somers   }
6704e5196e9SBrian Somers   close(s);
6714e5196e9SBrian Somers 
6724e5196e9SBrian Somers   return 1;	/* Success */
6734e5196e9SBrian Somers }
6744e5196e9SBrian Somers 
6754e5196e9SBrian Somers int
iface_SetFlags(const char * ifname,int flags)676dc744e19SBrian Somers iface_SetFlags(const char *ifname, int flags)
6774e5196e9SBrian Somers {
678dc744e19SBrian Somers   return iface_ChangeFlags(ifname, flags, IFACE_ADDFLAGS);
6794e5196e9SBrian Somers }
6804e5196e9SBrian Somers 
6814e5196e9SBrian Somers int
iface_ClearFlags(const char * ifname,int flags)682dc744e19SBrian Somers iface_ClearFlags(const char *ifname, int flags)
6834e5196e9SBrian Somers {
684dc744e19SBrian Somers   return iface_ChangeFlags(ifname, flags, IFACE_DELFLAGS);
6854e5196e9SBrian Somers }
6864e5196e9SBrian Somers 
6878fa6ebe4SBrian Somers void
iface_Free(struct iface * iface)688f2f5156fSBrian Somers iface_Free(struct iface *iface)
6898fa6ebe4SBrian Somers {
6908fa6ebe4SBrian Somers     free(iface->name);
691f2f5156fSBrian Somers     free(iface->descr);
69230949fd4SBrian Somers     free(iface->addr);
6938fa6ebe4SBrian Somers     free(iface);
6948fa6ebe4SBrian Somers }
695f2f5156fSBrian Somers 
696f2f5156fSBrian Somers void
iface_Destroy(struct iface * iface)697f2f5156fSBrian Somers iface_Destroy(struct iface *iface)
698f2f5156fSBrian Somers {
699f2f5156fSBrian Somers   struct ifreq ifr;
700f2f5156fSBrian Somers   int s;
701f2f5156fSBrian Somers 
702f2f5156fSBrian Somers   if (iface != NULL) {
703f2f5156fSBrian Somers     if ((s = ID0socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
704f2f5156fSBrian Somers       log_Printf(LogERROR, "iface_Destroy: socket(): %s\n", strerror(errno));
705f2f5156fSBrian Somers     } else {
706f2f5156fSBrian Somers       strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
707f2f5156fSBrian Somers       if (ID0ioctl(s, SIOCIFDESTROY, (caddr_t)&ifr) < 0)
708f2f5156fSBrian Somers         log_Printf(LogWARN, "iface_Destroy: ioctl(SIOCIFDESTROY, %s): %s\n",
709f2f5156fSBrian Somers                iface->name, strerror(errno));
710f2f5156fSBrian Somers     }
711f2f5156fSBrian Somers     iface_Free(iface);
712f2f5156fSBrian Somers   }
7138fa6ebe4SBrian Somers }
7148fa6ebe4SBrian Somers 
7158fa6ebe4SBrian Somers #define if_entry(x) { IFF_##x, #x }
7168fa6ebe4SBrian Somers 
7178fa6ebe4SBrian Somers struct {
7188fa6ebe4SBrian Somers   int flag;
7198fa6ebe4SBrian Somers   const char *value;
7208fa6ebe4SBrian Somers } if_flags[] = {
7218fa6ebe4SBrian Somers   if_entry(UP),
7228fa6ebe4SBrian Somers   if_entry(BROADCAST),
7238fa6ebe4SBrian Somers   if_entry(DEBUG),
7248fa6ebe4SBrian Somers   if_entry(LOOPBACK),
7258fa6ebe4SBrian Somers   if_entry(POINTOPOINT),
7268fa6ebe4SBrian Somers   if_entry(RUNNING),
7278fa6ebe4SBrian Somers   if_entry(NOARP),
7288fa6ebe4SBrian Somers   if_entry(PROMISC),
7298fa6ebe4SBrian Somers   if_entry(ALLMULTI),
7308fa6ebe4SBrian Somers   if_entry(OACTIVE),
7318fa6ebe4SBrian Somers   if_entry(SIMPLEX),
7328fa6ebe4SBrian Somers   if_entry(LINK0),
7338fa6ebe4SBrian Somers   if_entry(LINK1),
7348fa6ebe4SBrian Somers   if_entry(LINK2),
7358fa6ebe4SBrian Somers   if_entry(MULTICAST),
7368fa6ebe4SBrian Somers   { 0, "???" }
7378fa6ebe4SBrian Somers };
7388fa6ebe4SBrian Somers 
7398fa6ebe4SBrian Somers int
iface_Show(struct cmdargs const * arg)7408fa6ebe4SBrian Somers iface_Show(struct cmdargs const *arg)
7418fa6ebe4SBrian Somers {
74230949fd4SBrian Somers   struct ncpaddr ncpaddr;
7438fa6ebe4SBrian Somers   struct iface *iface = arg->bundle->iface, *current;
744057f1760SBrian Somers   unsigned f;
745057f1760SBrian Somers   int flags;
74630949fd4SBrian Somers #ifndef NOINET6
74730949fd4SBrian Somers   int scopeid, width;
74830949fd4SBrian Somers #endif
74930949fd4SBrian Somers   struct in_addr mask;
7508fa6ebe4SBrian Somers 
7518fa6ebe4SBrian Somers   current = iface_Create(iface->name);
7528fa6ebe4SBrian Somers   flags = iface->flags = current->flags;
753f2f5156fSBrian Somers   iface_Free(current);
7548fa6ebe4SBrian Somers 
7558fa6ebe4SBrian Somers   prompt_Printf(arg->prompt, "%s (idx %d) <", iface->name, iface->index);
7568fa6ebe4SBrian Somers   for (f = 0; f < sizeof if_flags / sizeof if_flags[0]; f++)
757ebdcbc67SBrian Somers     if ((if_flags[f].flag & flags)) {
7588fa6ebe4SBrian Somers       prompt_Printf(arg->prompt, "%s%s", flags == iface->flags ? "" : ",",
7598fa6ebe4SBrian Somers                     if_flags[f].value);
7608fa6ebe4SBrian Somers       flags &= ~if_flags[f].flag;
7618fa6ebe4SBrian Somers     }
762ebdcbc67SBrian Somers 
763ebdcbc67SBrian Somers #if 0
764ebdcbc67SBrian Somers   if (flags)
765ebdcbc67SBrian Somers     prompt_Printf(arg->prompt, "%s0x%x", flags == iface->flags ? "" : ",",
766ebdcbc67SBrian Somers                   flags);
767ebdcbc67SBrian Somers #endif
768ebdcbc67SBrian Somers 
769057f1760SBrian Somers   prompt_Printf(arg->prompt, "> mtu %lu has %d address%s:\n", iface->mtu,
77030949fd4SBrian Somers                 iface->addrs, iface->addrs == 1 ? "" : "es");
7718fa6ebe4SBrian Somers 
77230949fd4SBrian Somers   for (f = 0; f < iface->addrs; f++) {
77330949fd4SBrian Somers     ncprange_getaddr(&iface->addr[f].ifa, &ncpaddr);
77430949fd4SBrian Somers     switch (ncprange_family(&iface->addr[f].ifa)) {
77530949fd4SBrian Somers     case AF_INET:
77630949fd4SBrian Somers       prompt_Printf(arg->prompt, "  inet %s --> ", ncpaddr_ntoa(&ncpaddr));
77730949fd4SBrian Somers       if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC)
77830949fd4SBrian Somers         prompt_Printf(arg->prompt, "255.255.255.255");
77930949fd4SBrian Somers       else
78030949fd4SBrian Somers         prompt_Printf(arg->prompt, "%s", ncpaddr_ntoa(&iface->addr[f].peer));
78130949fd4SBrian Somers       ncprange_getip4mask(&iface->addr[f].ifa, &mask);
78230949fd4SBrian Somers       prompt_Printf(arg->prompt, " netmask 0x%08lx", (long)ntohl(mask.s_addr));
78330949fd4SBrian Somers       break;
78430949fd4SBrian Somers 
78530949fd4SBrian Somers #ifndef NOINET6
78630949fd4SBrian Somers     case AF_INET6:
78730949fd4SBrian Somers       prompt_Printf(arg->prompt, "  inet6 %s", ncpaddr_ntoa(&ncpaddr));
78830949fd4SBrian Somers       if (ncpaddr_family(&iface->addr[f].peer) != AF_UNSPEC)
78930949fd4SBrian Somers         prompt_Printf(arg->prompt, " --> %s",
79030949fd4SBrian Somers                       ncpaddr_ntoa(&iface->addr[f].peer));
79130949fd4SBrian Somers       ncprange_getwidth(&iface->addr[f].ifa, &width);
792a8862471SBrian Somers       if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC)
79330949fd4SBrian Somers         prompt_Printf(arg->prompt, " prefixlen %d", width);
79430949fd4SBrian Somers       if ((scopeid = ncprange_scopeid(&iface->addr[f].ifa)) != -1)
79530949fd4SBrian Somers         prompt_Printf(arg->prompt, " scopeid 0x%x", (unsigned)scopeid);
79630949fd4SBrian Somers       break;
79730949fd4SBrian Somers #endif
79830949fd4SBrian Somers     }
7998fa6ebe4SBrian Somers     prompt_Printf(arg->prompt, "\n");
8008fa6ebe4SBrian Somers   }
8018fa6ebe4SBrian Somers 
8028fa6ebe4SBrian Somers   return 0;
8038fa6ebe4SBrian Somers }
8046b457978SBrian Somers 
8056b457978SBrian Somers void
iface_ParseHdr(struct ifa_msghdr * ifam,struct sockaddr * sa[RTAX_MAX])8066b457978SBrian Somers iface_ParseHdr(struct ifa_msghdr *ifam, struct sockaddr *sa[RTAX_MAX])
8076b457978SBrian Somers {
8086b457978SBrian Somers   char *wp;
8096b457978SBrian Somers   int rtax;
8106b457978SBrian Somers 
8116b457978SBrian Somers   wp = (char *)(ifam + 1);
8126b457978SBrian Somers 
8136b457978SBrian Somers   for (rtax = 0; rtax < RTAX_MAX; rtax++)
8146b457978SBrian Somers     if (ifam->ifam_addrs & (1 << rtax)) {
8156b457978SBrian Somers       sa[rtax] = (struct sockaddr *)wp;
8166b457978SBrian Somers       wp += ROUNDUP(sa[rtax]->sa_len);
8176b457978SBrian Somers     } else
8186b457978SBrian Somers       sa[rtax] = NULL;
8196b457978SBrian Somers }
820