xref: /freebsd/usr.sbin/ppp/iface.c (revision 8fa6ebe47d24a6621f1be15f3157e2e1a046596e)
18fa6ebe4SBrian Somers /*-
28fa6ebe4SBrian Somers  * Copyright (c) 1998 Brian Somers <brian@Awfulhak.org>
38fa6ebe4SBrian Somers  * All rights reserved.
48fa6ebe4SBrian Somers  *
58fa6ebe4SBrian Somers  * Redistribution and use in source and binary forms, with or without
68fa6ebe4SBrian Somers  * modification, are permitted provided that the following conditions
78fa6ebe4SBrian Somers  * are met:
88fa6ebe4SBrian Somers  * 1. Redistributions of source code must retain the above copyright
98fa6ebe4SBrian Somers  *    notice, this list of conditions and the following disclaimer.
108fa6ebe4SBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
118fa6ebe4SBrian Somers  *    notice, this list of conditions and the following disclaimer in the
128fa6ebe4SBrian Somers  *    documentation and/or other materials provided with the distribution.
138fa6ebe4SBrian Somers  *
148fa6ebe4SBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
158fa6ebe4SBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168fa6ebe4SBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
178fa6ebe4SBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
188fa6ebe4SBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
198fa6ebe4SBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
208fa6ebe4SBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
218fa6ebe4SBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
228fa6ebe4SBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
238fa6ebe4SBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
248fa6ebe4SBrian Somers  * SUCH DAMAGE.
258fa6ebe4SBrian Somers  *
268fa6ebe4SBrian Somers  *	$Id:$
278fa6ebe4SBrian Somers  */
288fa6ebe4SBrian Somers 
298fa6ebe4SBrian Somers #include <sys/types.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 <arpa/inet.h>
368fa6ebe4SBrian Somers #include <netinet/in_systm.h>
378fa6ebe4SBrian Somers #include <netinet/ip.h>
388fa6ebe4SBrian Somers #include <sys/un.h>
398fa6ebe4SBrian Somers 
408fa6ebe4SBrian Somers #include <sys/errno.h>
418fa6ebe4SBrian Somers #include <sys/ioctl.h>
428fa6ebe4SBrian Somers #include <sys/sysctl.h>
438fa6ebe4SBrian Somers #include <string.h>
448fa6ebe4SBrian Somers #include <stdio.h>
458fa6ebe4SBrian Somers #include <stdlib.h>
468fa6ebe4SBrian Somers #include <termios.h>
478fa6ebe4SBrian Somers #include <unistd.h>
488fa6ebe4SBrian Somers 
498fa6ebe4SBrian Somers #include "defs.h"
508fa6ebe4SBrian Somers #include "command.h"
518fa6ebe4SBrian Somers #include "mbuf.h"
528fa6ebe4SBrian Somers #include "log.h"
538fa6ebe4SBrian Somers #include "id.h"
548fa6ebe4SBrian Somers #include "timer.h"
558fa6ebe4SBrian Somers #include "fsm.h"
568fa6ebe4SBrian Somers #include "iplist.h"
578fa6ebe4SBrian Somers #include "lqr.h"
588fa6ebe4SBrian Somers #include "hdlc.h"
598fa6ebe4SBrian Somers #include "throughput.h"
608fa6ebe4SBrian Somers #include "slcompress.h"
618fa6ebe4SBrian Somers #include "filter.h"
628fa6ebe4SBrian Somers #include "descriptor.h"
638fa6ebe4SBrian Somers #include "ipcp.h"
648fa6ebe4SBrian Somers #include "lcp.h"
658fa6ebe4SBrian Somers #include "ccp.h"
668fa6ebe4SBrian Somers #include "link.h"
678fa6ebe4SBrian Somers #include "mp.h"
688fa6ebe4SBrian Somers #include "bundle.h"
698fa6ebe4SBrian Somers #include "prompt.h"
708fa6ebe4SBrian Somers #include "iface.h"
718fa6ebe4SBrian Somers 
728fa6ebe4SBrian Somers 
738fa6ebe4SBrian Somers static int
748fa6ebe4SBrian Somers bitsinmask(struct in_addr mask)
758fa6ebe4SBrian Somers {
768fa6ebe4SBrian Somers   u_int32_t bitmask, maskaddr;
778fa6ebe4SBrian Somers   int bits;
788fa6ebe4SBrian Somers 
798fa6ebe4SBrian Somers   bitmask = 0xffffffff;
808fa6ebe4SBrian Somers   maskaddr = ntohl(mask.s_addr);
818fa6ebe4SBrian Somers   for (bits = 32; bits >= 0; bits--) {
828fa6ebe4SBrian Somers     if (maskaddr == bitmask)
838fa6ebe4SBrian Somers       break;
848fa6ebe4SBrian Somers     bitmask &= ~(1 << (32 - bits));
858fa6ebe4SBrian Somers   }
868fa6ebe4SBrian Somers 
878fa6ebe4SBrian Somers   return bits;
888fa6ebe4SBrian Somers }
898fa6ebe4SBrian Somers 
908fa6ebe4SBrian Somers struct iface *
918fa6ebe4SBrian Somers iface_Create(const char *name)
928fa6ebe4SBrian Somers {
938fa6ebe4SBrian Somers   int mib[6], i, s;
948fa6ebe4SBrian Somers   size_t needed;
958fa6ebe4SBrian Somers   char *buf, *ptr, *end, *cp, *lim;
968fa6ebe4SBrian Somers   struct if_msghdr *ifm;
978fa6ebe4SBrian Somers   struct ifa_msghdr *ifam;
988fa6ebe4SBrian Somers   struct sockaddr_dl *dl;
998fa6ebe4SBrian Somers   struct rt_addrinfo rti;
1008fa6ebe4SBrian Somers   struct iface *iface;
1018fa6ebe4SBrian Somers   struct iface_addr *addr;
1028fa6ebe4SBrian Somers 
1038fa6ebe4SBrian Somers   s = socket(AF_INET, SOCK_DGRAM, 0);
1048fa6ebe4SBrian Somers   if (s < 0) {
1058fa6ebe4SBrian Somers     fprintf(stderr, "iface_Create: socket(): %s\n", strerror(errno));
1068fa6ebe4SBrian Somers     return NULL;
1078fa6ebe4SBrian Somers   }
1088fa6ebe4SBrian Somers 
1098fa6ebe4SBrian Somers   mib[0] = CTL_NET;
1108fa6ebe4SBrian Somers   mib[1] = PF_ROUTE;
1118fa6ebe4SBrian Somers   mib[2] = 0;
1128fa6ebe4SBrian Somers   mib[3] = 0;
1138fa6ebe4SBrian Somers   mib[4] = NET_RT_IFLIST;
1148fa6ebe4SBrian Somers   mib[5] = 0;
1158fa6ebe4SBrian Somers 
1168fa6ebe4SBrian Somers   if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
1178fa6ebe4SBrian Somers     fprintf(stderr, "clean: sysctl: estimate: %s\n",
1188fa6ebe4SBrian Somers               strerror(errno));
1198fa6ebe4SBrian Somers     close(s);
1208fa6ebe4SBrian Somers     return NULL;
1218fa6ebe4SBrian Somers   }
1228fa6ebe4SBrian Somers 
1238fa6ebe4SBrian Somers   if ((buf = (char *)malloc(needed)) == NULL) {
1248fa6ebe4SBrian Somers     close(s);
1258fa6ebe4SBrian Somers     return NULL;
1268fa6ebe4SBrian Somers   }
1278fa6ebe4SBrian Somers 
1288fa6ebe4SBrian Somers   if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
1298fa6ebe4SBrian Somers     free(buf);
1308fa6ebe4SBrian Somers     close(s);
1318fa6ebe4SBrian Somers     return NULL;
1328fa6ebe4SBrian Somers   }
1338fa6ebe4SBrian Somers 
1348fa6ebe4SBrian Somers   ptr = buf;
1358fa6ebe4SBrian Somers   end = buf + needed;
1368fa6ebe4SBrian Somers   iface = NULL;
1378fa6ebe4SBrian Somers 
1388fa6ebe4SBrian Somers   while (ptr < end && iface == NULL) {
1398fa6ebe4SBrian Somers     ifm = (struct if_msghdr *)ptr;			/* On if_msghdr */
1408fa6ebe4SBrian Somers     if (ifm->ifm_type != RTM_IFINFO)
1418fa6ebe4SBrian Somers       break;
1428fa6ebe4SBrian Somers     dl = (struct sockaddr_dl *)(ifm + 1);		/* Single _dl at end */
1438fa6ebe4SBrian Somers     if (!strncmp(name, dl->sdl_data, dl->sdl_nlen)) {
1448fa6ebe4SBrian Somers       iface = (struct iface *)malloc(sizeof *iface);
1458fa6ebe4SBrian Somers       if (iface == NULL) {
1468fa6ebe4SBrian Somers         fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno));
1478fa6ebe4SBrian Somers         return NULL;
1488fa6ebe4SBrian Somers       }
1498fa6ebe4SBrian Somers       iface->name = strdup(name);
1508fa6ebe4SBrian Somers       iface->flags = ifm->ifm_flags;
1518fa6ebe4SBrian Somers       iface->index = ifm->ifm_index;
1528fa6ebe4SBrian Somers       iface->in_addrs = 0;
1538fa6ebe4SBrian Somers       iface->in_addr = NULL;
1548fa6ebe4SBrian Somers     }
1558fa6ebe4SBrian Somers     ptr += ifm->ifm_msglen;				/* First ifa_msghdr */
1568fa6ebe4SBrian Somers     for (; ptr < end; ptr += ifam->ifam_msglen) {
1578fa6ebe4SBrian Somers       ifam = (struct ifa_msghdr *)ptr;			/* Next if address */
1588fa6ebe4SBrian Somers 
1598fa6ebe4SBrian Somers       if (ifam->ifam_type != RTM_NEWADDR)		/* finished this if */
1608fa6ebe4SBrian Somers         break;
1618fa6ebe4SBrian Somers 
1628fa6ebe4SBrian Somers       if (iface == NULL)				/* Keep wading */
1638fa6ebe4SBrian Somers         continue;
1648fa6ebe4SBrian Somers 
1658fa6ebe4SBrian Somers       /* Found an address ! */
1668fa6ebe4SBrian Somers 
1678fa6ebe4SBrian Somers       if (ifam->ifam_addrs & (1 << RTAX_IFA)) {
1688fa6ebe4SBrian Somers         /* *And* it's configured ! */
1698fa6ebe4SBrian Somers         rti.rti_addrs = ifam->ifam_addrs;
1708fa6ebe4SBrian Somers         lim = (char *)ifam + ifam->ifam_msglen;
1718fa6ebe4SBrian Somers         cp = (char *)(ifam + 1);
1728fa6ebe4SBrian Somers         memset(rti.rti_info, '\0', sizeof(rti.rti_info));
1738fa6ebe4SBrian Somers         for (i = 0; i < RTAX_MAX && cp < lim; i++) {
1748fa6ebe4SBrian Somers           if ((rti.rti_addrs & (1 << i)) == 0)
1758fa6ebe4SBrian Somers             continue;
1768fa6ebe4SBrian Somers           rti.rti_info[i] = (struct sockaddr *)cp;
1778fa6ebe4SBrian Somers #define ROUNDUP(x) \
1788fa6ebe4SBrian Somers           ((x) > 0 ? (1 + (((x) - 1) | (sizeof(long) - 1))) : sizeof(long))
1798fa6ebe4SBrian Somers           cp += ROUNDUP(rti.rti_info[i]->sa_len);
1808fa6ebe4SBrian Somers         }
1818fa6ebe4SBrian Somers 
1828fa6ebe4SBrian Somers         if (rti.rti_info[RTAX_IFA] &&
1838fa6ebe4SBrian Somers             rti.rti_info[RTAX_IFA]->sa_family == AF_INET) {
1848fa6ebe4SBrian Somers           /* Record the iface address rti */
1858fa6ebe4SBrian Somers 
1868fa6ebe4SBrian Somers           addr = (struct iface_addr *)realloc
1878fa6ebe4SBrian Somers             (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
1888fa6ebe4SBrian Somers           if (addr == NULL)
1898fa6ebe4SBrian Somers             break;
1908fa6ebe4SBrian Somers           iface->in_addr = addr;
1918fa6ebe4SBrian Somers 
1928fa6ebe4SBrian Somers           addr += iface->in_addrs;
1938fa6ebe4SBrian Somers           iface->in_addrs++;
1948fa6ebe4SBrian Somers 
1958fa6ebe4SBrian Somers           addr->ifa.s_addr = ((struct sockaddr_in *)rti.rti_info[RTAX_IFA])->
1968fa6ebe4SBrian Somers             sin_addr.s_addr;
1978fa6ebe4SBrian Somers           addr->brd.s_addr = rti.rti_info[RTAX_BRD] ?
1988fa6ebe4SBrian Somers             ((struct sockaddr_in *)rti.rti_info[RTAX_BRD])->sin_addr.s_addr :
1998fa6ebe4SBrian Somers             INADDR_ANY;
2008fa6ebe4SBrian Somers           addr->mask.s_addr = rti.rti_info[RTAX_NETMASK] ?
2018fa6ebe4SBrian Somers             ((struct sockaddr_in *)rti.rti_info[RTAX_NETMASK])->sin_addr.s_addr:
2028fa6ebe4SBrian Somers             INADDR_ANY;
2038fa6ebe4SBrian Somers 
2048fa6ebe4SBrian Somers           addr->bits = bitsinmask(addr->mask);
2058fa6ebe4SBrian Somers         }
2068fa6ebe4SBrian Somers       }
2078fa6ebe4SBrian Somers     }
2088fa6ebe4SBrian Somers   }
2098fa6ebe4SBrian Somers 
2108fa6ebe4SBrian Somers   free(buf);
2118fa6ebe4SBrian Somers   close(s);
2128fa6ebe4SBrian Somers 
2138fa6ebe4SBrian Somers   return iface;
2148fa6ebe4SBrian Somers }
2158fa6ebe4SBrian Somers 
2168fa6ebe4SBrian Somers static void
2178fa6ebe4SBrian Somers iface_addr_Zap(const char *name, struct iface_addr *addr)
2188fa6ebe4SBrian Somers {
2198fa6ebe4SBrian Somers   struct ifaliasreq ifra;
2208fa6ebe4SBrian Somers   struct sockaddr_in *me, *peer;
2218fa6ebe4SBrian Somers   int s;
2228fa6ebe4SBrian Somers 
2238fa6ebe4SBrian Somers   s = ID0socket(AF_INET, SOCK_DGRAM, 0);
2248fa6ebe4SBrian Somers   if (s < 0)
2258fa6ebe4SBrian Somers     log_Printf(LogERROR, "iface_addr_Zap: socket(): %s\n", strerror(errno));
2268fa6ebe4SBrian Somers   else {
2278fa6ebe4SBrian Somers     memset(&ifra, '\0', sizeof ifra);
2288fa6ebe4SBrian Somers     strncpy(ifra.ifra_name, name, sizeof ifra.ifra_name - 1);
2298fa6ebe4SBrian Somers     me = (struct sockaddr_in *)&ifra.ifra_addr;
2308fa6ebe4SBrian Somers     peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
2318fa6ebe4SBrian Somers     me->sin_family = peer->sin_family = AF_INET;
2328fa6ebe4SBrian Somers     me->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
2338fa6ebe4SBrian Somers     me->sin_addr = addr->ifa;
2348fa6ebe4SBrian Somers     peer->sin_addr = addr->brd;
2358fa6ebe4SBrian Somers     if (ID0ioctl(s, SIOCDIFADDR, &ifra) < 0)
2368fa6ebe4SBrian Somers       log_Printf(LogWARN, "iface_addr_Zap: ioctl(SIOCDIFADDR, %s): %s\n",
2378fa6ebe4SBrian Somers                  inet_ntoa(addr->ifa), strerror(errno));
2388fa6ebe4SBrian Somers     close(s);
2398fa6ebe4SBrian Somers   }
2408fa6ebe4SBrian Somers }
2418fa6ebe4SBrian Somers 
2428fa6ebe4SBrian Somers void
2438fa6ebe4SBrian Somers iface_inClear(struct iface *iface, int how)
2448fa6ebe4SBrian Somers {
2458fa6ebe4SBrian Somers   int n, addrs;
2468fa6ebe4SBrian Somers 
2478fa6ebe4SBrian Somers   addrs = n = how == IFACE_CLEAR_ALL ? 0 : 1;
2488fa6ebe4SBrian Somers   for (; n < iface->in_addrs; n++)
2498fa6ebe4SBrian Somers     iface_addr_Zap(iface->name, iface->in_addr + n);
2508fa6ebe4SBrian Somers 
2518fa6ebe4SBrian Somers   iface->in_addrs = addrs;
2528fa6ebe4SBrian Somers   /* Don't bother realloc()ing - we have little to gain */
2538fa6ebe4SBrian Somers }
2548fa6ebe4SBrian Somers 
2558fa6ebe4SBrian Somers int
2568fa6ebe4SBrian Somers iface_inAdd(struct iface *iface, struct in_addr ifa, struct in_addr mask,
2578fa6ebe4SBrian Somers             struct in_addr brd, int how)
2588fa6ebe4SBrian Somers {
2598fa6ebe4SBrian Somers   int slot, s;
2608fa6ebe4SBrian Somers   struct ifaliasreq ifra;
2618fa6ebe4SBrian Somers   struct sockaddr_in *me, *peer, *msk;
2628fa6ebe4SBrian Somers   struct iface_addr *addr;
2638fa6ebe4SBrian Somers 
2648fa6ebe4SBrian Somers   for (slot = 0; slot < iface->in_addrs; slot++)
2658fa6ebe4SBrian Somers     if (iface->in_addr[slot].ifa.s_addr == ifa.s_addr) {
2668fa6ebe4SBrian Somers       if (how & IFACE_FORCE_ADD)
2678fa6ebe4SBrian Somers         break;
2688fa6ebe4SBrian Somers       else
2698fa6ebe4SBrian Somers         /* errno = EEXIST; */
2708fa6ebe4SBrian Somers         return 0;
2718fa6ebe4SBrian Somers     }
2728fa6ebe4SBrian Somers 
2738fa6ebe4SBrian Somers   addr = (struct iface_addr *)realloc
2748fa6ebe4SBrian Somers     (iface->in_addr, (iface->in_addrs + 1) * sizeof iface->in_addr[0]);
2758fa6ebe4SBrian Somers   if (addr == NULL) {
2768fa6ebe4SBrian Somers     log_Printf(LogERROR, "iface_inAdd: realloc: %s\n", strerror(errno));
2778fa6ebe4SBrian Somers     return 0;
2788fa6ebe4SBrian Somers   }
2798fa6ebe4SBrian Somers   iface->in_addr = addr;
2808fa6ebe4SBrian Somers 
2818fa6ebe4SBrian Somers   s = ID0socket(AF_INET, SOCK_DGRAM, 0);
2828fa6ebe4SBrian Somers   if (s < 0) {
2838fa6ebe4SBrian Somers     log_Printf(LogERROR, "iface_inAdd: socket(): %s\n", strerror(errno));
2848fa6ebe4SBrian Somers     return 0;
2858fa6ebe4SBrian Somers   }
2868fa6ebe4SBrian Somers 
2878fa6ebe4SBrian Somers   memset(&ifra, '\0', sizeof ifra);
2888fa6ebe4SBrian Somers   strncpy(ifra.ifra_name, iface->name, sizeof ifra.ifra_name - 1);
2898fa6ebe4SBrian Somers 
2908fa6ebe4SBrian Somers   me = (struct sockaddr_in *)&ifra.ifra_addr;
2918fa6ebe4SBrian Somers   msk = (struct sockaddr_in *)&ifra.ifra_mask;
2928fa6ebe4SBrian Somers   peer = (struct sockaddr_in *)&ifra.ifra_broadaddr;
2938fa6ebe4SBrian Somers 
2948fa6ebe4SBrian Somers   me->sin_family = msk->sin_family = peer->sin_family = AF_INET;
2958fa6ebe4SBrian Somers   me->sin_len = msk->sin_len = peer->sin_len = sizeof(struct sockaddr_in);
2968fa6ebe4SBrian Somers 
2978fa6ebe4SBrian Somers   me->sin_addr = ifa;
2988fa6ebe4SBrian Somers   msk->sin_addr = mask;
2998fa6ebe4SBrian Somers   peer->sin_addr = brd;
3008fa6ebe4SBrian Somers 
3018fa6ebe4SBrian Somers   /*
3028fa6ebe4SBrian Somers    * Note: EEXIST is sometimes returned, despite the route actually being
3038fa6ebe4SBrian Somers    *       added !
3048fa6ebe4SBrian Somers    */
3058fa6ebe4SBrian Somers   if (ID0ioctl(s, SIOCAIFADDR, &ifra) < 0 && errno != EEXIST) {
3068fa6ebe4SBrian Somers     log_Printf(LogERROR, "iface_inAdd: ioctl(SIOCAIFADDR): %s\n",
3078fa6ebe4SBrian Somers                strerror(errno));
3088fa6ebe4SBrian Somers     close(s);
3098fa6ebe4SBrian Somers     return 0;
3108fa6ebe4SBrian Somers   }
3118fa6ebe4SBrian Somers   close(s);
3128fa6ebe4SBrian Somers 
3138fa6ebe4SBrian Somers   if (slot == iface->in_addrs) {
3148fa6ebe4SBrian Somers     /* We're adding a new interface address */
3158fa6ebe4SBrian Somers 
3168fa6ebe4SBrian Somers     if (how & IFACE_ADD_FIRST) {
3178fa6ebe4SBrian Somers       /* Stuff it at the start of our list */
3188fa6ebe4SBrian Somers       slot = 0;
3198fa6ebe4SBrian Somers       bcopy(iface->in_addr, iface->in_addr + 1,
3208fa6ebe4SBrian Somers             iface->in_addrs * sizeof iface->in_addr[0]);
3218fa6ebe4SBrian Somers     }
3228fa6ebe4SBrian Somers 
3238fa6ebe4SBrian Somers     iface->in_addrs++;
3248fa6ebe4SBrian Somers   } else if (how & IFACE_ADD_FIRST) {
3258fa6ebe4SBrian Somers     /* Shift it up to the first slot */
3268fa6ebe4SBrian Somers     bcopy(iface->in_addr, iface->in_addr + 1, slot * sizeof iface->in_addr[0]);
3278fa6ebe4SBrian Somers     slot = 0;
3288fa6ebe4SBrian Somers   }
3298fa6ebe4SBrian Somers 
3308fa6ebe4SBrian Somers   iface->in_addr[slot].ifa = ifa;
3318fa6ebe4SBrian Somers   iface->in_addr[slot].mask = mask;
3328fa6ebe4SBrian Somers   iface->in_addr[slot].brd = brd;
3338fa6ebe4SBrian Somers   iface->in_addr[slot].bits = bitsinmask(iface->in_addr[slot].mask);
3348fa6ebe4SBrian Somers 
3358fa6ebe4SBrian Somers   return 1;
3368fa6ebe4SBrian Somers }
3378fa6ebe4SBrian Somers 
3388fa6ebe4SBrian Somers int
3398fa6ebe4SBrian Somers iface_inDelete(struct iface *iface, struct in_addr ip)
3408fa6ebe4SBrian Somers {
3418fa6ebe4SBrian Somers   int n;
3428fa6ebe4SBrian Somers 
3438fa6ebe4SBrian Somers   for (n = 0; n < iface->in_addrs; n++)
3448fa6ebe4SBrian Somers     if (iface->in_addr[n].ifa.s_addr == ip.s_addr) {
3458fa6ebe4SBrian Somers       iface_addr_Zap(iface->name, iface->in_addr + n);
3468fa6ebe4SBrian Somers       bcopy(iface->in_addr + n + 1, iface->in_addr + n,
3478fa6ebe4SBrian Somers             (iface->in_addrs - n - 1) * sizeof iface->in_addr[0]);
3488fa6ebe4SBrian Somers       iface->in_addrs--;
3498fa6ebe4SBrian Somers       return 1;
3508fa6ebe4SBrian Somers     }
3518fa6ebe4SBrian Somers 
3528fa6ebe4SBrian Somers   return 0;
3538fa6ebe4SBrian Somers }
3548fa6ebe4SBrian Somers 
3558fa6ebe4SBrian Somers void
3568fa6ebe4SBrian Somers iface_Destroy(struct iface *iface)
3578fa6ebe4SBrian Somers {
3588fa6ebe4SBrian Somers   /*
3598fa6ebe4SBrian Somers    * iface_Clear(iface, IFACE_CLEAR_ALL) must be called manually
3608fa6ebe4SBrian Somers    * if that's what the user wants.  It's better to leave the interface
3618fa6ebe4SBrian Somers    * allocated so that existing connections can continue to work.
3628fa6ebe4SBrian Somers    */
3638fa6ebe4SBrian Somers 
3648fa6ebe4SBrian Somers   if (iface != NULL) {
3658fa6ebe4SBrian Somers     free(iface->name);
3668fa6ebe4SBrian Somers     free(iface->in_addr);
3678fa6ebe4SBrian Somers     free(iface);
3688fa6ebe4SBrian Somers   }
3698fa6ebe4SBrian Somers }
3708fa6ebe4SBrian Somers 
3718fa6ebe4SBrian Somers #define if_entry(x) { IFF_##x, #x }
3728fa6ebe4SBrian Somers 
3738fa6ebe4SBrian Somers struct {
3748fa6ebe4SBrian Somers   int flag;
3758fa6ebe4SBrian Somers   const char *value;
3768fa6ebe4SBrian Somers } if_flags[] = {
3778fa6ebe4SBrian Somers   if_entry(UP),
3788fa6ebe4SBrian Somers   if_entry(BROADCAST),
3798fa6ebe4SBrian Somers   if_entry(DEBUG),
3808fa6ebe4SBrian Somers   if_entry(LOOPBACK),
3818fa6ebe4SBrian Somers   if_entry(POINTOPOINT),
3828fa6ebe4SBrian Somers   if_entry(RUNNING),
3838fa6ebe4SBrian Somers   if_entry(NOARP),
3848fa6ebe4SBrian Somers   if_entry(PROMISC),
3858fa6ebe4SBrian Somers   if_entry(ALLMULTI),
3868fa6ebe4SBrian Somers   if_entry(OACTIVE),
3878fa6ebe4SBrian Somers   if_entry(SIMPLEX),
3888fa6ebe4SBrian Somers   if_entry(LINK0),
3898fa6ebe4SBrian Somers   if_entry(LINK1),
3908fa6ebe4SBrian Somers   if_entry(LINK2),
3918fa6ebe4SBrian Somers   if_entry(MULTICAST),
3928fa6ebe4SBrian Somers   { 0, "???" }
3938fa6ebe4SBrian Somers };
3948fa6ebe4SBrian Somers 
3958fa6ebe4SBrian Somers int
3968fa6ebe4SBrian Somers iface_Show(struct cmdargs const *arg)
3978fa6ebe4SBrian Somers {
3988fa6ebe4SBrian Somers   struct iface *iface = arg->bundle->iface, *current;
3998fa6ebe4SBrian Somers   int f, flags;
4008fa6ebe4SBrian Somers 
4018fa6ebe4SBrian Somers   current = iface_Create(iface->name);
4028fa6ebe4SBrian Somers   flags = iface->flags = current->flags;
4038fa6ebe4SBrian Somers   iface_Destroy(current);
4048fa6ebe4SBrian Somers 
4058fa6ebe4SBrian Somers   prompt_Printf(arg->prompt, "%s (idx %d) <", iface->name, iface->index);
4068fa6ebe4SBrian Somers   for (f = 0; f < sizeof if_flags / sizeof if_flags[0]; f++)
4078fa6ebe4SBrian Somers     if ((if_flags[f].flag & flags) || (!if_flags[f].flag && flags)) {
4088fa6ebe4SBrian Somers       prompt_Printf(arg->prompt, "%s%s", flags == iface->flags ? "" : ",",
4098fa6ebe4SBrian Somers                     if_flags[f].value);
4108fa6ebe4SBrian Somers       flags &= ~if_flags[f].flag;
4118fa6ebe4SBrian Somers     }
4128fa6ebe4SBrian Somers   prompt_Printf(arg->prompt, "> has %d address%s:\n", iface->in_addrs,
4138fa6ebe4SBrian Somers                 iface->in_addrs == 1 ? "" : "es");
4148fa6ebe4SBrian Somers 
4158fa6ebe4SBrian Somers   for (f = 0; f < iface->in_addrs; f++) {
4168fa6ebe4SBrian Somers     prompt_Printf(arg->prompt, "  %s", inet_ntoa(iface->in_addr[f].ifa));
4178fa6ebe4SBrian Somers     if (iface->in_addr[f].bits >= 0)
4188fa6ebe4SBrian Somers       prompt_Printf(arg->prompt, "/%d", iface->in_addr[f].bits);
4198fa6ebe4SBrian Somers     if (iface->flags & IFF_POINTOPOINT)
4208fa6ebe4SBrian Somers       prompt_Printf(arg->prompt, " -> %s", inet_ntoa(iface->in_addr[f].brd));
4218fa6ebe4SBrian Somers     else if (iface->flags & IFF_BROADCAST)
4228fa6ebe4SBrian Somers       prompt_Printf(arg->prompt, " broadcast %s",
4238fa6ebe4SBrian Somers                     inet_ntoa(iface->in_addr[f].brd));
4248fa6ebe4SBrian Somers     if (iface->in_addr[f].bits < 0)
4258fa6ebe4SBrian Somers       prompt_Printf(arg->prompt, " (mask %s)",
4268fa6ebe4SBrian Somers                     inet_ntoa(iface->in_addr[f].mask));
4278fa6ebe4SBrian Somers     prompt_Printf(arg->prompt, "\n");
4288fa6ebe4SBrian Somers   }
4298fa6ebe4SBrian Somers 
4308fa6ebe4SBrian Somers   return 0;
4318fa6ebe4SBrian Somers }
432