File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / zebra / ioctl_solaris.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

    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: #include "zebra/ioctl_solaris.h"
   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: {
  313:   int ret4 = 0, ret6 = 0;
  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: {
  411:   char addrbuf[PREFIX_STRLEN];
  412: 
  413:   zlog_warn ("Can't set %s on interface %s",
  414:              prefix2str(ifc->address, addrbuf, sizeof(addrbuf)),
  415:              ifp->name);
  416: 
  417:   return 0;
  418: 
  419: }
  420: 
  421: int
  422: if_prefix_delete_ipv6 (struct interface *ifp, struct connected *ifc)
  423: {
  424:   char addrbuf[PREFIX_STRLEN];
  425: 
  426:   zlog_warn ("Can't delete %s on interface %s",
  427:              prefix2str(ifc->address, addrbuf, sizeof(addrbuf)),
  428:              ifp->name);
  429: 
  430:   return 0;
  431: 
  432: }
  433: 
  434: #endif /* HAVE_IPV6 */

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