Coverage Report

Created: 2026-01-10 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/radvd/interface.c
Line
Count
Source
1
/*
2
 *
3
 *   Authors:
4
 *    Lars Fenneberg    <lf@elemental.net>
5
 *
6
 *   This software is Copyright 1996,1997 by the above mentioned author(s),
7
 *   All Rights Reserved.
8
 *
9
 *   The license which is distributed with this software in the file COPYRIGHT
10
 *   applies to this software. If your distribution is missing this file, you
11
 *   may request it from <reubenhwk@gmail.com>.
12
 *
13
 */
14
15
#include "config.h"
16
#include "defaults.h"
17
#include "includes.h"
18
#include "radvd.h"
19
20
#define IFACE_SETUP_DELAY 1
21
22
void iface_init_defaults(struct Interface *iface)
23
0
{
24
0
  memset(iface, 0, sizeof(struct Interface));
25
26
0
  iface->state_info.changed = 1;
27
28
0
  iface->IgnoreIfMissing = DFLT_IgnoreIfMissing;
29
0
  iface->AdvSendAdvert = DFLT_AdvSendAdv;
30
0
  iface->MaxRtrAdvInterval = DFLT_MaxRtrAdvInterval;
31
0
  iface->AdvSourceLLAddress = DFLT_AdvSourceLLAddress;
32
0
  iface->RemoveAdvOnExit = DFLT_RemoveAdvOnExit;
33
0
  iface->MinDelayBetweenRAs = DFLT_MinDelayBetweenRAs;
34
0
  iface->MinRtrAdvInterval = -1;
35
0
  iface->UnicastOnly = DFLT_UnicastOnly;
36
0
  iface->UnrestrictedUnicast = DFLT_UnrestrictedUnicast;
37
0
  iface->AdvRASolicitedUnicast = DFLT_AdvRASolicitedUnicast;
38
39
0
  iface->ra_header_info.AdvDefaultPreference = DFLT_AdvDefaultPreference;
40
0
  iface->ra_header_info.AdvDefaultLifetime = -1;
41
0
  iface->ra_header_info.AdvReachableTime = DFLT_AdvReachableTime;
42
0
  iface->ra_header_info.AdvRetransTimer = DFLT_AdvRetransTimer;
43
0
  iface->ra_header_info.AdvCurHopLimit = DFLT_AdvCurHopLimit;
44
0
  iface->ra_header_info.AdvHomeAgentFlag = DFLT_AdvHomeAgentFlag;
45
46
0
  iface->mipv6.AdvIntervalOpt = DFLT_AdvIntervalOpt;
47
0
  iface->mipv6.AdvHomeAgentInfo = DFLT_AdvHomeAgentInfo;
48
0
  iface->mipv6.HomeAgentPreference = DFLT_HomeAgentPreference;
49
0
  iface->mipv6.AdvMobRtrSupportFlag = DFLT_AdvMobRtrSupportFlag;
50
0
  iface->mipv6.HomeAgentLifetime = -1;
51
52
0
  iface->AdvLinkMTU = DFLT_AdvLinkMTU;
53
0
  iface->AdvRAMTU = DFLT_AdvRAMTU;
54
0
}
55
56
void touch_iface(struct Interface *iface)
57
0
{
58
0
  iface->state_info.changed = 1;
59
0
  iface->state_info.ready = 0;
60
0
  iface->state_info.racount = 0;
61
0
  reschedule_iface(iface, 0);
62
0
}
63
64
int setup_iface(int sock, struct Interface *iface)
65
0
{
66
0
  iface->state_info.changed = 0;
67
0
  iface->state_info.ready = 0;
68
69
  /* The device index must be setup first so we can search it later */
70
0
  if (update_device_index(iface) < 0) {
71
0
    return -1;
72
0
  }
73
74
  /* Check IFF_UP, IFF_RUNNING and IFF_MULTICAST */
75
0
  if (check_device(sock, iface) < 0) {
76
0
    return -2;
77
0
  }
78
79
  /* Set iface->max_mtu and iface hardware address */
80
0
  if (update_device_info(sock, iface) < 0) {
81
0
    return -3;
82
0
  }
83
84
  /* Make sure the settings in the config file for this interface are ok (this depends
85
   * on iface->max_mtu already being set). */
86
0
  if (check_iface(iface) < 0) {
87
0
    return -4;
88
0
  }
89
90
  /* Save the first link local address seen on the specified interface to
91
   * iface->props.if_addr and keep a list off all addrs in iface->props.if_addrs */
92
0
  if (setup_iface_addrs(iface) < 0) {
93
0
    return -5;
94
0
  }
95
96
  /* Check if we a usable RA source address */
97
0
  if (iface->props.if_addr_rasrc == NULL) {
98
0
    dlog(LOG_DEBUG, 5, "no configured AdvRASrcAddress present, skipping send");
99
0
    return -6;
100
0
  }
101
102
  /* join the allrouters multicast group so we get the solicitations */
103
0
  if (setup_allrouters_membership(sock, iface) < 0) {
104
0
    return -7;
105
0
  }
106
107
0
  iface->state_info.ready = 1;
108
109
0
  dlog(LOG_DEBUG, 4, "%s is ready", iface->props.name);
110
111
0
  return 0;
112
0
}
113
114
int cleanup_iface(int sock, struct Interface *iface)
115
0
{
116
  /* leave the allrouters multicast group */
117
0
  cleanup_allrouters_membership(sock, iface);
118
0
  return 0;
119
0
}
120
void prefix_init_defaults(struct AdvPrefix *prefix)
121
0
{
122
0
  memset(prefix, 0, sizeof(struct AdvPrefix));
123
124
0
  prefix->AdvOnLinkFlag = DFLT_AdvOnLinkFlag;
125
0
  prefix->AdvAutonomousFlag = DFLT_AdvAutonomousFlag;
126
0
  prefix->AdvRouterAddr = DFLT_AdvRouterAddr;
127
0
  prefix->AdvValidLifetime = DFLT_AdvValidLifetime;
128
0
  prefix->AdvPreferredLifetime = DFLT_AdvPreferredLifetime;
129
0
  prefix->DeprecatePrefixFlag = DFLT_DeprecatePrefixFlag;
130
0
  prefix->DecrementLifetimesFlag = DFLT_DecrementLifetimesFlag;
131
132
0
  prefix->curr_validlft = prefix->AdvValidLifetime;
133
0
  prefix->curr_preferredlft = prefix->AdvPreferredLifetime;
134
0
}
135
136
void nat64prefix_init_defaults(struct NAT64Prefix *prefix, struct Interface *iface)
137
0
{
138
0
  memset(prefix, 0, sizeof(struct NAT64Prefix));
139
140
0
  prefix->AdvValidLifetime = min(DFLT_NAT64MaxValidLifetime, 3*(iface->MaxRtrAdvInterval));
141
142
0
  prefix->curr_validlft = prefix->AdvValidLifetime;
143
0
}
144
145
void route_init_defaults(struct AdvRoute *route, struct Interface *iface)
146
0
{
147
0
  memset(route, 0, sizeof(struct AdvRoute));
148
149
0
  route->AdvRouteLifetime = DFLT_AdvRouteLifetime(iface);
150
0
  route->AdvRoutePreference = DFLT_AdvRoutePreference;
151
0
  route->RemoveRouteFlag = DFLT_RemoveRouteFlag;
152
0
}
153
154
void rdnss_init_defaults(struct AdvRDNSS *rdnss, struct Interface *iface)
155
0
{
156
0
  memset(rdnss, 0, sizeof(struct AdvRDNSS));
157
158
0
  rdnss->AdvRDNSSLifetime = DFLT_AdvRDNSSLifetime(iface);
159
0
  rdnss->AdvRDNSSNumber = 0;
160
0
  rdnss->FlushRDNSSFlag = DFLT_FlushRDNSSFlag;
161
0
}
162
163
void dnssl_init_defaults(struct AdvDNSSL *dnssl, struct Interface *iface)
164
0
{
165
0
  memset(dnssl, 0, sizeof(struct AdvDNSSL));
166
167
0
  dnssl->AdvDNSSLLifetime = DFLT_AdvDNSSLLifetime(iface);
168
0
  dnssl->FlushDNSSLFlag = DFLT_FlushDNSSLFlag;
169
0
}
170
171
int check_iface(struct Interface *iface)
172
0
{
173
0
  int res = 0;
174
0
  int MIPv6 = 0;
175
0
  struct in6_addr zeroaddr;
176
0
  memset(&zeroaddr, 0, sizeof(zeroaddr));
177
178
  /* Check if we use Mobile IPv6 extensions */
179
0
  if (iface->ra_header_info.AdvHomeAgentFlag || iface->mipv6.AdvHomeAgentInfo || iface->mipv6.AdvIntervalOpt) {
180
0
    MIPv6 = 1;
181
0
    flog(LOG_INFO, "using Mobile IPv6 extensions");
182
0
  }
183
184
  /* Check forwarding on interface */
185
0
  if (check_ip6_iface_forwarding(iface->props.name) < 1) {
186
0
    flog(LOG_WARNING, "IPv6 forwarding on interface seems to be disabled, but continuing anyway");
187
0
  }
188
189
0
  struct AdvPrefix *prefix = iface->AdvPrefixList;
190
0
  while (!MIPv6 && prefix) {
191
0
    if (prefix->AdvRouterAddr) {
192
0
      MIPv6 = 1;
193
0
    }
194
0
    prefix = prefix->next;
195
0
  }
196
197
0
  if (iface->MinRtrAdvInterval < 0)
198
0
    iface->MinRtrAdvInterval = DFLT_MinRtrAdvInterval(iface);
199
200
0
  if ((iface->MinRtrAdvInterval < (MIPv6 ? MIN_MinRtrAdvInterval_MIPv6 : MIN_MinRtrAdvInterval)) ||
201
0
      (iface->MinRtrAdvInterval > MAX_MinRtrAdvInterval(iface))) {
202
0
    flog(LOG_ERR,
203
0
         "MinRtrAdvInterval for %s (%.2f) must be at least %.2f but no more than 3/4 of MaxRtrAdvInterval (%.2f)",
204
0
         iface->props.name, iface->MinRtrAdvInterval,
205
0
         MIPv6 ? MIN_MinRtrAdvInterval_MIPv6 : (int)MIN_MinRtrAdvInterval, MAX_MinRtrAdvInterval(iface));
206
0
    res = -1;
207
0
  }
208
209
0
  if ((iface->MaxRtrAdvInterval < (MIPv6 ? MIN_MaxRtrAdvInterval_MIPv6 : MIN_MaxRtrAdvInterval)) ||
210
0
      (iface->MaxRtrAdvInterval > MAX_MaxRtrAdvInterval)) {
211
0
    flog(LOG_ERR, "MaxRtrAdvInterval for %s (%.2f) must be between %.2f and %d", iface->props.name,
212
0
         iface->MaxRtrAdvInterval, MIPv6 ? MIN_MaxRtrAdvInterval_MIPv6 : (int)MIN_MaxRtrAdvInterval,
213
0
         MAX_MaxRtrAdvInterval);
214
0
    res = -1;
215
0
  }
216
217
0
  if (iface->MinDelayBetweenRAs < (MIPv6 ? MIN_DELAY_BETWEEN_RAS_MIPv6 : MIN_DELAY_BETWEEN_RAS)) {
218
0
    flog(LOG_ERR, "MinDelayBetweenRAs for %s (%.2f) must be at least %.2f", iface->props.name,
219
0
         iface->MinDelayBetweenRAs, MIPv6 ? MIN_DELAY_BETWEEN_RAS_MIPv6 : MIN_DELAY_BETWEEN_RAS);
220
0
    res = -1;
221
0
  }
222
223
0
  if ((iface->AdvLinkMTU != 0) && ((iface->AdvLinkMTU < MIN_AdvLinkMTU) ||
224
0
           (iface->sllao.if_maxmtu != -1 && (iface->AdvLinkMTU > iface->sllao.if_maxmtu)))) {
225
0
    flog(LOG_ERR, "AdvLinkMTU for %s (%u) must be zero or between %u and %u", iface->props.name, iface->AdvLinkMTU,
226
0
         MIN_AdvLinkMTU, iface->sllao.if_maxmtu);
227
0
    res = -1;
228
0
  }
229
230
0
  if (iface->ra_header_info.AdvReachableTime > MAX_AdvReachableTime) {
231
0
    flog(LOG_ERR, "AdvReachableTime for %s (%u) must not be greater than %u", iface->props.name,
232
0
         iface->ra_header_info.AdvReachableTime, MAX_AdvReachableTime);
233
0
    res = -1;
234
0
  }
235
236
0
  if (iface->ra_header_info.AdvDefaultLifetime < 0)
237
0
    iface->ra_header_info.AdvDefaultLifetime = DFLT_AdvDefaultLifetime(iface);
238
239
0
  if ((iface->ra_header_info.AdvDefaultLifetime != 0) &&
240
0
      ((iface->ra_header_info.AdvDefaultLifetime > MAX_AdvDefaultLifetime) ||
241
0
       (iface->ra_header_info.AdvDefaultLifetime < MIN_AdvDefaultLifetime(iface)))) {
242
0
    flog(LOG_ERR, "AdvDefaultLifetime for %s (%u) must be zero or between %u and %u", iface->props.name,
243
0
         iface->ra_header_info.AdvDefaultLifetime, (int)MIN_AdvDefaultLifetime(iface), MAX_AdvDefaultLifetime);
244
0
    res = -1;
245
0
  }
246
247
  /* Mobile IPv6 ext */
248
0
  if (iface->mipv6.HomeAgentLifetime < 0)
249
0
    iface->mipv6.HomeAgentLifetime = DFLT_HomeAgentLifetime(iface);
250
251
  /* Mobile IPv6 ext */
252
0
  if (iface->mipv6.AdvHomeAgentInfo) {
253
0
    if ((iface->mipv6.HomeAgentLifetime > MAX_HomeAgentLifetime) ||
254
0
        (iface->mipv6.HomeAgentLifetime < MIN_HomeAgentLifetime)) {
255
0
      flog(LOG_ERR, "HomeAgentLifetime for %s (%u) must be between %u and %u", iface->props.name,
256
0
           iface->mipv6.HomeAgentLifetime, MIN_HomeAgentLifetime, MAX_HomeAgentLifetime);
257
0
      res = -1;
258
0
    }
259
0
  }
260
261
  /* Mobile IPv6 ext */
262
0
  if (iface->mipv6.AdvHomeAgentInfo && !(iface->ra_header_info.AdvHomeAgentFlag)) {
263
0
    flog(LOG_ERR, "AdvHomeAgentFlag for %s must be set with HomeAgentInfo", iface->props.name);
264
0
    res = -1;
265
0
  }
266
0
  if (iface->mipv6.AdvMobRtrSupportFlag && !(iface->mipv6.AdvHomeAgentInfo)) {
267
0
    flog(LOG_ERR, "AdvHomeAgentInfo for %s must be set with AdvMobRtrSupportFlag", iface->props.name);
268
0
    res = -1;
269
0
  }
270
271
  /* XXX: need this? prefix = iface->AdvPrefixList; */
272
273
0
  while (prefix) {
274
0
    if (prefix->PrefixLen > MAX_PrefixLen) {
275
0
      flog(LOG_ERR, "invalid prefix length (%u) for %s", prefix->PrefixLen, iface->props.name);
276
0
      res = -1;
277
0
    }
278
279
0
    if (prefix->AdvPreferredLifetime > prefix->AdvValidLifetime) {
280
0
      flog(LOG_ERR, "AdvValidLifetime for %s (%u) must be "
281
0
              "greater than or equal to AdvPreferredLifetime for",
282
0
           iface->props.name, prefix->AdvValidLifetime);
283
0
      res = -1;
284
0
    }
285
286
0
    prefix = prefix->next;
287
0
  }
288
289
0
  struct AdvRoute *route = iface->AdvRouteList;
290
0
  while (route) {
291
0
    if (route->PrefixLen > MAX_PrefixLen) {
292
0
      flog(LOG_ERR, "invalid route prefix length (%u) for %s", route->PrefixLen, iface->props.name);
293
0
      res = -1;
294
0
    }
295
296
    /* For the default route 0::/0, we need to explicitly check the
297
     * lifetime against the AdvDefaultLifetime value.
298
     *
299
     * If exactly one of the two has a zero value, then nodes processing
300
     * the RA may have a flap in their default route.
301
     *
302
     * AdvDefaultLifetime == 0 && route.AdvRouteLifetime > 0:
303
     * - default route is deleted and then re-added.
304
     * AdvDefaultLifetime > 0 && route.AdvRouteLifetime == 0:
305
     * - default route is added and then deleted.
306
     */
307
0
    if (IN6_IS_ADDR_UNSPECIFIED(&(route->Prefix))) {
308
0
      int route_zerolife = (route->AdvRouteLifetime == 0);
309
0
      int defaultroute_zerolife = (iface->ra_header_info.AdvDefaultLifetime == 0);
310
0
      if (route_zerolife ^ defaultroute_zerolife) {
311
0
        flog(
312
0
            LOG_ERR,
313
0
            "route 0::/0 lifetime (%u) conflicts with AdvDefaultLifetime (%u), default routes will flap!",
314
0
            route->AdvRouteLifetime, iface->ra_header_info.AdvDefaultLifetime);
315
        // res = -1; // In some future version, abort on this configuration error.
316
0
      }
317
0
    }
318
319
0
    route = route->next;
320
0
  }
321
322
0
  return res;
323
0
}
324
325
struct Interface *find_iface_by_index(struct Interface *iface, int index)
326
0
{
327
0
  for (; iface; iface = iface->next) {
328
0
    if (iface->props.if_index == index) {
329
0
      return iface;
330
0
    }
331
0
  }
332
333
0
  return 0;
334
0
}
335
336
struct Interface *find_iface_by_name(struct Interface *iface, const char *name)
337
0
{
338
0
  if (!name) {
339
0
    return 0;
340
0
  }
341
342
0
  for (; iface; iface = iface->next) {
343
0
    if (strcmp(iface->props.name, name) == 0) {
344
0
      return iface;
345
0
    }
346
0
  }
347
348
0
  return 0;
349
0
}
350
351
struct Interface *find_iface_by_time(struct Interface *iface)
352
0
{
353
0
  if (!iface) {
354
0
    return 0;
355
0
  }
356
357
0
  int timeout = next_time_msec(iface);
358
0
  struct Interface *next = iface;
359
360
0
  for (iface = iface->next; iface; iface = iface->next) {
361
0
    int t = next_time_msec(iface);
362
0
    if (timeout > t) {
363
0
      timeout = t;
364
0
      next = iface;
365
0
    }
366
0
  }
367
368
0
  return next;
369
0
}
370
371
void reschedule_iface(struct Interface *iface, double next)
372
0
{
373
#ifdef HAVE_NETLINK
374
  if (!iface->state_info.changed && !iface->state_info.ready) {
375
    next = 10 * iface->MaxRtrAdvInterval;
376
  } else if (next == 0) {
377
    next = IFACE_SETUP_DELAY;
378
  } else
379
#endif
380
0
      if (iface->state_info.racount < MAX_INITIAL_RTR_ADVERTISEMENTS) {
381
0
    next = min(MAX_INITIAL_RTR_ADVERT_INTERVAL, iface->MaxRtrAdvInterval);
382
0
  }
383
384
0
  dlog(LOG_DEBUG, 5, "%s next scheduled RA in %g second(s)", iface->props.name, next);
385
386
0
  iface->times.next_multicast = next_timespec(next);
387
0
}
388
389
void for_each_iface(struct Interface *ifaces, void (*foo)(struct Interface *, void *), void *data)
390
0
{
391
0
  for (; ifaces; ifaces = ifaces->next) {
392
0
    foo(ifaces, data);
393
0
  }
394
0
}
395
396
static void free_iface_list(struct Interface *iface)
397
549
{
398
549
  while (iface) {
399
0
    struct Interface *next_iface = iface->next;
400
401
0
    dlog(LOG_DEBUG, 4, "freeing interface %s", iface->props.name);
402
403
0
    struct AdvPrefix *prefix = iface->AdvPrefixList;
404
0
    while (prefix) {
405
0
      struct AdvPrefix *next_prefix = prefix->next;
406
407
0
      free(prefix);
408
0
      prefix = next_prefix;
409
0
    }
410
411
0
    struct AdvRoute *route = iface->AdvRouteList;
412
0
    while (route) {
413
0
      struct AdvRoute *next_route = route->next;
414
415
0
      free(route);
416
0
      route = next_route;
417
0
    }
418
419
0
    struct AdvRDNSS *rdnss = iface->AdvRDNSSList;
420
0
    while (rdnss) {
421
0
      struct AdvRDNSS *next_rdnss = rdnss->next;
422
423
0
      free(rdnss->AdvRDNSSAddr);
424
0
      free(rdnss);
425
0
      rdnss = next_rdnss;
426
0
    }
427
428
0
    struct AdvDNSSL *dnssl = iface->AdvDNSSLList;
429
0
    while (dnssl) {
430
0
      struct AdvDNSSL *next_dnssl = dnssl->next;
431
432
0
      for (int i = 0; i < dnssl->AdvDNSSLNumber; i++)
433
0
        free(dnssl->AdvDNSSLSuffixes[i]);
434
0
      free(dnssl->AdvDNSSLSuffixes);
435
0
      free(dnssl);
436
437
0
      dnssl = next_dnssl;
438
0
    }
439
440
0
    struct AutogenIgnorePrefix *ignore_prefixes = iface->IgnorePrefixList;
441
0
    while (ignore_prefixes) {
442
0
      struct AutogenIgnorePrefix *next_ignore_prefix = ignore_prefixes->next;
443
444
0
      free(ignore_prefixes);
445
0
      ignore_prefixes = next_ignore_prefix;
446
0
    }
447
448
0
    struct Clients *clients = iface->ClientList;
449
0
    while (clients) {
450
0
      struct Clients *next_client = clients->next;
451
452
0
      free(clients);
453
0
      clients = next_client;
454
0
    }
455
456
0
    free(iface->props.if_addrs);
457
458
0
    free(iface->AdvCaptivePortalAPI);
459
460
0
    free(iface);
461
0
    iface = next_iface;
462
0
  }
463
549
}
464
465
void free_ifaces(struct Interface *ifaces)
466
549
{
467
549
  dlog(LOG_DEBUG, 3, "Freeing Interfaces");
468
469
549
  free_iface_list(ifaces);
470
549
}