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>