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

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

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