blob: 1980007f4025976c79b42e0734acdd2fd9c7b5b0 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/*
2 * Address linked list routine.
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 "prefix.h"
26#include "linklist.h"
27#include "if.h"
28#include "table.h"
29#include "rib.h"
30#include "table.h"
31#include "log.h"
paul0752ef02005-11-03 12:35:21 +000032#include "memory.h"
paul718e3742002-12-13 20:15:29 +000033
34#include "zebra/zserv.h"
35#include "zebra/redistribute.h"
hassoeef1fe12004-10-03 18:46:08 +000036#include "zebra/interface.h"
paula1ac18c2005-06-28 17:17:12 +000037#include "zebra/connected.h"
Denis Ovsienko6ce80bd2007-11-12 14:55:01 +000038extern struct zebra_t zebrad;
David Lamparter6b0655a2014-06-04 06:53:35 +020039
Christian Franke02b48052013-01-24 14:04:49 +000040/* communicate the withdrawal of a connected address */
paulca162182005-09-12 16:58:52 +000041static void
42connected_withdraw (struct connected *ifc)
43{
44 if (! ifc)
45 return;
46
47 /* Update interface address information to protocol daemon. */
48 if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
49 {
50 zebra_interface_address_delete_update (ifc->ifp, ifc);
51
Christian Franke9db047f2013-01-24 14:04:44 +000052 if (ifc->address->family == AF_INET)
53 if_subnet_delete (ifc->ifp, ifc);
54
paulca162182005-09-12 16:58:52 +000055 if (ifc->address->family == AF_INET)
56 connected_down_ipv4 (ifc->ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +000057#ifdef HAVE_IPV6
paulca162182005-09-12 16:58:52 +000058 else
59 connected_down_ipv6 (ifc->ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +000060#endif
paulca162182005-09-12 16:58:52 +000061
62 UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
63 }
64
Christian Frankef7f740f2013-01-24 14:04:48 +000065 /* The address is not in the kernel anymore, so clear the flag */
66 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
67
Andrew J. Schorr9c378512006-05-21 04:04:49 +000068 if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
69 {
70 listnode_delete (ifc->ifp->connected, ifc);
71 connected_free (ifc);
72 }
paulca162182005-09-12 16:58:52 +000073}
74
75static void
76connected_announce (struct interface *ifp, struct connected *ifc)
77{
78 if (!ifc)
79 return;
Donald Sharp4c7efde2015-11-16 18:19:18 -050080
81 if (!if_is_loopback(ifp) && ifc->address->family == AF_INET)
82 {
83 if (ifc->address->prefixlen == 32)
84 SET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
85 else
86 UNSET_FLAG (ifc->flags, ZEBRA_IFA_UNNUMBERED);
87 }
88
paulca162182005-09-12 16:58:52 +000089 listnode_add (ifp->connected, ifc);
90
91 /* Update interface address information to protocol daemon. */
Christian Franke02b48052013-01-24 14:04:49 +000092 if (ifc->address->family == AF_INET)
93 if_subnet_add (ifp, ifc);
94
95 zebra_interface_address_add_update (ifp, ifc);
96
97 if (if_is_operative(ifp))
paulca162182005-09-12 16:58:52 +000098 {
99 if (ifc->address->family == AF_INET)
Christian Franke02b48052013-01-24 14:04:49 +0000100 connected_up_ipv4 (ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +0000101#ifdef HAVE_IPV6
Christian Franke02b48052013-01-24 14:04:49 +0000102 else
103 connected_up_ipv6 (ifp, ifc);
vincentaa2e32b2005-09-28 13:42:11 +0000104#endif
paulca162182005-09-12 16:58:52 +0000105 }
106}
David Lamparter6b0655a2014-06-04 06:53:35 +0200107
paul718e3742002-12-13 20:15:29 +0000108/* If same interface address is already exist... */
109struct connected *
paulca162182005-09-12 16:58:52 +0000110connected_check (struct interface *ifp, struct prefix *p)
paul718e3742002-12-13 20:15:29 +0000111{
112 struct connected *ifc;
hasso52dc7ee2004-09-23 19:18:23 +0000113 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000114
paul1eb8ef22005-04-07 07:30:20 +0000115 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
116 if (prefix_same (ifc->address, p))
117 return ifc;
paul718e3742002-12-13 20:15:29 +0000118
paul718e3742002-12-13 20:15:29 +0000119 return NULL;
120}
121
Christian Franke02b48052013-01-24 14:04:49 +0000122/* Check if two ifc's describe the same address in the same state */
Paul Jakma74ecdc92006-06-15 18:10:47 +0000123static int
124connected_same (struct connected *ifc1, struct connected *ifc2)
125{
126 if (ifc1->ifp != ifc2->ifp)
127 return 0;
128
129 if (ifc1->destination)
130 if (!ifc2->destination)
131 return 0;
132 if (ifc2->destination)
133 if (!ifc1->destination)
134 return 0;
135
136 if (ifc1->destination && ifc2->destination)
137 if (!prefix_same (ifc1->destination, ifc2->destination))
138 return 0;
139
140 if (ifc1->flags != ifc2->flags)
141 return 0;
Christian Franke02b48052013-01-24 14:04:49 +0000142
143 if (ifc1->conf != ifc2->conf)
144 return 0;
Paul Jakma74ecdc92006-06-15 18:10:47 +0000145
146 return 1;
147}
148
Christian Franked7f5dad2013-01-24 14:04:46 +0000149/* Handle changes to addresses and send the neccesary announcements
150 * to clients. */
151static void
152connected_update(struct interface *ifp, struct connected *ifc)
Paul Jakma74ecdc92006-06-15 18:10:47 +0000153{
154 struct connected *current;
155
156 /* Check same connected route. */
157 if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
158 {
159 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
160 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
161
162 /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
163 * back an address we have already added.
164 */
Christian Franke02b48052013-01-24 14:04:49 +0000165 if (connected_same (current, ifc))
Paul Jakma74ecdc92006-06-15 18:10:47 +0000166 {
167 /* nothing to do */
168 connected_free (ifc);
Christian Franked7f5dad2013-01-24 14:04:46 +0000169 return;
Paul Jakma74ecdc92006-06-15 18:10:47 +0000170 }
Christian Franked7f5dad2013-01-24 14:04:46 +0000171
172 /* Clear the configured flag on the old ifc, so it will be freed by
173 * connected withdraw. */
Paul Jakma74ecdc92006-06-15 18:10:47 +0000174 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
175 connected_withdraw (current); /* implicit withdraw - freebsd does this */
176 }
Christian Franked7f5dad2013-01-24 14:04:46 +0000177
Christian Franke02b48052013-01-24 14:04:49 +0000178 /* If the connected is new or has changed, announce it, if it is usable */
179 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
180 connected_announce(ifp, ifc);
Paul Jakma74ecdc92006-06-15 18:10:47 +0000181}
182
paul718e3742002-12-13 20:15:29 +0000183/* Called from if_up(). */
184void
185connected_up_ipv4 (struct interface *ifp, struct connected *ifc)
186{
187 struct prefix_ipv4 p;
paul718e3742002-12-13 20:15:29 +0000188
189 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
190 return;
191
Andrew J. Schorre4529632006-12-12 19:18:21 +0000192 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000193
194 /* Apply mask to the network. */
195 apply_mask_ipv4 (&p);
196
197 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
198 address. */
199 if (prefix_ipv4_any (&p))
200 return;
201
Paul Jakma7514fb72007-05-02 16:05:35 +0000202 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
Timo Teräsb11f3b52015-11-02 16:50:07 +0200203 ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000204
G.Balaji42cb6b62012-04-02 23:31:29 +0530205 rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
Timo Teräsb11f3b52015-11-02 16:50:07 +0200206 ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST);
G.Balaji42cb6b62012-04-02 23:31:29 +0530207
Feng Lu0d0686f2015-05-22 11:40:02 +0200208 rib_update (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000209}
210
211/* Add connected IPv4 route to the interface. */
212void
213connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
pauld06b2a62005-10-11 03:53:54 +0000214 u_char prefixlen, struct in_addr *broad,
215 const char *label)
paul718e3742002-12-13 20:15:29 +0000216{
217 struct prefix_ipv4 *p;
218 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +0000219
220 /* Make connected structure. */
221 ifc = connected_new ();
222 ifc->ifp = ifp;
223 ifc->flags = flags;
Christian Frankef7f740f2013-01-24 14:04:48 +0000224 /* If we get a notification from the kernel,
225 * we can safely assume the address is known to the kernel */
226 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
paul718e3742002-12-13 20:15:29 +0000227
228 /* Allocate new connected address. */
229 p = prefix_ipv4_new ();
230 p->family = AF_INET;
231 p->prefix = *addr;
232 p->prefixlen = prefixlen;
233 ifc->address = (struct prefix *) p;
paulca162182005-09-12 16:58:52 +0000234
Andrew J. Schorre4529632006-12-12 19:18:21 +0000235 /* If there is broadcast or peer address. */
paul718e3742002-12-13 20:15:29 +0000236 if (broad)
237 {
238 p = prefix_ipv4_new ();
239 p->family = AF_INET;
240 p->prefix = *broad;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000241 p->prefixlen = prefixlen;
paul718e3742002-12-13 20:15:29 +0000242 ifc->destination = (struct prefix *) p;
hasso3fb9cd62004-10-19 19:44:43 +0000243
244 /* validate the destination address */
Andrew J. Schorre4529632006-12-12 19:18:21 +0000245 if (CONNECTED_PEER(ifc))
hasso3fb9cd62004-10-19 19:44:43 +0000246 {
247 if (IPV4_ADDR_SAME(addr,broad))
Andrew J. Schorre4529632006-12-12 19:18:21 +0000248 zlog_warn("warning: interface %s has same local and peer "
hasso3fb9cd62004-10-19 19:44:43 +0000249 "address %s, routing protocols may malfunction",
250 ifp->name,inet_ntoa(*addr));
hasso3fb9cd62004-10-19 19:44:43 +0000251 }
252 else
253 {
254 if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
255 {
256 char buf[2][INET_ADDRSTRLEN];
257 struct in_addr bcalc;
258 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
259 zlog_warn("warning: interface %s broadcast addr %s/%d != "
260 "calculated %s, routing protocols may malfunction",
261 ifp->name,
262 inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
263 prefixlen,
264 inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
265 }
266 }
267
paul718e3742002-12-13 20:15:29 +0000268 }
hasso3fb9cd62004-10-19 19:44:43 +0000269 else
Andrew J. Schorre4529632006-12-12 19:18:21 +0000270 {
271 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
272 {
273 zlog_warn("warning: %s called for interface %s "
274 "with peer flag set, but no peer address supplied",
275 __func__, ifp->name);
276 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
277 }
278
279 /* no broadcast or destination address was supplied */
280 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
281 zlog_warn("warning: PtP interface %s with addr %s/%d needs a "
282 "peer address",ifp->name,inet_ntoa(*addr),prefixlen);
283 }
paul718e3742002-12-13 20:15:29 +0000284
285 /* Label of this address. */
286 if (label)
paul0752ef02005-11-03 12:35:21 +0000287 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
paul718e3742002-12-13 20:15:29 +0000288
Christian Franke02b48052013-01-24 14:04:49 +0000289 /* For all that I know an IPv4 address is always ready when we receive
290 * the notification. So it should be safe to set the REAL flag here. */
291 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
292
Christian Franked7f5dad2013-01-24 14:04:46 +0000293 connected_update(ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000294}
295
296void
297connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
298{
299 struct prefix_ipv4 p;
paul718e3742002-12-13 20:15:29 +0000300
301 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
302 return;
303
Andrew J. Schorre4529632006-12-12 19:18:21 +0000304 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000305
306 /* Apply mask to the network. */
307 apply_mask_ipv4 (&p);
308
309 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
310 address. */
311 if (prefix_ipv4_any (&p))
312 return;
313
Denis Ovsienko6ce80bd2007-11-12 14:55:01 +0000314 /* Same logic as for connected_up_ipv4(): push the changes into the head. */
Feng Lu0d0686f2015-05-22 11:40:02 +0200315 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
316 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000317
Feng Lu0d0686f2015-05-22 11:40:02 +0200318 rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
319 SAFI_MULTICAST);
G.Balaji42cb6b62012-04-02 23:31:29 +0530320
Feng Lu0d0686f2015-05-22 11:40:02 +0200321 rib_update (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000322}
323
324/* Delete connected IPv4 route to the interface. */
325void
326connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
paul0752ef02005-11-03 12:35:21 +0000327 u_char prefixlen, struct in_addr *broad)
paul718e3742002-12-13 20:15:29 +0000328{
329 struct prefix_ipv4 p;
330 struct connected *ifc;
331
332 memset (&p, 0, sizeof (struct prefix_ipv4));
333 p.family = AF_INET;
334 p.prefix = *addr;
335 p.prefixlen = prefixlen;
336
paulca162182005-09-12 16:58:52 +0000337 ifc = connected_check (ifp, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000338 if (! ifc)
339 return;
paulca162182005-09-12 16:58:52 +0000340
341 connected_withdraw (ifc);
Stephen Hemminger90d2ab02009-04-29 21:54:59 -0700342
Feng Lu0d0686f2015-05-22 11:40:02 +0200343 rib_update (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000344}
345
346#ifdef HAVE_IPV6
paul718e3742002-12-13 20:15:29 +0000347void
348connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
349{
350 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +0000351
352 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
353 return;
354
Andrew J. Schorre4529632006-12-12 19:18:21 +0000355 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000356
357 /* Apply mask to the network. */
358 apply_mask_ipv6 (&p);
359
David Lamparter6d6df302014-06-28 21:12:37 +0200360#ifndef LINUX
hasso726f9b22003-05-25 21:04:54 +0000361 /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
paul718e3742002-12-13 20:15:29 +0000362 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
363 return;
hasso726f9b22003-05-25 21:04:54 +0000364#endif
paul718e3742002-12-13 20:15:29 +0000365
Feng Lu0d0686f2015-05-22 11:40:02 +0200366 rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
Timo Teräsb11f3b52015-11-02 16:50:07 +0200367 RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000368
Feng Lu0d0686f2015-05-22 11:40:02 +0200369 rib_update (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000370}
371
372/* Add connected IPv6 route to the interface. */
373void
Andrew J. Schorre4529632006-12-12 19:18:21 +0000374connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr,
paul89368d92005-11-26 09:14:07 +0000375 u_char prefixlen, struct in6_addr *broad,
376 const char *label)
paul718e3742002-12-13 20:15:29 +0000377{
378 struct prefix_ipv6 *p;
379 struct connected *ifc;
paul718e3742002-12-13 20:15:29 +0000380
381 /* Make connected structure. */
382 ifc = connected_new ();
383 ifc->ifp = ifp;
Andrew J. Schorre4529632006-12-12 19:18:21 +0000384 ifc->flags = flags;
Christian Frankef7f740f2013-01-24 14:04:48 +0000385 /* If we get a notification from the kernel,
386 * we can safely assume the address is known to the kernel */
387 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
paul718e3742002-12-13 20:15:29 +0000388
389 /* Allocate new connected address. */
390 p = prefix_ipv6_new ();
391 p->family = AF_INET6;
392 IPV6_ADDR_COPY (&p->prefix, addr);
393 p->prefixlen = prefixlen;
394 ifc->address = (struct prefix *) p;
395
Andrew J. Schorre4529632006-12-12 19:18:21 +0000396 /* If there is broadcast or peer address. */
paul718e3742002-12-13 20:15:29 +0000397 if (broad)
398 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000399 if (IN6_IS_ADDR_UNSPECIFIED(broad))
400 zlog_warn("warning: %s called for interface %s with unspecified "
401 "destination address; ignoring!", __func__, ifp->name);
402 else
403 {
404 p = prefix_ipv6_new ();
405 p->family = AF_INET6;
406 IPV6_ADDR_COPY (&p->prefix, broad);
407 p->prefixlen = prefixlen;
408 ifc->destination = (struct prefix *) p;
409 }
410 }
411 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination)
412 {
413 zlog_warn("warning: %s called for interface %s "
414 "with peer flag set, but no peer address supplied",
415 __func__, ifp->name);
416 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
paul718e3742002-12-13 20:15:29 +0000417 }
418
paul0752ef02005-11-03 12:35:21 +0000419 /* Label of this address. */
420 if (label)
421 ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
Christian Franked7f5dad2013-01-24 14:04:46 +0000422
Christian Franke02b48052013-01-24 14:04:49 +0000423 /* On Linux, we only get here when DAD is complete, therefore we can set
424 * ZEBRA_IFC_REAL.
425 *
426 * On BSD, there currently doesn't seem to be a way to check for completion of
427 * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD
428 * might still be running.
429 */
430 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
Christian Franked7f5dad2013-01-24 14:04:46 +0000431 connected_update(ifp, ifc);
paul718e3742002-12-13 20:15:29 +0000432}
433
434void
435connected_down_ipv6 (struct interface *ifp, struct connected *ifc)
436{
437 struct prefix_ipv6 p;
paul718e3742002-12-13 20:15:29 +0000438
439 if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
440 return;
441
Andrew J. Schorre4529632006-12-12 19:18:21 +0000442 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
paul718e3742002-12-13 20:15:29 +0000443
444 apply_mask_ipv6 (&p);
445
446 if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
447 return;
448
Feng Lu0d0686f2015-05-22 11:40:02 +0200449 rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
450 SAFI_UNICAST);
paul718e3742002-12-13 20:15:29 +0000451
Feng Lu0d0686f2015-05-22 11:40:02 +0200452 rib_update (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000453}
454
455void
456connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
hassofce954f2004-10-07 20:29:24 +0000457 u_char prefixlen, struct in6_addr *broad)
paul718e3742002-12-13 20:15:29 +0000458{
459 struct prefix_ipv6 p;
460 struct connected *ifc;
461
462 memset (&p, 0, sizeof (struct prefix_ipv6));
463 p.family = AF_INET6;
464 memcpy (&p.prefix, address, sizeof (struct in6_addr));
465 p.prefixlen = prefixlen;
466
paulca162182005-09-12 16:58:52 +0000467 ifc = connected_check (ifp, (struct prefix *) &p);
paul718e3742002-12-13 20:15:29 +0000468 if (! ifc)
469 return;
470
paulca162182005-09-12 16:58:52 +0000471 connected_withdraw (ifc);
Stephen Hemminger90d2ab02009-04-29 21:54:59 -0700472
Feng Lu0d0686f2015-05-22 11:40:02 +0200473 rib_update (ifp->vrf_id);
paul718e3742002-12-13 20:15:29 +0000474}
475#endif /* HAVE_IPV6 */