Annotation of embedaddon/quagga/zebra/ioctl_solaris.c, revision 1.1.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>