Annotation of embedaddon/quagga/zebra/ioctl_solaris.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Common ioctl functions for Solaris.
        !             3:  * Copyright (C) 1997, 98 Kunihiro Ishiguro
        !             4:  *
        !             5:  * This file is part of GNU Zebra.
        !             6:  *
        !             7:  * GNU Zebra is free software; you can redistribute it and/or modify it
        !             8:  * under the terms of the GNU General Public License as published by the
        !             9:  * Free Software Foundation; either version 2, or (at your option) any
        !            10:  * later version.
        !            11:  *
        !            12:  * GNU Zebra is distributed in the hope that it will be useful, but
        !            13:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            15:  * General Public License for more details.
        !            16:  *
        !            17:  * You should have received a copy of the GNU General Public License
        !            18:  * along with GNU Zebra; see the file COPYING.  If not, write to the Free
        !            19:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
        !            20:  * 02111-1307, USA.  
        !            21:  */
        !            22: 
        !            23: #include <zebra.h>
        !            24: 
        !            25: #include "linklist.h"
        !            26: #include "if.h"
        !            27: #include "prefix.h"
        !            28: #include "ioctl.h"
        !            29: #include "log.h"
        !            30: #include "privs.h"
        !            31: 
        !            32: #include "zebra/rib.h"
        !            33: #include "zebra/rt.h"
        !            34: #include "zebra/interface.h"
        !            35: 
        !            36: extern struct zebra_privs_t zserv_privs;
        !            37: 
        !            38: /* clear and set interface name string */
        !            39: void
        !            40: lifreq_set_name (struct lifreq *lifreq, const char *ifname)
        !            41: {
        !            42:   strncpy (lifreq->lifr_name, ifname, IFNAMSIZ);
        !            43: }
        !            44: 
        !            45: /* call ioctl system call */
        !            46: int
        !            47: if_ioctl (u_long request, caddr_t buffer)
        !            48: {
        !            49:   int sock;
        !            50:   int ret;
        !            51:   int err;
        !            52: 
        !            53:   if (zserv_privs.change(ZPRIVS_RAISE))
        !            54:     zlog (NULL, LOG_ERR, "Can't raise privileges");
        !            55:     
        !            56:   sock = socket (AF_INET, SOCK_DGRAM, 0);
        !            57:   if (sock < 0)
        !            58:     {
        !            59:       int save_errno = errno;
        !            60:       if (zserv_privs.change(ZPRIVS_LOWER))
        !            61:         zlog (NULL, LOG_ERR, "Can't lower privileges");
        !            62:       zlog_err("Cannot create UDP socket: %s", safe_strerror(save_errno));
        !            63:       exit (1);
        !            64:     }
        !            65: 
        !            66:   if ((ret = ioctl (sock, request, buffer)) < 0)
        !            67:     err = errno;
        !            68:   
        !            69:   if (zserv_privs.change(ZPRIVS_LOWER))
        !            70:     zlog (NULL, LOG_ERR, "Can't lower privileges");
        !            71: 
        !            72:   close (sock);
        !            73: 
        !            74:   if (ret < 0)
        !            75:     {
        !            76:       errno = err;
        !            77:       return ret;
        !            78:     }
        !            79:   return 0;
        !            80: }
        !            81: 
        !            82: 
        !            83: int
        !            84: if_ioctl_ipv6 (u_long request, caddr_t buffer)
        !            85: {
        !            86: #ifdef HAVE_IPV6
        !            87:   int sock;
        !            88:   int ret;
        !            89:   int err;
        !            90: 
        !            91:   if (zserv_privs.change(ZPRIVS_RAISE))
        !            92:     zlog (NULL, LOG_ERR, "Can't raise privileges");
        !            93: 
        !            94:   sock = socket (AF_INET6, SOCK_DGRAM, 0);
        !            95:   if (sock < 0)
        !            96:     {
        !            97:       int save_errno = errno;
        !            98:       if (zserv_privs.change(ZPRIVS_LOWER))
        !            99:         zlog (NULL, LOG_ERR, "Can't lower privileges");
        !           100:       zlog_err("Cannot create IPv6 datagram socket: %s",
        !           101:               safe_strerror(save_errno));
        !           102:       exit (1);
        !           103:     }
        !           104: 
        !           105:   if ((ret = ioctl (sock, request, buffer)) < 0)
        !           106:     err = errno;
        !           107: 
        !           108:   if (zserv_privs.change(ZPRIVS_LOWER))
        !           109:     zlog (NULL, LOG_ERR, "Can't lower privileges");
        !           110: 
        !           111:   close (sock);
        !           112: 
        !           113:   if (ret < 0)
        !           114:     {
        !           115:       errno = err;
        !           116:       return ret;
        !           117:     }
        !           118: #endif /* HAVE_IPV6 */
        !           119: 
        !           120:   return 0;
        !           121: }
        !           122: 
        !           123: /*
        !           124:  * get interface metric
        !           125:  *   -- if value is not avaliable set -1
        !           126:  */
        !           127: void
        !           128: if_get_metric (struct interface *ifp)
        !           129: {
        !           130:   struct lifreq lifreq;
        !           131:   int ret;
        !           132: 
        !           133:   lifreq_set_name (&lifreq, ifp->name);
        !           134: 
        !           135:   if (ifp->flags & IFF_IPV4)
        !           136:     ret = AF_IOCTL (AF_INET, SIOCGLIFMETRIC, (caddr_t) & lifreq);
        !           137: #ifdef SOLARIS_IPV6
        !           138:   else if (ifp->flags & IFF_IPV6)
        !           139:     ret = AF_IOCTL (AF_INET6, SIOCGLIFMETRIC, (caddr_t) & lifreq);
        !           140: #endif /* SOLARIS_IPV6 */
        !           141:   else
        !           142:     ret = -1;
        !           143:     
        !           144:   if (ret < 0)
        !           145:     return;
        !           146: 
        !           147:   ifp->metric = lifreq.lifr_metric;
        !           148: 
        !           149:   if (ifp->metric == 0)
        !           150:     ifp->metric = 1;
        !           151: }
        !           152: 
        !           153: /* get interface MTU */
        !           154: void
        !           155: if_get_mtu (struct interface *ifp)
        !           156: {
        !           157:   struct lifreq lifreq;
        !           158:   int ret;
        !           159:   u_char changed = 0;
        !           160:   
        !           161:   if (ifp->flags & IFF_IPV4)
        !           162:     {
        !           163:       lifreq_set_name (&lifreq, ifp->name);
        !           164:       ret = AF_IOCTL (AF_INET, SIOCGLIFMTU, (caddr_t) & lifreq);
        !           165:       if (ret < 0)
        !           166:         {
        !           167:           zlog_info ("Can't lookup mtu on %s by ioctl(SIOCGLIFMTU)",
        !           168:                      ifp->name);
        !           169:           ifp->mtu = -1;
        !           170:         }
        !           171:       else
        !           172:         {
        !           173:           ifp->mtu = lifreq.lifr_metric;
        !           174:           changed = 1;
        !           175:         }
        !           176:     }
        !           177: 
        !           178: #ifdef HAVE_IPV6
        !           179:   if (ifp->flags & IFF_IPV6)
        !           180:   {
        !           181:     memset(&lifreq, 0, sizeof(lifreq));
        !           182:     lifreq_set_name (&lifreq, ifp->name);
        !           183: 
        !           184:     ret = AF_IOCTL (AF_INET6, SIOCGLIFMTU, (caddr_t) & lifreq);
        !           185:     if (ret < 0)
        !           186:     {
        !           187:       zlog_info ("Can't lookup mtu6 on %s by ioctl(SIOCGIFMTU)", ifp->name);
        !           188:       ifp->mtu6 = -1;
        !           189:     }
        !           190:     else
        !           191:     {
        !           192:       ifp->mtu6 = lifreq.lifr_metric;
        !           193:       changed = 1;
        !           194:     }
        !           195:   }
        !           196: #endif /* HAVE_IPV6 */
        !           197: 
        !           198:   if (changed)
        !           199:     zebra_interface_up_update(ifp);
        !           200: }
        !           201: 
        !           202: /* Set up interface's address, netmask (and broadcast? ).
        !           203:    Solaris uses ifname:number semantics to set IP address aliases. */
        !           204: int
        !           205: if_set_prefix (struct interface *ifp, struct connected *ifc)
        !           206: {
        !           207:   int ret;
        !           208:   struct ifreq ifreq;
        !           209:   struct sockaddr_in addr;
        !           210:   struct sockaddr_in broad;
        !           211:   struct sockaddr_in mask;
        !           212:   struct prefix_ipv4 ifaddr;
        !           213:   struct prefix_ipv4 *p;
        !           214: 
        !           215:   p = (struct prefix_ipv4 *) ifc->address;
        !           216: 
        !           217:   ifaddr = *p;
        !           218: 
        !           219:   strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
        !           220: 
        !           221:   addr.sin_addr = p->prefix;
        !           222:   addr.sin_family = p->family;
        !           223:   memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
        !           224: 
        !           225:   ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq);
        !           226: 
        !           227:   if (ret < 0)
        !           228:     return ret;
        !           229: 
        !           230:   /* We need mask for make broadcast addr. */
        !           231:   masklen2ip (p->prefixlen, &mask.sin_addr);
        !           232: 
        !           233:   if (if_is_broadcast (ifp))
        !           234:     {
        !           235:       apply_mask_ipv4 (&ifaddr);
        !           236:       addr.sin_addr = ifaddr.prefix;
        !           237: 
        !           238:       broad.sin_addr.s_addr = (addr.sin_addr.s_addr | ~mask.sin_addr.s_addr);
        !           239:       broad.sin_family = p->family;
        !           240: 
        !           241:       memcpy (&ifreq.ifr_broadaddr, &broad, sizeof (struct sockaddr_in));
        !           242:       ret = if_ioctl (SIOCSIFBRDADDR, (caddr_t) & ifreq);
        !           243:       if (ret < 0)
        !           244:         return ret;
        !           245:     }
        !           246: 
        !           247:   mask.sin_family = p->family;
        !           248: #ifdef SUNOS_5
        !           249:   memcpy (&mask, &ifreq.ifr_addr, sizeof (mask));
        !           250: #else
        !           251:   memcpy (&ifreq.ifr_netmask, &mask, sizeof (struct sockaddr_in));
        !           252: #endif /* SUNOS_5 */
        !           253:   ret = if_ioctl (SIOCSIFNETMASK, (caddr_t) & ifreq);
        !           254: 
        !           255:   return ((ret < 0) ? ret : 0);
        !           256: }
        !           257: 
        !           258: /* Set up interface's address, netmask (and broadcast).
        !           259:    Solaris uses ifname:number semantics to set IP address aliases. */
        !           260: int
        !           261: if_unset_prefix (struct interface *ifp, struct connected *ifc)
        !           262: {
        !           263:   int ret;
        !           264:   struct ifreq ifreq;
        !           265:   struct sockaddr_in addr;
        !           266:   struct prefix_ipv4 *p;
        !           267: 
        !           268:   p = (struct prefix_ipv4 *) ifc->address;
        !           269: 
        !           270:   strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
        !           271: 
        !           272:   memset (&addr, 0, sizeof (struct sockaddr_in));
        !           273:   addr.sin_family = p->family;
        !           274:   memcpy (&ifreq.ifr_addr, &addr, sizeof (struct sockaddr_in));
        !           275: 
        !           276:   ret = if_ioctl (SIOCSIFADDR, (caddr_t) & ifreq);
        !           277:   
        !           278:   if (ret < 0)
        !           279:     return ret;
        !           280: 
        !           281:   return 0;
        !           282: }
        !           283: 
        !           284: /* Get just the flags for the given name.
        !           285:  * Used by the normal 'if_get_flags' function, as well
        !           286:  * as the bootup interface-list code, which has to peek at per-address
        !           287:  * flags in order to figure out which ones should be ignored..
        !           288:  */
        !           289: int
        !           290: if_get_flags_direct (const char *ifname, uint64_t *flags, unsigned int af)
        !           291: {
        !           292:   struct lifreq lifreq;
        !           293:   int ret;
        !           294:     
        !           295:   lifreq_set_name (&lifreq, ifname);
        !           296:   
        !           297:   ret = AF_IOCTL (af, SIOCGLIFFLAGS, (caddr_t) &lifreq);
        !           298:   
        !           299:   if (ret)
        !           300:     zlog_debug ("%s: ifname %s, error %s (%d)",
        !           301:                 __func__, ifname, safe_strerror (errno), errno);
        !           302:   
        !           303:   *flags = lifreq.lifr_flags;
        !           304:   
        !           305:   return ret;
        !           306: }
        !           307: 
        !           308: /* get interface flags */
        !           309: void
        !           310: if_get_flags (struct interface *ifp)
        !           311: {
        !           312:   int ret4, ret6;
        !           313:   uint64_t newflags = 0;
        !           314:   uint64_t tmpflags;
        !           315: 
        !           316:   if (ifp->flags & IFF_IPV4)
        !           317:     {
        !           318:       ret4 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET);
        !           319:       
        !           320:       if (!ret4)
        !           321:         newflags |= tmpflags;
        !           322:       else if (errno == ENXIO)
        !           323:         {
        !           324:           /* it's gone */
        !           325:           UNSET_FLAG (ifp->flags, IFF_UP);
        !           326:           if_flags_update (ifp, ifp->flags);
        !           327:         }
        !           328:     }
        !           329: 
        !           330:   if (ifp->flags & IFF_IPV6)
        !           331:     {
        !           332:       ret6 = if_get_flags_direct (ifp->name, &tmpflags, AF_INET6);
        !           333:       
        !           334:       if (!ret6)
        !           335:         newflags |= tmpflags;
        !           336:       else if (errno == ENXIO)
        !           337:         {
        !           338:           /* it's gone */
        !           339:           UNSET_FLAG (ifp->flags, IFF_UP);
        !           340:           if_flags_update (ifp, ifp->flags);
        !           341:         }
        !           342:     }
        !           343:   
        !           344:   /* only update flags if one of above succeeded */
        !           345:   if ( !(ret4 && ret6) )
        !           346:     if_flags_update (ifp, newflags);
        !           347: }
        !           348: 
        !           349: /* Set interface flags */
        !           350: int
        !           351: if_set_flags (struct interface *ifp, uint64_t flags)
        !           352: {
        !           353:   int ret;
        !           354:   struct lifreq lifreq;
        !           355: 
        !           356:   lifreq_set_name (&lifreq, ifp->name);
        !           357: 
        !           358:   lifreq.lifr_flags = ifp->flags;
        !           359:   lifreq.lifr_flags |= flags;
        !           360: 
        !           361:   if (ifp->flags & IFF_IPV4)
        !           362:     ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq);
        !           363:   else if (ifp->flags & IFF_IPV6)
        !           364:     ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq);
        !           365:   else
        !           366:     ret = -1;
        !           367: 
        !           368:   if (ret < 0)
        !           369:     zlog_info ("can't set interface flags on %s: %s", ifp->name,
        !           370:                safe_strerror (errno));
        !           371:   else
        !           372:     ret = 0;
        !           373:     
        !           374:   return ret;
        !           375: }
        !           376: 
        !           377: /* Unset interface's flag. */
        !           378: int
        !           379: if_unset_flags (struct interface *ifp, uint64_t flags)
        !           380: {
        !           381:   int ret;
        !           382:   struct lifreq lifreq;
        !           383: 
        !           384:   lifreq_set_name (&lifreq, ifp->name);
        !           385: 
        !           386:   lifreq.lifr_flags = ifp->flags;
        !           387:   lifreq.lifr_flags &= ~flags;
        !           388: 
        !           389:   if (ifp->flags & IFF_IPV4)
        !           390:     ret = AF_IOCTL (AF_INET, SIOCSLIFFLAGS, (caddr_t) & lifreq);
        !           391:   else if (ifp->flags & IFF_IPV6)
        !           392:     ret = AF_IOCTL (AF_INET6, SIOCSLIFFLAGS, (caddr_t) & lifreq);
        !           393:   else
        !           394:     ret = -1;
        !           395: 
        !           396:   if (ret < 0)
        !           397:     zlog_info ("can't unset interface flags");
        !           398:   else
        !           399:     ret = 0;
        !           400:   
        !           401:   return ret;
        !           402: }
        !           403: 
        !           404: #ifdef HAVE_IPV6
        !           405: 
        !           406: /* Interface's address add/delete functions. */
        !           407: int
        !           408: if_prefix_add_ipv6 (struct interface *ifp, struct connected *ifc)
        !           409: {
        !           410:   char addrbuf[INET_ADDRSTRLEN];
        !           411: 
        !           412:   inet_ntop (AF_INET6, &(((struct prefix_ipv6 *) (ifc->address))->prefix),
        !           413:              addrbuf, sizeof (addrbuf));
        !           414:   zlog_warn ("Can't set %s on interface %s", addrbuf, ifp->name);
        !           415: 
        !           416:   return 0;
        !           417: 
        !           418: }
        !           419: 
        !           420: int
        !           421: if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
        !           422: {
        !           423:   char addrbuf[INET_ADDRSTRLEN];
        !           424: 
        !           425:   inet_ntop (AF_INET6, &(((struct prefix_ipv6 *) (ifc->address))->prefix),
        !           426:              addrbuf, sizeof (addrbuf));
        !           427:   zlog_warn ("Can't delete %s on interface %s", addrbuf, ifp->name);
        !           428: 
        !           429:   return 0;
        !           430: 
        !           431: }
        !           432: 
        !           433: #endif /* HAVE_IPV6 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>