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>