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

1.1     ! misho       1: /*
        !             2:  * Kernel routing table updates by routing socket.
        !             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 "if.h"
        !            26: #include "prefix.h"
        !            27: #include "sockunion.h"
        !            28: #include "log.h"
        !            29: #include "str.h"
        !            30: #include "privs.h"
        !            31: 
        !            32: #include "zebra/debug.h"
        !            33: #include "zebra/rib.h"
        !            34: #include "zebra/rt.h"
        !            35: #include "zebra/kernel_socket.h"
        !            36: 
        !            37: extern struct zebra_privs_t zserv_privs;
        !            38: 
        !            39: /* kernel socket export */
        !            40: extern int rtm_write (int message, union sockunion *dest,
        !            41:                       union sockunion *mask, union sockunion *gate,
        !            42:                       unsigned int index, int zebra_flags, int metric);
        !            43: 
        !            44: /* Adjust netmask socket length. Return value is a adjusted sin_len
        !            45:    value. */
        !            46: static int
        !            47: sin_masklen (struct in_addr mask)
        !            48: {
        !            49:   char *p, *lim;
        !            50:   int len;
        !            51:   struct sockaddr_in sin;
        !            52: 
        !            53:   if (mask.s_addr == 0) 
        !            54:     return sizeof (long);
        !            55: 
        !            56:   sin.sin_addr = mask;
        !            57:   len = sizeof (struct sockaddr_in);
        !            58: 
        !            59:   lim = (char *) &sin.sin_addr;
        !            60:   p = lim + sizeof (sin.sin_addr);
        !            61: 
        !            62:   while (*--p == 0 && p >= lim) 
        !            63:     len--;
        !            64:   return len;
        !            65: }
        !            66: 
        !            67: /* Interface between zebra message and rtm message. */
        !            68: static int
        !            69: kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family)
        !            70: 
        !            71: {
        !            72:   struct sockaddr_in *mask = NULL;
        !            73:   struct sockaddr_in sin_dest, sin_mask, sin_gate;
        !            74:   struct nexthop *nexthop;
        !            75:   int nexthop_num = 0;
        !            76:   unsigned int ifindex = 0;
        !            77:   int gate = 0;
        !            78:   int error;
        !            79:   char prefix_buf[INET_ADDRSTRLEN];
        !            80: 
        !            81:   if (IS_ZEBRA_DEBUG_RIB)
        !            82:     inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN);
        !            83:   memset (&sin_dest, 0, sizeof (struct sockaddr_in));
        !            84:   sin_dest.sin_family = AF_INET;
        !            85: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
        !            86:   sin_dest.sin_len = sizeof (struct sockaddr_in);
        !            87: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
        !            88:   sin_dest.sin_addr = p->u.prefix4;
        !            89: 
        !            90:   memset (&sin_mask, 0, sizeof (struct sockaddr_in));
        !            91: 
        !            92:   memset (&sin_gate, 0, sizeof (struct sockaddr_in));
        !            93:   sin_gate.sin_family = AF_INET;
        !            94: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
        !            95:   sin_gate.sin_len = sizeof (struct sockaddr_in);
        !            96: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
        !            97: 
        !            98:   /* Make gateway. */
        !            99:   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
        !           100:     {
        !           101:       gate = 0;
        !           102:       char gate_buf[INET_ADDRSTRLEN] = "NULL";
        !           103: 
        !           104:       /*
        !           105:        * XXX We need to refrain from kernel operations in some cases,
        !           106:        * but this if statement seems overly cautious - what about
        !           107:        * other than ADD and DELETE?
        !           108:        */
        !           109:       if ((cmd == RTM_ADD
        !           110:           && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
        !           111:          || (cmd == RTM_DELETE
        !           112:              && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
        !           113:              ))
        !           114:        {
        !           115:          if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
        !           116:            {
        !           117:              if (nexthop->rtype == NEXTHOP_TYPE_IPV4 ||
        !           118:                  nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
        !           119:                {
        !           120:                  sin_gate.sin_addr = nexthop->rgate.ipv4;
        !           121:                  gate = 1;
        !           122:                }
        !           123:              if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
        !           124:                  || nexthop->rtype == NEXTHOP_TYPE_IFNAME
        !           125:                  || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
        !           126:                ifindex = nexthop->rifindex;
        !           127:            }
        !           128:          else
        !           129:            {
        !           130:              if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
        !           131:                  nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
        !           132:                {
        !           133:                  sin_gate.sin_addr = nexthop->gate.ipv4;
        !           134:                  gate = 1;
        !           135:                }
        !           136:              if (nexthop->type == NEXTHOP_TYPE_IFINDEX
        !           137:                  || nexthop->type == NEXTHOP_TYPE_IFNAME
        !           138:                  || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
        !           139:                ifindex = nexthop->ifindex;
        !           140:              if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
        !           141:                {
        !           142:                  struct in_addr loopback;
        !           143:                  loopback.s_addr = htonl (INADDR_LOOPBACK);
        !           144:                  sin_gate.sin_addr = loopback;
        !           145:                  gate = 1;
        !           146:                }
        !           147:            }
        !           148: 
        !           149:          if (gate && p->prefixlen == 32)
        !           150:            mask = NULL;
        !           151:          else
        !           152:            {
        !           153:              masklen2ip (p->prefixlen, &sin_mask.sin_addr);
        !           154:              sin_mask.sin_family = AF_INET;
        !           155: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
        !           156:              sin_mask.sin_len = sin_masklen (sin_mask.sin_addr);
        !           157: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
        !           158:              mask = &sin_mask;
        !           159:            }
        !           160: 
        !           161:          error = rtm_write (cmd,
        !           162:                             (union sockunion *)&sin_dest, 
        !           163:                             (union sockunion *)mask, 
        !           164:                             gate ? (union sockunion *)&sin_gate : NULL,
        !           165:                             ifindex,
        !           166:                             rib->flags,
        !           167:                             rib->metric);
        !           168: 
        !           169:            if (IS_ZEBRA_DEBUG_RIB)
        !           170:            {
        !           171:              if (!gate)
        !           172:              {
        !           173:                zlog_debug ("%s: %s/%d: attention! gate not found for rib %p",
        !           174:                  __func__, prefix_buf, p->prefixlen, rib);
        !           175:                rib_dump (__func__, (struct prefix_ipv4 *)p, rib);
        !           176:              }
        !           177:              else
        !           178:                inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN);
        !           179:            }
        !           180:  
        !           181:            switch (error)
        !           182:            {
        !           183:              /* We only flag nexthops as being in FIB if rtm_write() did its work. */
        !           184:              case ZEBRA_ERR_NOERROR:
        !           185:                nexthop_num++;
        !           186:                if (IS_ZEBRA_DEBUG_RIB)
        !           187:                  zlog_debug ("%s: %s/%d: successfully did NH %s",
        !           188:                    __func__, prefix_buf, p->prefixlen, gate_buf);
        !           189:                if (cmd == RTM_ADD)
        !           190:                  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
        !           191:                break;
        !           192:  
        !           193:              /* The only valid case for this error is kernel's failure to install
        !           194:               * a multipath route, which is common for FreeBSD. This should be
        !           195:               * ignored silently, but logged as an error otherwise.
        !           196:               */
        !           197:              case ZEBRA_ERR_RTEXIST:
        !           198:                if (cmd != RTM_ADD)
        !           199:                  zlog_err ("%s: rtm_write() returned %d for command %d",
        !           200:                    __func__, error, cmd);
        !           201:                continue;
        !           202:                break;
        !           203:  
        !           204:              /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't
        !           205:               * normal to get any other messages in ANY case.
        !           206:               */
        !           207:              case ZEBRA_ERR_RTNOEXIST:
        !           208:              case ZEBRA_ERR_RTUNREACH:
        !           209:              default:
        !           210:                /* This point is reachable regardless of debugging mode. */
        !           211:                if (!IS_ZEBRA_DEBUG_RIB)
        !           212:                  inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN);
        !           213:                zlog_err ("%s: %s/%d: rtm_write() unexpectedly returned %d for command %s",
        !           214:                  __func__, prefix_buf, p->prefixlen, error, lookup (rtm_type_str, cmd));
        !           215:                break;
        !           216:            }
        !           217:          } /* if (cmd and flags make sense) */
        !           218:        else
        !           219:          if (IS_ZEBRA_DEBUG_RIB)
        !           220:            zlog_debug ("%s: odd command %s for flags %d",
        !           221:              __func__, lookup (rtm_type_str, cmd), nexthop->flags);
        !           222:      } /* for (nexthop = ... */
        !           223:  
        !           224:    /* If there was no useful nexthop, then complain. */
        !           225:    if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL)
        !           226:      zlog_debug ("%s: No useful nexthops were found in RIB entry %p", __func__, rib);
        !           227: 
        !           228:   return 0; /*XXX*/
        !           229: }
        !           230: 
        !           231: int
        !           232: kernel_add_ipv4 (struct prefix *p, struct rib *rib)
        !           233: {
        !           234:   int route;
        !           235: 
        !           236:   if (zserv_privs.change(ZPRIVS_RAISE))
        !           237:     zlog (NULL, LOG_ERR, "Can't raise privileges");
        !           238:   route = kernel_rtm_ipv4 (RTM_ADD, p, rib, AF_INET);
        !           239:   if (zserv_privs.change(ZPRIVS_LOWER))
        !           240:     zlog (NULL, LOG_ERR, "Can't lower privileges");
        !           241: 
        !           242:   return route;
        !           243: }
        !           244: 
        !           245: int
        !           246: kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
        !           247: {
        !           248:   int route;
        !           249: 
        !           250:   if (zserv_privs.change(ZPRIVS_RAISE))
        !           251:     zlog (NULL, LOG_ERR, "Can't raise privileges");
        !           252:   route = kernel_rtm_ipv4 (RTM_DELETE, p, rib, AF_INET);
        !           253:   if (zserv_privs.change(ZPRIVS_LOWER))
        !           254:     zlog (NULL, LOG_ERR, "Can't lower privileges");
        !           255: 
        !           256:   return route;
        !           257: }
        !           258: 
        !           259: #ifdef HAVE_IPV6
        !           260: 
        !           261: /* Calculate sin6_len value for netmask socket value. */
        !           262: static int
        !           263: sin6_masklen (struct in6_addr mask)
        !           264: {
        !           265:   struct sockaddr_in6 sin6;
        !           266:   char *p, *lim;
        !           267:   int len;
        !           268: 
        !           269: #if defined (INRIA)
        !           270:   if (IN_ANYADDR6 (mask)) 
        !           271:     return sizeof (long);
        !           272: #else /* ! INRIA */
        !           273:   if (IN6_IS_ADDR_UNSPECIFIED (&mask)) 
        !           274:     return sizeof (long);
        !           275: #endif /* ! INRIA */
        !           276: 
        !           277:   sin6.sin6_addr = mask;
        !           278:   len = sizeof (struct sockaddr_in6);
        !           279: 
        !           280:   lim = (char *) & sin6.sin6_addr;
        !           281:   p = lim + sizeof (sin6.sin6_addr);
        !           282: 
        !           283:   while (*--p == 0 && p >= lim) 
        !           284:     len--;
        !           285: 
        !           286:   return len;
        !           287: }
        !           288: 
        !           289: /* Interface between zebra message and rtm message. */
        !           290: static int
        !           291: kernel_rtm_ipv6 (int message, struct prefix_ipv6 *dest,
        !           292:                 struct in6_addr *gate, int index, int flags)
        !           293: {
        !           294:   struct sockaddr_in6 *mask;
        !           295:   struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
        !           296: 
        !           297:   memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
        !           298:   sin_dest.sin6_family = AF_INET6;
        !           299: #ifdef SIN6_LEN
        !           300:   sin_dest.sin6_len = sizeof (struct sockaddr_in6);
        !           301: #endif /* SIN6_LEN */
        !           302: 
        !           303:   memset (&sin_mask, 0, sizeof (struct sockaddr_in6));
        !           304: 
        !           305:   memset (&sin_gate, 0, sizeof (struct sockaddr_in6));
        !           306:   sin_gate.sin6_family = AF_INET6;
        !           307: #ifdef SIN6_LEN
        !           308:   sin_gate.sin6_len = sizeof (struct sockaddr_in6);
        !           309: #endif /* SIN6_LEN */
        !           310: 
        !           311:   sin_dest.sin6_addr = dest->prefix;
        !           312: 
        !           313:   if (gate)
        !           314:     memcpy (&sin_gate.sin6_addr, gate, sizeof (struct in6_addr));
        !           315: 
        !           316:   /* Under kame set interface index to link local address. */
        !           317: #ifdef KAME
        !           318: 
        !           319: #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
        !           320:   do { \
        !           321:     (a).s6_addr[2] = ((i) >> 8) & 0xff; \
        !           322:     (a).s6_addr[3] = (i) & 0xff; \
        !           323:   } while (0)
        !           324: 
        !           325:   if (gate && IN6_IS_ADDR_LINKLOCAL(gate))
        !           326:     SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, index);
        !           327: #endif /* KAME */
        !           328: 
        !           329:   if (gate && dest->prefixlen == 128)
        !           330:     mask = NULL;
        !           331:   else
        !           332:     {
        !           333:       masklen2ip6 (dest->prefixlen, &sin_mask.sin6_addr);
        !           334:       sin_mask.sin6_family = AF_INET6;
        !           335: #ifdef SIN6_LEN
        !           336:       sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
        !           337: #endif /* SIN6_LEN */
        !           338:       mask = &sin_mask;
        !           339:     }
        !           340: 
        !           341:   return rtm_write (message, 
        !           342:                    (union sockunion *) &sin_dest,
        !           343:                    (union sockunion *) mask,
        !           344:                    gate ? (union sockunion *)&sin_gate : NULL,
        !           345:                    index,
        !           346:                    flags,
        !           347:                    0);
        !           348: }
        !           349: 
        !           350: /* Interface between zebra message and rtm message. */
        !           351: static int
        !           352: kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib,
        !           353:                           int family)
        !           354: {
        !           355:   struct sockaddr_in6 *mask;
        !           356:   struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
        !           357:   struct nexthop *nexthop;
        !           358:   int nexthop_num = 0;
        !           359:   unsigned int ifindex = 0;
        !           360:   int gate = 0;
        !           361:   int error;
        !           362: 
        !           363:   memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
        !           364:   sin_dest.sin6_family = AF_INET6;
        !           365: #ifdef SIN6_LEN
        !           366:   sin_dest.sin6_len = sizeof (struct sockaddr_in6);
        !           367: #endif /* SIN6_LEN */
        !           368:   sin_dest.sin6_addr = p->u.prefix6;
        !           369: 
        !           370:   memset (&sin_mask, 0, sizeof (struct sockaddr_in6));
        !           371: 
        !           372:   memset (&sin_gate, 0, sizeof (struct sockaddr_in6));
        !           373:   sin_gate.sin6_family = AF_INET6;
        !           374: #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
        !           375:   sin_gate.sin6_len = sizeof (struct sockaddr_in6);
        !           376: #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
        !           377: 
        !           378:   /* Make gateway. */
        !           379:   for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
        !           380:     {
        !           381:       gate = 0;
        !           382: 
        !           383:       if ((cmd == RTM_ADD
        !           384:           && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
        !           385:          || (cmd == RTM_DELETE
        !           386: #if 0
        !           387:              && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
        !           388: #endif
        !           389:              ))
        !           390:        {
        !           391:          if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
        !           392:            {
        !           393:              if (nexthop->rtype == NEXTHOP_TYPE_IPV6
        !           394:                  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
        !           395:                  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
        !           396:                {
        !           397:                  sin_gate.sin6_addr = nexthop->rgate.ipv6;
        !           398:                  gate = 1;
        !           399:                }
        !           400:              if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
        !           401:                  || nexthop->rtype == NEXTHOP_TYPE_IFNAME
        !           402:                  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
        !           403:                  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
        !           404:                ifindex = nexthop->rifindex;
        !           405:            }
        !           406:          else
        !           407:            {
        !           408:              if (nexthop->type == NEXTHOP_TYPE_IPV6
        !           409:                  || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
        !           410:                  || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
        !           411:                {
        !           412:                  sin_gate.sin6_addr = nexthop->gate.ipv6;
        !           413:                  gate = 1;
        !           414:                }
        !           415:              if (nexthop->type == NEXTHOP_TYPE_IFINDEX
        !           416:                  || nexthop->type == NEXTHOP_TYPE_IFNAME
        !           417:                  || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
        !           418:                  || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
        !           419:                ifindex = nexthop->ifindex;
        !           420:            }
        !           421: 
        !           422:          if (cmd == RTM_ADD)
        !           423:            SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
        !           424:        }
        !           425: 
        !           426:       /* Under kame set interface index to link local address. */
        !           427: #ifdef KAME
        !           428: 
        !           429: #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
        !           430:       do { \
        !           431:        (a).s6_addr[2] = ((i) >> 8) & 0xff; \
        !           432:        (a).s6_addr[3] = (i) & 0xff; \
        !           433:       } while (0)
        !           434: 
        !           435:       if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr))
        !           436:        SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, ifindex);
        !           437: #endif /* KAME */
        !           438: 
        !           439:       if (gate && p->prefixlen == 128)
        !           440:        mask = NULL;
        !           441:       else
        !           442:        {
        !           443:          masklen2ip6 (p->prefixlen, &sin_mask.sin6_addr);
        !           444:          sin_mask.sin6_family = AF_INET6;
        !           445: #ifdef SIN6_LEN
        !           446:          sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
        !           447: #endif /* SIN6_LEN */
        !           448:          mask = &sin_mask;
        !           449:        }
        !           450: 
        !           451:       error = rtm_write (cmd,
        !           452:                        (union sockunion *) &sin_dest,
        !           453:                        (union sockunion *) mask,
        !           454:                        gate ? (union sockunion *)&sin_gate : NULL,
        !           455:                        ifindex,
        !           456:                        rib->flags,
        !           457:                        rib->metric);
        !           458: 
        !           459: #if 0
        !           460:       if (error)
        !           461:        {
        !           462:          zlog_info ("kernel_rtm_ipv6_multipath(): nexthop %d add error=%d.",
        !           463:            nexthop_num, error);
        !           464:        }
        !           465: #endif
        !           466: 
        !           467:       nexthop_num++;
        !           468:     }
        !           469: 
        !           470:   /* If there is no useful nexthop then return. */
        !           471:   if (nexthop_num == 0)
        !           472:     {
        !           473:       if (IS_ZEBRA_DEBUG_KERNEL)
        !           474:        zlog_debug ("kernel_rtm_ipv6_multipath(): No useful nexthop.");
        !           475:       return 0;
        !           476:     }
        !           477: 
        !           478:   return 0; /*XXX*/
        !           479: }
        !           480: 
        !           481: int
        !           482: kernel_add_ipv6 (struct prefix *p, struct rib *rib)
        !           483: {
        !           484:   int route;
        !           485: 
        !           486:   if (zserv_privs.change(ZPRIVS_RAISE))
        !           487:     zlog (NULL, LOG_ERR, "Can't raise privileges");
        !           488:   route =  kernel_rtm_ipv6_multipath (RTM_ADD, p, rib, AF_INET6);
        !           489:   if (zserv_privs.change(ZPRIVS_LOWER))
        !           490:     zlog (NULL, LOG_ERR, "Can't lower privileges");
        !           491: 
        !           492:   return route;
        !           493: }
        !           494: 
        !           495: int
        !           496: kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
        !           497: {
        !           498:   int route;
        !           499: 
        !           500:   if (zserv_privs.change(ZPRIVS_RAISE))
        !           501:     zlog (NULL, LOG_ERR, "Can't raise privileges");
        !           502:   route =  kernel_rtm_ipv6_multipath (RTM_DELETE, p, rib, AF_INET6);
        !           503:   if (zserv_privs.change(ZPRIVS_LOWER))
        !           504:     zlog (NULL, LOG_ERR, "Can't lower privileges");
        !           505: 
        !           506:   return route;
        !           507: }
        !           508: 
        !           509: /* Delete IPv6 route from the kernel. */
        !           510: int
        !           511: kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
        !           512:                        unsigned int index, int flags, int table)
        !           513: {
        !           514:   int route;
        !           515: 
        !           516:   if (zserv_privs.change(ZPRIVS_RAISE))
        !           517:     zlog (NULL, LOG_ERR, "Can't raise privileges");
        !           518:   route = kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index, flags);
        !           519:   if (zserv_privs.change(ZPRIVS_LOWER))
        !           520:     zlog (NULL, LOG_ERR, "Can't lower privileges");
        !           521: 
        !           522:   return route;
        !           523: }
        !           524: #endif /* HAVE_IPV6 */

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