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