~ubuntu-branches/ubuntu/breezy/quagga/breezy-security

« back to all changes in this revision

Viewing changes to zebra/rt_netlink.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-05-20 13:16:12 UTC
  • Revision ID: james.westby@ubuntu.com-20050520131612-pr6paalox60o3x3n
Tags: upstream-0.99.1
ImportĀ upstreamĀ versionĀ 0.99.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Kernel routing table updates using netlink over GNU/Linux system.
 
2
 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
 
3
 *
 
4
 * This file is part of GNU Zebra.
 
5
 *
 
6
 * GNU Zebra is free software; you can redistribute it and/or modify it
 
7
 * under the terms of the GNU General Public License as published by the
 
8
 * Free Software Foundation; either version 2, or (at your option) any
 
9
 * later version.
 
10
 *
 
11
 * GNU Zebra is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with GNU Zebra; see the file COPYING.  If not, write to the Free
 
18
 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
19
 * 02111-1307, USA.  
 
20
 */
 
21
 
 
22
#include <zebra.h>
 
23
 
 
24
/* Hack for GNU libc version 2. */
 
25
#ifndef MSG_TRUNC
 
26
#define MSG_TRUNC      0x20
 
27
#endif /* MSG_TRUNC */
 
28
 
 
29
#include "linklist.h"
 
30
#include "if.h"
 
31
#include "log.h"
 
32
#include "prefix.h"
 
33
#include "connected.h"
 
34
#include "table.h"
 
35
#include "rib.h"
 
36
#include "thread.h"
 
37
#include "privs.h"
 
38
 
 
39
#include "zebra/zserv.h"
 
40
#include "zebra/redistribute.h"
 
41
#include "zebra/interface.h"
 
42
#include "zebra/debug.h"
 
43
 
 
44
/* Socket interface to kernel */
 
45
struct nlsock
 
46
{
 
47
  int sock;
 
48
  int seq;
 
49
  struct sockaddr_nl snl;
 
50
  const char *name;
 
51
} netlink      = { -1, 0, {0}, "netlink-listen"},     /* kernel messages */
 
52
  netlink_cmd  = { -1, 0, {0}, "netlink-cmd"},        /* command channel */
 
53
  netlink_addr = { -1, 0, {0}, "netlink-addr"};       /* address channel */
 
54
 
 
55
struct message nlmsg_str[] = {
 
56
  {RTM_NEWROUTE, "RTM_NEWROUTE"},
 
57
  {RTM_DELROUTE, "RTM_DELROUTE"},
 
58
  {RTM_GETROUTE, "RTM_GETROUTE"},
 
59
  {RTM_NEWLINK,  "RTM_NEWLINK"},
 
60
  {RTM_DELLINK,  "RTM_DELLINK"},
 
61
  {RTM_GETLINK,  "RTM_GETLINK"},
 
62
  {RTM_NEWADDR,  "RTM_NEWADDR"},
 
63
  {RTM_DELADDR,  "RTM_DELADDR"},
 
64
  {RTM_GETADDR,  "RTM_GETADDR"},
 
65
  {0, NULL}
 
66
};
 
67
 
 
68
const char *nexthop_types_desc[] =  
 
69
{
 
70
  "none",
 
71
  "Directly connected",
 
72
  "Interface route",
 
73
  "IPv4 nexthop",
 
74
  "IPv4 nexthop with ifindex",
 
75
  "IPv4 nexthop with ifname",
 
76
  "IPv6 nexthop",
 
77
  "IPv6 nexthop with ifindex",
 
78
  "IPv6 nexthop with ifname",
 
79
  "Null0 nexthop",
 
80
};
 
81
 
 
82
 
 
83
extern struct zebra_t zebrad;
 
84
 
 
85
extern struct zebra_privs_t zserv_privs;
 
86
 
 
87
extern u_int32_t nl_rcvbufsize;
 
88
 
 
89
/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
 
90
   names and ifindex values. */
 
91
static void
 
92
set_ifindex(struct interface *ifp, unsigned int ifi_index)
 
93
{
 
94
  struct interface *oifp;
 
95
 
 
96
  if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
 
97
    {
 
98
      if (ifi_index == IFINDEX_INTERNAL)
 
99
        zlog_err("Netlink is setting interface %s ifindex to reserved "
 
100
                 "internal value %u", ifp->name, ifi_index);
 
101
      else
 
102
        {
 
103
          if (IS_ZEBRA_DEBUG_KERNEL)
 
104
            zlog_debug("interface index %d was renamed from %s to %s",
 
105
                       ifi_index, oifp->name, ifp->name);
 
106
          if (if_is_up(oifp))
 
107
            zlog_err("interface rename detected on up interface: index %d "
 
108
                     "was renamed from %s to %s, results are uncertain!", 
 
109
                     ifi_index, oifp->name, ifp->name);
 
110
          if_delete_update(oifp);
 
111
        }
 
112
    }
 
113
  ifp->ifindex = ifi_index;
 
114
}
 
115
 
 
116
/* Make socket for Linux netlink interface. */
 
117
static int
 
118
netlink_socket (struct nlsock *nl, unsigned long groups)
 
119
{
 
120
  int ret;
 
121
  struct sockaddr_nl snl;
 
122
  int sock;
 
123
  int namelen;
 
124
  int save_errno;
 
125
 
 
126
  sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
 
127
  if (sock < 0)
 
128
    {
 
129
      zlog (NULL, LOG_ERR, "Can't open %s socket: %s", nl->name,
 
130
            safe_strerror (errno));
 
131
      return -1;
 
132
    }
 
133
 
 
134
  ret = fcntl (sock, F_SETFL, O_NONBLOCK);
 
135
  if (ret < 0)
 
136
    {
 
137
      zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name,
 
138
            safe_strerror (errno));
 
139
      close (sock);
 
140
      return -1;
 
141
    }
 
142
 
 
143
  /* Set receive buffer size if it's set from command line */
 
144
  if (nl_rcvbufsize)
 
145
    {
 
146
      u_int32_t oldsize, oldlen;
 
147
      u_int32_t newsize, newlen;
 
148
 
 
149
      oldlen = sizeof(oldsize);
 
150
      newlen = sizeof(newsize);
 
151
 
 
152
      ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen);
 
153
      if (ret < 0)
 
154
        {
 
155
          zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
 
156
                safe_strerror (errno));
 
157
          close (sock);
 
158
          return -1;
 
159
        }
 
160
 
 
161
      ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize,
 
162
                       sizeof(nl_rcvbufsize));
 
163
      if (ret < 0)
 
164
        {
 
165
          zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name,
 
166
                safe_strerror (errno));
 
167
          close (sock);
 
168
          return -1;
 
169
        }
 
170
 
 
171
      ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen);
 
172
      if (ret < 0)
 
173
        {
 
174
          zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name,
 
175
                safe_strerror (errno));
 
176
          close (sock);
 
177
          return -1;
 
178
        }
 
179
 
 
180
      zlog (NULL, LOG_INFO,
 
181
            "Setting netlink socket receive buffer size: %u -> %u",
 
182
            oldsize, newsize);
 
183
    }
 
184
 
 
185
  memset (&snl, 0, sizeof snl);
 
186
  snl.nl_family = AF_NETLINK;
 
187
  snl.nl_groups = groups;
 
188
 
 
189
  /* Bind the socket to the netlink structure for anything. */
 
190
  if (zserv_privs.change (ZPRIVS_RAISE))
 
191
    {
 
192
      zlog (NULL, LOG_ERR, "Can't raise privileges");
 
193
      return -1;
 
194
    }
 
195
 
 
196
  ret = bind (sock, (struct sockaddr *) &snl, sizeof snl);
 
197
  save_errno = errno;
 
198
  if (zserv_privs.change (ZPRIVS_LOWER))
 
199
    zlog (NULL, LOG_ERR, "Can't lower privileges");
 
200
 
 
201
  if (ret < 0)
 
202
    {
 
203
      zlog (NULL, LOG_ERR, "Can't bind %s socket to group 0x%x: %s",
 
204
            nl->name, snl.nl_groups, safe_strerror (save_errno));
 
205
      close (sock);
 
206
      return -1;
 
207
    }
 
208
 
 
209
  /* multiple netlink sockets will have different nl_pid */
 
210
  namelen = sizeof snl;
 
211
  ret = getsockname (sock, (struct sockaddr *) &snl, (socklen_t *) &namelen);
 
212
  if (ret < 0 || namelen != sizeof snl)
 
213
    {
 
214
      zlog (NULL, LOG_ERR, "Can't get %s socket name: %s", nl->name,
 
215
            safe_strerror (errno));
 
216
      close (sock);
 
217
      return -1;
 
218
    }
 
219
 
 
220
  nl->snl = snl;
 
221
  nl->sock = sock;
 
222
  return ret;
 
223
}
 
224
 
 
225
int
 
226
set_netlink_blocking (struct nlsock *nl, int *flags)
 
227
{
 
228
 
 
229
  /* Change socket flags for blocking I/O.  */
 
230
  if ((*flags = fcntl (nl->sock, F_GETFL, 0)) < 0)
 
231
    {
 
232
      zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s",
 
233
            __FUNCTION__, __LINE__, safe_strerror (errno));
 
234
      return -1;
 
235
    }
 
236
  *flags &= ~O_NONBLOCK;
 
237
  if (fcntl (nl->sock, F_SETFL, *flags) < 0)
 
238
    {
 
239
      zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
 
240
            __FUNCTION__, __LINE__, safe_strerror (errno));
 
241
      return -1;
 
242
    }
 
243
  return 0;
 
244
}
 
245
 
 
246
int
 
247
set_netlink_nonblocking (struct nlsock *nl, int *flags)
 
248
{
 
249
  /* Restore socket flags for nonblocking I/O */
 
250
  *flags |= O_NONBLOCK;
 
251
  if (fcntl (nl->sock, F_SETFL, *flags) < 0)
 
252
    {
 
253
      zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s",
 
254
            __FUNCTION__, __LINE__, safe_strerror (errno));
 
255
      return -1;
 
256
    }
 
257
  return 0;
 
258
}
 
259
 
 
260
/* Get type specified information from netlink. */
 
261
static int
 
262
netlink_request (int family, int type, struct nlsock *nl)
 
263
{
 
264
  int ret;
 
265
  struct sockaddr_nl snl;
 
266
  int save_errno;
 
267
 
 
268
  struct
 
269
  {
 
270
    struct nlmsghdr nlh;
 
271
    struct rtgenmsg g;
 
272
  } req;
 
273
 
 
274
 
 
275
  /* Check netlink socket. */
 
276
  if (nl->sock < 0)
 
277
    {
 
278
      zlog (NULL, LOG_ERR, "%s socket isn't active.", nl->name);
 
279
      return -1;
 
280
    }
 
281
 
 
282
  memset (&snl, 0, sizeof snl);
 
283
  snl.nl_family = AF_NETLINK;
 
284
 
 
285
  req.nlh.nlmsg_len = sizeof req;
 
286
  req.nlh.nlmsg_type = type;
 
287
  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
 
288
  req.nlh.nlmsg_pid = 0;
 
289
  req.nlh.nlmsg_seq = ++nl->seq;
 
290
  req.g.rtgen_family = family;
 
291
 
 
292
  /* linux appears to check capabilities on every message 
 
293
   * have to raise caps for every message sent
 
294
   */
 
295
  if (zserv_privs.change (ZPRIVS_RAISE))
 
296
    {
 
297
      zlog (NULL, LOG_ERR, "Can't raise privileges");
 
298
      return -1;
 
299
    }
 
300
 
 
301
  ret = sendto (nl->sock, (void *) &req, sizeof req, 0,
 
302
                (struct sockaddr *) &snl, sizeof snl);
 
303
  save_errno = errno;
 
304
 
 
305
  if (zserv_privs.change (ZPRIVS_LOWER))
 
306
    zlog (NULL, LOG_ERR, "Can't lower privileges");
 
307
 
 
308
  if (ret < 0)
 
309
    {
 
310
      zlog (NULL, LOG_ERR, "%s sendto failed: %s", nl->name,
 
311
            safe_strerror (save_errno));
 
312
      return -1;
 
313
    }
 
314
 
 
315
  return 0;
 
316
}
 
317
 
 
318
/* Receive message from netlink interface and pass those information
 
319
   to the given function. */
 
320
static int
 
321
netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *),
 
322
                    struct nlsock *nl)
 
323
{
 
324
  int status;
 
325
  int ret = 0;
 
326
  int error;
 
327
 
 
328
  while (1)
 
329
    {
 
330
      char buf[4096];
 
331
      struct iovec iov = { buf, sizeof buf };
 
332
      struct sockaddr_nl snl;
 
333
      struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
 
334
      struct nlmsghdr *h;
 
335
      int save_errno;
 
336
 
 
337
      if (zserv_privs.change (ZPRIVS_RAISE))
 
338
        zlog (NULL, LOG_ERR, "Can't raise privileges");
 
339
 
 
340
      status = recvmsg (nl->sock, &msg, 0);
 
341
      save_errno = errno;
 
342
 
 
343
      if (zserv_privs.change (ZPRIVS_LOWER))
 
344
        zlog (NULL, LOG_ERR, "Can't lower privileges");
 
345
 
 
346
      if (status < 0)
 
347
        {
 
348
          if (save_errno == EINTR)
 
349
            continue;
 
350
          if (save_errno == EWOULDBLOCK || save_errno == EAGAIN)
 
351
            break;
 
352
          zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s",
 
353
                nl->name, safe_strerror(save_errno));
 
354
          continue;
 
355
        }
 
356
 
 
357
      if (status == 0)
 
358
        {
 
359
          zlog (NULL, LOG_ERR, "%s EOF", nl->name);
 
360
          return -1;
 
361
        }
 
362
 
 
363
      if (msg.msg_namelen != sizeof snl)
 
364
        {
 
365
          zlog (NULL, LOG_ERR, "%s sender address length error: length %d",
 
366
                nl->name, msg.msg_namelen);
 
367
          return -1;
 
368
        }
 
369
      
 
370
      /* JF: Ignore messages that aren't from the kernel */
 
371
      if ( snl.nl_pid != 0 )
 
372
        {
 
373
          zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl.nl_pid );
 
374
          continue;
 
375
        }
 
376
 
 
377
      for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status);
 
378
           h = NLMSG_NEXT (h, status))
 
379
        {
 
380
          /* Finish of reading. */
 
381
          if (h->nlmsg_type == NLMSG_DONE)
 
382
            return ret;
 
383
 
 
384
          /* Error handling. */
 
385
          if (h->nlmsg_type == NLMSG_ERROR)
 
386
            {
 
387
              struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h);
 
388
 
 
389
              /* If the error field is zero, then this is an ACK */
 
390
              if (err->error == 0)
 
391
                {
 
392
                  if (IS_ZEBRA_DEBUG_KERNEL)
 
393
                    {
 
394
                      zlog_debug ("%s: %s ACK: type=%s(%u), seq=%u, pid=%d",
 
395
                                 __FUNCTION__, nl->name,
 
396
                                 lookup (nlmsg_str, err->msg.nlmsg_type),
 
397
                                 err->msg.nlmsg_type, err->msg.nlmsg_seq,
 
398
                                 err->msg.nlmsg_pid);
 
399
                    }
 
400
 
 
401
                  /* return if not a multipart message, otherwise continue */
 
402
                  if (!(h->nlmsg_flags & NLM_F_MULTI))
 
403
                    {
 
404
                      return 0;
 
405
                    }
 
406
                  continue;
 
407
                }
 
408
 
 
409
              if (h->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
 
410
                {
 
411
                  zlog (NULL, LOG_ERR, "%s error: message truncated",
 
412
                        nl->name);
 
413
                  return -1;
 
414
                }
 
415
 
 
416
              /* Deal with Error Noise  - MAG */
 
417
              {
 
418
                int loglvl = LOG_ERR;
 
419
                int errnum = err->error;
 
420
                int msg_type = err->msg.nlmsg_type;
 
421
 
 
422
                if (nl == &netlink_cmd
 
423
                    && (-errnum == ENODEV || -errnum == ESRCH)
 
424
                    && (msg_type == RTM_NEWROUTE || msg_type == RTM_DELROUTE))
 
425
                  loglvl = LOG_DEBUG;
 
426
 
 
427
                zlog (NULL, loglvl, "%s error: %s, type=%s(%u), "
 
428
                      "seq=%u, pid=%d",
 
429
                      nl->name, safe_strerror (-errnum),
 
430
                      lookup (nlmsg_str, msg_type),
 
431
                      msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid);
 
432
              }
 
433
              /*
 
434
                 ret = -1;
 
435
                 continue;
 
436
               */
 
437
              return -1;
 
438
            }
 
439
 
 
440
          /* OK we got netlink message. */
 
441
          if (IS_ZEBRA_DEBUG_KERNEL)
 
442
            zlog_debug ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%d",
 
443
                       nl->name,
 
444
                       lookup (nlmsg_str, h->nlmsg_type), h->nlmsg_type,
 
445
                       h->nlmsg_seq, h->nlmsg_pid);
 
446
 
 
447
          /* skip unsolicited messages originating from command socket */
 
448
          if (nl != &netlink_cmd && h->nlmsg_pid == netlink_cmd.snl.nl_pid)
 
449
            {
 
450
              if (IS_ZEBRA_DEBUG_KERNEL)
 
451
                zlog_debug ("netlink_parse_info: %s packet comes from %s",
 
452
                           nl->name, netlink_cmd.name);
 
453
              continue;
 
454
            }
 
455
 
 
456
          error = (*filter) (&snl, h);
 
457
          if (error < 0)
 
458
            {
 
459
              zlog (NULL, LOG_ERR, "%s filter function error", nl->name);
 
460
              ret = error;
 
461
            }
 
462
        }
 
463
 
 
464
      /* After error care. */
 
465
      if (msg.msg_flags & MSG_TRUNC)
 
466
        {
 
467
          zlog (NULL, LOG_ERR, "%s error: message truncated", nl->name);
 
468
          continue;
 
469
        }
 
470
      if (status)
 
471
        {
 
472
          zlog (NULL, LOG_ERR, "%s error: data remnant size %d", nl->name,
 
473
                status);
 
474
          return -1;
 
475
        }
 
476
    }
 
477
  return ret;
 
478
}
 
479
 
 
480
/* Utility function for parse rtattr. */
 
481
static void
 
482
netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta,
 
483
                      int len)
 
484
{
 
485
  while (RTA_OK (rta, len))
 
486
    {
 
487
      if (rta->rta_type <= max)
 
488
        tb[rta->rta_type] = rta;
 
489
      rta = RTA_NEXT (rta, len);
 
490
    }
 
491
}
 
492
 
 
493
/* Called from interface_lookup_netlink().  This function is only used
 
494
   during bootstrap. */
 
495
int
 
496
netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h)
 
497
{
 
498
  int len;
 
499
  struct ifinfomsg *ifi;
 
500
  struct rtattr *tb[IFLA_MAX + 1];
 
501
  struct interface *ifp;
 
502
  char *name;
 
503
  int i;
 
504
 
 
505
  ifi = NLMSG_DATA (h);
 
506
 
 
507
  if (h->nlmsg_type != RTM_NEWLINK)
 
508
    return 0;
 
509
 
 
510
  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
 
511
  if (len < 0)
 
512
    return -1;
 
513
 
 
514
  /* Looking up interface name. */
 
515
  memset (tb, 0, sizeof tb);
 
516
  netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
 
517
  
 
518
#ifdef IFLA_WIRELESS
 
519
  /* check for wireless messages to ignore */
 
520
  if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
 
521
    {
 
522
      if (IS_ZEBRA_DEBUG_KERNEL)
 
523
        zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
 
524
      return 0;
 
525
    }
 
526
#endif /* IFLA_WIRELESS */
 
527
 
 
528
  if (tb[IFLA_IFNAME] == NULL)
 
529
    return -1;
 
530
  name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
 
531
 
 
532
  /* Add interface. */
 
533
  ifp = if_get_by_name (name);
 
534
  set_ifindex(ifp, ifi->ifi_index);
 
535
  ifp->flags = ifi->ifi_flags & 0x0000fffff;
 
536
  ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
 
537
  ifp->metric = 1;
 
538
 
 
539
  /* Hardware type and address. */
 
540
  ifp->hw_type = ifi->ifi_type;
 
541
 
 
542
  if (tb[IFLA_ADDRESS])
 
543
    {
 
544
      int hw_addr_len;
 
545
 
 
546
      hw_addr_len = RTA_PAYLOAD (tb[IFLA_ADDRESS]);
 
547
 
 
548
      if (hw_addr_len > INTERFACE_HWADDR_MAX)
 
549
        zlog_warn ("Hardware address is too large: %d", hw_addr_len);
 
550
      else
 
551
        {
 
552
          ifp->hw_addr_len = hw_addr_len;
 
553
          memcpy (ifp->hw_addr, RTA_DATA (tb[IFLA_ADDRESS]), hw_addr_len);
 
554
 
 
555
          for (i = 0; i < hw_addr_len; i++)
 
556
            if (ifp->hw_addr[i] != 0)
 
557
              break;
 
558
 
 
559
          if (i == hw_addr_len)
 
560
            ifp->hw_addr_len = 0;
 
561
          else
 
562
            ifp->hw_addr_len = hw_addr_len;
 
563
        }
 
564
    }
 
565
 
 
566
  if_add_update (ifp);
 
567
 
 
568
  return 0;
 
569
}
 
570
 
 
571
/* Lookup interface IPv4/IPv6 address. */
 
572
int
 
573
netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
 
574
{
 
575
  int len;
 
576
  struct ifaddrmsg *ifa;
 
577
  struct rtattr *tb[IFA_MAX + 1];
 
578
  struct interface *ifp;
 
579
  void *addr = NULL;
 
580
  void *broad = NULL;
 
581
  u_char flags = 0;
 
582
  char *label = NULL;
 
583
 
 
584
  ifa = NLMSG_DATA (h);
 
585
 
 
586
  if (ifa->ifa_family != AF_INET
 
587
#ifdef HAVE_IPV6
 
588
      && ifa->ifa_family != AF_INET6
 
589
#endif /* HAVE_IPV6 */
 
590
    )
 
591
    return 0;
 
592
 
 
593
  if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
 
594
    return 0;
 
595
 
 
596
  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
 
597
  if (len < 0)
 
598
    return -1;
 
599
 
 
600
  memset (tb, 0, sizeof tb);
 
601
  netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);
 
602
 
 
603
  ifp = if_lookup_by_index (ifa->ifa_index);
 
604
  if (ifp == NULL)
 
605
    {
 
606
      zlog_err ("netlink_interface_addr can't find interface by index %d",
 
607
                ifa->ifa_index);
 
608
      return -1;
 
609
    }
 
610
 
 
611
  if (IS_ZEBRA_DEBUG_KERNEL)    /* remove this line to see initial ifcfg */
 
612
    {
 
613
      char buf[BUFSIZ];
 
614
      zlog_debug ("netlink_interface_addr %s %s:",
 
615
                 lookup (nlmsg_str, h->nlmsg_type), ifp->name);
 
616
      if (tb[IFA_LOCAL])
 
617
        zlog_debug ("  IFA_LOCAL     %s/%d",
 
618
                    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
 
619
                               buf, BUFSIZ), ifa->ifa_prefixlen);
 
620
      if (tb[IFA_ADDRESS])
 
621
        zlog_debug ("  IFA_ADDRESS   %s/%d",
 
622
                    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
 
623
                               buf, BUFSIZ), ifa->ifa_prefixlen);
 
624
      if (tb[IFA_BROADCAST])
 
625
        zlog_debug ("  IFA_BROADCAST %s/%d",
 
626
                    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
 
627
                               buf, BUFSIZ), ifa->ifa_prefixlen);
 
628
      if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
 
629
        zlog_debug ("  IFA_LABEL     %s", (char *)RTA_DATA (tb[IFA_LABEL]));
 
630
    }
 
631
  
 
632
  if (tb[IFA_ADDRESS] == NULL)
 
633
    tb[IFA_ADDRESS] = tb[IFA_LOCAL];
 
634
  
 
635
  if (ifp->flags & IFF_POINTOPOINT)
 
636
    {
 
637
      if (tb[IFA_LOCAL])
 
638
        {
 
639
          addr = RTA_DATA (tb[IFA_LOCAL]);
 
640
          if (tb[IFA_ADDRESS] &&
 
641
              memcmp(RTA_DATA(tb[IFA_ADDRESS]),RTA_DATA(tb[IFA_LOCAL]),4))
 
642
            /* if IFA_ADDRESS != IFA_LOCAL, then it's the peer address */
 
643
            broad = RTA_DATA (tb[IFA_ADDRESS]);
 
644
          else
 
645
            broad = NULL;
 
646
        }
 
647
      else
 
648
        {
 
649
          if (tb[IFA_ADDRESS])
 
650
            addr = RTA_DATA (tb[IFA_ADDRESS]);
 
651
          else
 
652
            addr = NULL;
 
653
        }
 
654
    }
 
655
  else
 
656
    {
 
657
      if (tb[IFA_ADDRESS])
 
658
        addr = RTA_DATA (tb[IFA_ADDRESS]);
 
659
      else
 
660
        addr = NULL;
 
661
      
 
662
      if (tb[IFA_BROADCAST])
 
663
        broad = RTA_DATA(tb[IFA_BROADCAST]);
 
664
      else
 
665
        broad = NULL;
 
666
    }
 
667
 
 
668
  /* Flags. */
 
669
  if (ifa->ifa_flags & IFA_F_SECONDARY)
 
670
    SET_FLAG (flags, ZEBRA_IFA_SECONDARY);
 
671
 
 
672
  /* Label */
 
673
  if (tb[IFA_LABEL])
 
674
    label = (char *) RTA_DATA (tb[IFA_LABEL]);
 
675
 
 
676
  if (ifp && label && strcmp (ifp->name, label) == 0)
 
677
    label = NULL;
 
678
 
 
679
  /* Register interface address to the interface. */
 
680
  if (ifa->ifa_family == AF_INET)
 
681
    {
 
682
      if (h->nlmsg_type == RTM_NEWADDR)
 
683
        connected_add_ipv4 (ifp, flags,
 
684
                            (struct in_addr *) addr, ifa->ifa_prefixlen,
 
685
                            (struct in_addr *) broad, label);
 
686
      else
 
687
        connected_delete_ipv4 (ifp, flags,
 
688
                               (struct in_addr *) addr, ifa->ifa_prefixlen,
 
689
                               (struct in_addr *) broad, label);
 
690
    }
 
691
#ifdef HAVE_IPV6
 
692
  if (ifa->ifa_family == AF_INET6)
 
693
    {
 
694
      if (h->nlmsg_type == RTM_NEWADDR)
 
695
        connected_add_ipv6 (ifp,
 
696
                            (struct in6_addr *) addr, ifa->ifa_prefixlen,
 
697
                            (struct in6_addr *) broad);
 
698
      else
 
699
        connected_delete_ipv6 (ifp,
 
700
                               (struct in6_addr *) addr, ifa->ifa_prefixlen,
 
701
                               (struct in6_addr *) broad);
 
702
    }
 
703
#endif /* HAVE_IPV6 */
 
704
 
 
705
  return 0;
 
706
}
 
707
 
 
708
/* Looking up routing table by netlink interface. */
 
709
int
 
710
netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h)
 
711
{
 
712
  int len;
 
713
  struct rtmsg *rtm;
 
714
  struct rtattr *tb[RTA_MAX + 1];
 
715
  u_char flags = 0;
 
716
 
 
717
  char anyaddr[16] = { 0 };
 
718
 
 
719
  int index;
 
720
  int table;
 
721
  int metric;
 
722
 
 
723
  void *dest;
 
724
  void *gate;
 
725
 
 
726
  rtm = NLMSG_DATA (h);
 
727
 
 
728
  if (h->nlmsg_type != RTM_NEWROUTE)
 
729
    return 0;
 
730
  if (rtm->rtm_type != RTN_UNICAST)
 
731
    return 0;
 
732
 
 
733
  table = rtm->rtm_table;
 
734
#if 0                           /* we weed them out later in rib_weed_tables () */
 
735
  if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
 
736
    return 0;
 
737
#endif
 
738
 
 
739
  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
 
740
  if (len < 0)
 
741
    return -1;
 
742
 
 
743
  memset (tb, 0, sizeof tb);
 
744
  netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
 
745
 
 
746
  if (rtm->rtm_flags & RTM_F_CLONED)
 
747
    return 0;
 
748
  if (rtm->rtm_protocol == RTPROT_REDIRECT)
 
749
    return 0;
 
750
  if (rtm->rtm_protocol == RTPROT_KERNEL)
 
751
    return 0;
 
752
 
 
753
  if (rtm->rtm_src_len != 0)
 
754
    return 0;
 
755
 
 
756
  /* Route which inserted by Zebra. */
 
757
  if (rtm->rtm_protocol == RTPROT_ZEBRA)
 
758
    flags |= ZEBRA_FLAG_SELFROUTE;
 
759
 
 
760
  index = 0;
 
761
  metric = 0;
 
762
  dest = NULL;
 
763
  gate = NULL;
 
764
 
 
765
  if (tb[RTA_OIF])
 
766
    index = *(int *) RTA_DATA (tb[RTA_OIF]);
 
767
 
 
768
  if (tb[RTA_DST])
 
769
    dest = RTA_DATA (tb[RTA_DST]);
 
770
  else
 
771
    dest = anyaddr;
 
772
 
 
773
  /* Multipath treatment is needed. */
 
774
  if (tb[RTA_GATEWAY])
 
775
    gate = RTA_DATA (tb[RTA_GATEWAY]);
 
776
 
 
777
  if (tb[RTA_PRIORITY])
 
778
    metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
 
779
 
 
780
  if (rtm->rtm_family == AF_INET)
 
781
    {
 
782
      struct prefix_ipv4 p;
 
783
      p.family = AF_INET;
 
784
      memcpy (&p.prefix, dest, 4);
 
785
      p.prefixlen = rtm->rtm_dst_len;
 
786
 
 
787
      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, metric, 0);
 
788
    }
 
789
#ifdef HAVE_IPV6
 
790
  if (rtm->rtm_family == AF_INET6)
 
791
    {
 
792
      struct prefix_ipv6 p;
 
793
      p.family = AF_INET6;
 
794
      memcpy (&p.prefix, dest, 16);
 
795
      p.prefixlen = rtm->rtm_dst_len;
 
796
 
 
797
      rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table);
 
798
    }
 
799
#endif /* HAVE_IPV6 */
 
800
 
 
801
  return 0;
 
802
}
 
803
 
 
804
struct message rtproto_str[] = {
 
805
  {RTPROT_REDIRECT, "redirect"},
 
806
  {RTPROT_KERNEL,   "kernel"},
 
807
  {RTPROT_BOOT,     "boot"},
 
808
  {RTPROT_STATIC,   "static"},
 
809
  {RTPROT_GATED,    "GateD"},
 
810
  {RTPROT_RA,       "router advertisement"},
 
811
  {RTPROT_MRT,      "MRT"},
 
812
  {RTPROT_ZEBRA,    "Zebra"},
 
813
#ifdef RTPROT_BIRD
 
814
  {RTPROT_BIRD,     "BIRD"},
 
815
#endif /* RTPROT_BIRD */
 
816
  {0,               NULL}
 
817
};
 
818
 
 
819
/* Routing information change from the kernel. */
 
820
int
 
821
netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
 
822
{
 
823
  int len;
 
824
  struct rtmsg *rtm;
 
825
  struct rtattr *tb[RTA_MAX + 1];
 
826
 
 
827
  char anyaddr[16] = { 0 };
 
828
 
 
829
  int index;
 
830
  int table;
 
831
  void *dest;
 
832
  void *gate;
 
833
 
 
834
  rtm = NLMSG_DATA (h);
 
835
 
 
836
  if (!(h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
 
837
    {
 
838
      /* If this is not route add/delete message print warning. */
 
839
      zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
 
840
      return 0;
 
841
    }
 
842
 
 
843
  /* Connected route. */
 
844
  if (IS_ZEBRA_DEBUG_KERNEL)
 
845
    zlog_debug ("%s %s %s proto %s",
 
846
               h->nlmsg_type ==
 
847
               RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
 
848
               rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
 
849
               rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
 
850
               lookup (rtproto_str, rtm->rtm_protocol));
 
851
 
 
852
  if (rtm->rtm_type != RTN_UNICAST)
 
853
    {
 
854
      return 0;
 
855
    }
 
856
 
 
857
  table = rtm->rtm_table;
 
858
  if (table != RT_TABLE_MAIN && table != zebrad.rtm_table_default)
 
859
    {
 
860
      return 0;
 
861
    }
 
862
 
 
863
  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct rtmsg));
 
864
  if (len < 0)
 
865
    return -1;
 
866
 
 
867
  memset (tb, 0, sizeof tb);
 
868
  netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);
 
869
 
 
870
  if (rtm->rtm_flags & RTM_F_CLONED)
 
871
    return 0;
 
872
  if (rtm->rtm_protocol == RTPROT_REDIRECT)
 
873
    return 0;
 
874
  if (rtm->rtm_protocol == RTPROT_KERNEL)
 
875
    return 0;
 
876
 
 
877
  if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
 
878
    return 0;
 
879
 
 
880
  if (rtm->rtm_src_len != 0)
 
881
    {
 
882
      zlog_warn ("netlink_route_change(): no src len");
 
883
      return 0;
 
884
    }
 
885
 
 
886
  index = 0;
 
887
  dest = NULL;
 
888
  gate = NULL;
 
889
 
 
890
  if (tb[RTA_OIF])
 
891
    index = *(int *) RTA_DATA (tb[RTA_OIF]);
 
892
 
 
893
  if (tb[RTA_DST])
 
894
    dest = RTA_DATA (tb[RTA_DST]);
 
895
  else
 
896
    dest = anyaddr;
 
897
 
 
898
  if (tb[RTA_GATEWAY])
 
899
    gate = RTA_DATA (tb[RTA_GATEWAY]);
 
900
 
 
901
  if (rtm->rtm_family == AF_INET)
 
902
    {
 
903
      struct prefix_ipv4 p;
 
904
      p.family = AF_INET;
 
905
      memcpy (&p.prefix, dest, 4);
 
906
      p.prefixlen = rtm->rtm_dst_len;
 
907
 
 
908
      if (IS_ZEBRA_DEBUG_KERNEL)
 
909
        {
 
910
          if (h->nlmsg_type == RTM_NEWROUTE)
 
911
            zlog_debug ("RTM_NEWROUTE %s/%d",
 
912
                       inet_ntoa (p.prefix), p.prefixlen);
 
913
          else
 
914
            zlog_debug ("RTM_DELROUTE %s/%d",
 
915
                       inet_ntoa (p.prefix), p.prefixlen);
 
916
        }
 
917
 
 
918
      if (h->nlmsg_type == RTM_NEWROUTE)
 
919
        rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
 
920
      else
 
921
        rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
 
922
    }
 
923
 
 
924
#ifdef HAVE_IPV6
 
925
  if (rtm->rtm_family == AF_INET6)
 
926
    {
 
927
      struct prefix_ipv6 p;
 
928
      char buf[BUFSIZ];
 
929
 
 
930
      p.family = AF_INET6;
 
931
      memcpy (&p.prefix, dest, 16);
 
932
      p.prefixlen = rtm->rtm_dst_len;
 
933
 
 
934
      if (IS_ZEBRA_DEBUG_KERNEL)
 
935
        {
 
936
          if (h->nlmsg_type == RTM_NEWROUTE)
 
937
            zlog_debug ("RTM_NEWROUTE %s/%d",
 
938
                       inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
 
939
                       p.prefixlen);
 
940
          else
 
941
            zlog_debug ("RTM_DELROUTE %s/%d",
 
942
                       inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
 
943
                       p.prefixlen);
 
944
        }
 
945
 
 
946
      if (h->nlmsg_type == RTM_NEWROUTE)
 
947
        rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
 
948
      else
 
949
        rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
 
950
    }
 
951
#endif /* HAVE_IPV6 */
 
952
 
 
953
  return 0;
 
954
}
 
955
 
 
956
int
 
957
netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
 
958
{
 
959
  int len;
 
960
  struct ifinfomsg *ifi;
 
961
  struct rtattr *tb[IFLA_MAX + 1];
 
962
  struct interface *ifp;
 
963
  char *name;
 
964
 
 
965
  ifi = NLMSG_DATA (h);
 
966
 
 
967
  if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
 
968
    {
 
969
      /* If this is not link add/delete message so print warning. */
 
970
      zlog_warn ("netlink_link_change: wrong kernel message %d\n",
 
971
                 h->nlmsg_type);
 
972
      return 0;
 
973
    }
 
974
 
 
975
  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
 
976
  if (len < 0)
 
977
    return -1;
 
978
 
 
979
  /* Looking up interface name. */
 
980
  memset (tb, 0, sizeof tb);
 
981
  netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
 
982
 
 
983
#ifdef IFLA_WIRELESS
 
984
  /* check for wireless messages to ignore */
 
985
  if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
 
986
    {
 
987
      if (IS_ZEBRA_DEBUG_KERNEL)
 
988
        zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
 
989
      return 0;
 
990
    }
 
991
#endif /* IFLA_WIRELESS */
 
992
  
 
993
  if (tb[IFLA_IFNAME] == NULL)
 
994
    return -1;
 
995
  name = (char *) RTA_DATA (tb[IFLA_IFNAME]);
 
996
 
 
997
  /* Add interface. */
 
998
  if (h->nlmsg_type == RTM_NEWLINK)
 
999
    {
 
1000
      ifp = if_lookup_by_name (name);
 
1001
 
 
1002
      if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
 
1003
        {
 
1004
          if (ifp == NULL)
 
1005
            ifp = if_get_by_name (name);
 
1006
 
 
1007
          set_ifindex(ifp, ifi->ifi_index);
 
1008
          ifp->flags = ifi->ifi_flags & 0x0000fffff;
 
1009
          ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
 
1010
          ifp->metric = 1;
 
1011
 
 
1012
          /* If new link is added. */
 
1013
          if_add_update (ifp);
 
1014
        }
 
1015
      else
 
1016
        {
 
1017
          /* Interface status change. */
 
1018
          set_ifindex(ifp, ifi->ifi_index);
 
1019
          ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
 
1020
          ifp->metric = 1;
 
1021
 
 
1022
          if (if_is_operative (ifp))
 
1023
            {
 
1024
              ifp->flags = ifi->ifi_flags & 0x0000fffff;
 
1025
              if (!if_is_operative (ifp))
 
1026
                if_down (ifp);
 
1027
              else
 
1028
                /* Must notify client daemons of new interface status. */
 
1029
                zebra_interface_up_update (ifp);
 
1030
            }
 
1031
          else
 
1032
            {
 
1033
              ifp->flags = ifi->ifi_flags & 0x0000fffff;
 
1034
              if (if_is_operative (ifp))
 
1035
                if_up (ifp);
 
1036
            }
 
1037
        }
 
1038
    }
 
1039
  else
 
1040
    {
 
1041
      /* RTM_DELLINK. */
 
1042
      ifp = if_lookup_by_name (name);
 
1043
 
 
1044
      if (ifp == NULL)
 
1045
        {
 
1046
          zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
 
1047
                name);
 
1048
          return 0;
 
1049
        }
 
1050
 
 
1051
      if_delete_update (ifp);
 
1052
    }
 
1053
 
 
1054
  return 0;
 
1055
}
 
1056
 
 
1057
int
 
1058
netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h)
 
1059
{
 
1060
  switch (h->nlmsg_type)
 
1061
    {
 
1062
    case RTM_NEWROUTE:
 
1063
      return netlink_route_change (snl, h);
 
1064
      break;
 
1065
    case RTM_DELROUTE:
 
1066
      return netlink_route_change (snl, h);
 
1067
      break;
 
1068
    case RTM_NEWLINK:
 
1069
      return netlink_link_change (snl, h);
 
1070
      break;
 
1071
    case RTM_DELLINK:
 
1072
      return netlink_link_change (snl, h);
 
1073
      break;
 
1074
    case RTM_NEWADDR:
 
1075
      return netlink_interface_addr (snl, h);
 
1076
      break;
 
1077
    case RTM_DELADDR:
 
1078
      return netlink_interface_addr (snl, h);
 
1079
      break;
 
1080
    default:
 
1081
      zlog_warn ("Unknown netlink nlmsg_type %d\n", h->nlmsg_type);
 
1082
      break;
 
1083
    }
 
1084
  return 0;
 
1085
}
 
1086
 
 
1087
/* Interface lookup by netlink socket. */
 
1088
int
 
1089
interface_lookup_netlink ()
 
1090
{
 
1091
  int ret;
 
1092
  int flags;
 
1093
  int snb_ret;
 
1094
 
 
1095
  /* 
 
1096
   * Change netlink socket flags to blocking to ensure we get 
 
1097
   * a reply via nelink_parse_info
 
1098
   */
 
1099
  snb_ret = set_netlink_blocking (&netlink_cmd, &flags);
 
1100
  if (snb_ret < 0)
 
1101
    zlog (NULL, LOG_WARNING,
 
1102
          "%s:%i Warning: Could not set netlink socket to blocking.",
 
1103
          __FUNCTION__, __LINE__);
 
1104
 
 
1105
  /* Get interface information. */
 
1106
  ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd);
 
1107
  if (ret < 0)
 
1108
    return ret;
 
1109
  ret = netlink_parse_info (netlink_interface, &netlink_cmd);
 
1110
  if (ret < 0)
 
1111
    return ret;
 
1112
 
 
1113
  /* Get IPv4 address of the interfaces. */
 
1114
  ret = netlink_request (AF_INET, RTM_GETADDR, &netlink_cmd);
 
1115
  if (ret < 0)
 
1116
    return ret;
 
1117
  ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
 
1118
  if (ret < 0)
 
1119
    return ret;
 
1120
 
 
1121
#ifdef HAVE_IPV6
 
1122
  /* Get IPv6 address of the interfaces. */
 
1123
  ret = netlink_request (AF_INET6, RTM_GETADDR, &netlink_cmd);
 
1124
  if (ret < 0)
 
1125
    return ret;
 
1126
  ret = netlink_parse_info (netlink_interface_addr, &netlink_cmd);
 
1127
  if (ret < 0)
 
1128
    return ret;
 
1129
#endif /* HAVE_IPV6 */
 
1130
 
 
1131
  /* restore socket flags */
 
1132
  if (snb_ret == 0)
 
1133
    set_netlink_nonblocking (&netlink_cmd, &flags);
 
1134
  return 0;
 
1135
}
 
1136
 
 
1137
/* Routing table read function using netlink interface.  Only called
 
1138
   bootstrap time. */
 
1139
int
 
1140
netlink_route_read ()
 
1141
{
 
1142
  int ret;
 
1143
  int flags;
 
1144
  int snb_ret;
 
1145
 
 
1146
  /* 
 
1147
   * Change netlink socket flags to blocking to ensure we get 
 
1148
   * a reply via nelink_parse_info
 
1149
   */
 
1150
  snb_ret = set_netlink_blocking (&netlink_cmd, &flags);
 
1151
  if (snb_ret < 0)
 
1152
    zlog (NULL, LOG_WARNING,
 
1153
          "%s:%i Warning: Could not set netlink socket to blocking.",
 
1154
          __FUNCTION__, __LINE__);
 
1155
 
 
1156
  /* Get IPv4 routing table. */
 
1157
  ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd);
 
1158
  if (ret < 0)
 
1159
    return ret;
 
1160
  ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
 
1161
  if (ret < 0)
 
1162
    return ret;
 
1163
 
 
1164
#ifdef HAVE_IPV6
 
1165
  /* Get IPv6 routing table. */
 
1166
  ret = netlink_request (AF_INET6, RTM_GETROUTE, &netlink_cmd);
 
1167
  if (ret < 0)
 
1168
    return ret;
 
1169
  ret = netlink_parse_info (netlink_routing_table, &netlink_cmd);
 
1170
  if (ret < 0)
 
1171
    return ret;
 
1172
#endif /* HAVE_IPV6 */
 
1173
 
 
1174
  /* restore flags */
 
1175
  if (snb_ret == 0)
 
1176
    set_netlink_nonblocking (&netlink_cmd, &flags);
 
1177
  return 0;
 
1178
}
 
1179
 
 
1180
/* Utility function  comes from iproute2. 
 
1181
   Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
 
1182
int
 
1183
addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen)
 
1184
{
 
1185
  int len;
 
1186
  struct rtattr *rta;
 
1187
 
 
1188
  len = RTA_LENGTH (alen);
 
1189
 
 
1190
  if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
 
1191
    return -1;
 
1192
 
 
1193
  rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
 
1194
  rta->rta_type = type;
 
1195
  rta->rta_len = len;
 
1196
  memcpy (RTA_DATA (rta), data, alen);
 
1197
  n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
 
1198
 
 
1199
  return 0;
 
1200
}
 
1201
 
 
1202
int
 
1203
rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen)
 
1204
{
 
1205
  int len;
 
1206
  struct rtattr *subrta;
 
1207
 
 
1208
  len = RTA_LENGTH (alen);
 
1209
 
 
1210
  if (RTA_ALIGN (rta->rta_len) + len > maxlen)
 
1211
    return -1;
 
1212
 
 
1213
  subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len));
 
1214
  subrta->rta_type = type;
 
1215
  subrta->rta_len = len;
 
1216
  memcpy (RTA_DATA (subrta), data, alen);
 
1217
  rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len;
 
1218
 
 
1219
  return 0;
 
1220
}
 
1221
 
 
1222
/* Utility function comes from iproute2. 
 
1223
   Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
 
1224
int
 
1225
addattr32 (struct nlmsghdr *n, int maxlen, int type, int data)
 
1226
{
 
1227
  int len;
 
1228
  struct rtattr *rta;
 
1229
 
 
1230
  len = RTA_LENGTH (4);
 
1231
 
 
1232
  if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen)
 
1233
    return -1;
 
1234
 
 
1235
  rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len));
 
1236
  rta->rta_type = type;
 
1237
  rta->rta_len = len;
 
1238
  memcpy (RTA_DATA (rta), &data, 4);
 
1239
  n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len;
 
1240
 
 
1241
  return 0;
 
1242
}
 
1243
 
 
1244
static int
 
1245
netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
 
1246
{
 
1247
  zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
 
1248
  return 0;
 
1249
}
 
1250
 
 
1251
/* sendmsg() to netlink socket then recvmsg(). */
 
1252
int
 
1253
netlink_talk (struct nlmsghdr *n, struct nlsock *nl)
 
1254
{
 
1255
  int status;
 
1256
  struct sockaddr_nl snl;
 
1257
  struct iovec iov = { (void *) n, n->nlmsg_len };
 
1258
  struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 };
 
1259
  int flags = 0;
 
1260
  int snb_ret;
 
1261
  int save_errno;
 
1262
 
 
1263
  memset (&snl, 0, sizeof snl);
 
1264
  snl.nl_family = AF_NETLINK;
 
1265
 
 
1266
  n->nlmsg_seq = ++nl->seq;
 
1267
 
 
1268
  /* Request an acknowledgement by setting NLM_F_ACK */
 
1269
  n->nlmsg_flags |= NLM_F_ACK;
 
1270
 
 
1271
  if (IS_ZEBRA_DEBUG_KERNEL)
 
1272
    zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name,
 
1273
               lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type,
 
1274
               n->nlmsg_seq);
 
1275
 
 
1276
  /* Send message to netlink interface. */
 
1277
  if (zserv_privs.change (ZPRIVS_RAISE))
 
1278
    zlog (NULL, LOG_ERR, "Can't raise privileges");
 
1279
  status = sendmsg (nl->sock, &msg, 0);
 
1280
  save_errno = errno;
 
1281
  if (zserv_privs.change (ZPRIVS_LOWER))
 
1282
    zlog (NULL, LOG_ERR, "Can't lower privileges");
 
1283
 
 
1284
  if (status < 0)
 
1285
    {
 
1286
      zlog (NULL, LOG_ERR, "netlink_talk sendmsg() error: %s",
 
1287
            safe_strerror (save_errno));
 
1288
      return -1;
 
1289
    }
 
1290
 
 
1291
  /* 
 
1292
   * Change socket flags for blocking I/O. 
 
1293
   * This ensures we wait for a reply in netlink_parse_info().
 
1294
   */
 
1295
  snb_ret = set_netlink_blocking (nl, &flags);
 
1296
  if (snb_ret < 0)
 
1297
    zlog (NULL, LOG_WARNING,
 
1298
          "%s:%i Warning: Could not set netlink socket to blocking.",
 
1299
          __FUNCTION__, __LINE__);
 
1300
 
 
1301
  /* 
 
1302
   * Get reply from netlink socket. 
 
1303
   * The reply should either be an acknowlegement or an error.
 
1304
   */
 
1305
  status = netlink_parse_info (netlink_talk_filter, nl);
 
1306
 
 
1307
  /* Restore socket flags for nonblocking I/O */
 
1308
  if (snb_ret == 0)
 
1309
    set_netlink_nonblocking (nl, &flags);
 
1310
 
 
1311
  return status;
 
1312
}
 
1313
 
 
1314
/* Routing table change via netlink interface. */
 
1315
int
 
1316
netlink_route (int cmd, int family, void *dest, int length, void *gate,
 
1317
               int index, int zebra_flags, int table)
 
1318
{
 
1319
  int ret;
 
1320
  int bytelen;
 
1321
  struct sockaddr_nl snl;
 
1322
  int discard;
 
1323
 
 
1324
  struct
 
1325
  {
 
1326
    struct nlmsghdr n;
 
1327
    struct rtmsg r;
 
1328
    char buf[1024];
 
1329
  } req;
 
1330
 
 
1331
  memset (&req, 0, sizeof req);
 
1332
 
 
1333
  bytelen = (family == AF_INET ? 4 : 16);
 
1334
 
 
1335
  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
 
1336
  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
 
1337
  req.n.nlmsg_type = cmd;
 
1338
  req.r.rtm_family = family;
 
1339
  req.r.rtm_table = table;
 
1340
  req.r.rtm_dst_len = length;
 
1341
 
 
1342
  if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE)
 
1343
      || (zebra_flags & ZEBRA_FLAG_REJECT))
 
1344
    discard = 1;
 
1345
  else
 
1346
    discard = 0;
 
1347
 
 
1348
  if (cmd == RTM_NEWROUTE)
 
1349
    {
 
1350
      req.r.rtm_protocol = RTPROT_ZEBRA;
 
1351
      req.r.rtm_scope = RT_SCOPE_UNIVERSE;
 
1352
 
 
1353
      if (discard)
 
1354
        {
 
1355
          if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
 
1356
            req.r.rtm_type = RTN_BLACKHOLE;
 
1357
          else if (zebra_flags & ZEBRA_FLAG_REJECT)
 
1358
            req.r.rtm_type = RTN_UNREACHABLE;
 
1359
          else
 
1360
            assert (RTN_BLACKHOLE != RTN_UNREACHABLE);  /* false */
 
1361
        }
 
1362
      else
 
1363
        req.r.rtm_type = RTN_UNICAST;
 
1364
    }
 
1365
 
 
1366
  if (dest)
 
1367
    addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen);
 
1368
 
 
1369
  if (!discard)
 
1370
    {
 
1371
      if (gate)
 
1372
        addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen);
 
1373
      if (index > 0)
 
1374
        addattr32 (&req.n, sizeof req, RTA_OIF, index);
 
1375
    }
 
1376
 
 
1377
  /* Destination netlink address. */
 
1378
  memset (&snl, 0, sizeof snl);
 
1379
  snl.nl_family = AF_NETLINK;
 
1380
 
 
1381
  /* Talk to netlink socket. */
 
1382
  ret = netlink_talk (&req.n, &netlink_cmd);
 
1383
  if (ret < 0)
 
1384
    return -1;
 
1385
 
 
1386
  return 0;
 
1387
}
 
1388
 
 
1389
/* Routing table change via netlink interface. */
 
1390
int
 
1391
netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib,
 
1392
                         int family)
 
1393
{
 
1394
  int bytelen;
 
1395
  struct sockaddr_nl snl;
 
1396
  struct nexthop *nexthop = NULL;
 
1397
  int nexthop_num = 0;
 
1398
  int discard;
 
1399
 
 
1400
  struct
 
1401
  {
 
1402
    struct nlmsghdr n;
 
1403
    struct rtmsg r;
 
1404
    char buf[1024];
 
1405
  } req;
 
1406
 
 
1407
  memset (&req, 0, sizeof req);
 
1408
 
 
1409
  bytelen = (family == AF_INET ? 4 : 16);
 
1410
 
 
1411
  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg));
 
1412
  req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
 
1413
  req.n.nlmsg_type = cmd;
 
1414
  req.r.rtm_family = family;
 
1415
  req.r.rtm_table = rib->table;
 
1416
  req.r.rtm_dst_len = p->prefixlen;
 
1417
 
 
1418
  if ((rib->flags & ZEBRA_FLAG_BLACKHOLE) || (rib->flags & ZEBRA_FLAG_REJECT))
 
1419
    discard = 1;
 
1420
  else
 
1421
    discard = 0;
 
1422
 
 
1423
  if (cmd == RTM_NEWROUTE)
 
1424
    {
 
1425
      req.r.rtm_protocol = RTPROT_ZEBRA;
 
1426
      req.r.rtm_scope = RT_SCOPE_UNIVERSE;
 
1427
 
 
1428
      if (discard)
 
1429
        {
 
1430
          if (rib->flags & ZEBRA_FLAG_BLACKHOLE)
 
1431
            req.r.rtm_type = RTN_BLACKHOLE;
 
1432
          else if (rib->flags & ZEBRA_FLAG_REJECT)
 
1433
            req.r.rtm_type = RTN_UNREACHABLE;
 
1434
          else
 
1435
            assert (RTN_BLACKHOLE != RTN_UNREACHABLE);  /* false */
 
1436
        }
 
1437
      else
 
1438
        req.r.rtm_type = RTN_UNICAST;
 
1439
    }
 
1440
 
 
1441
  addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen);
 
1442
 
 
1443
  /* Metric. */
 
1444
  addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
 
1445
 
 
1446
  if (discard)
 
1447
    {
 
1448
      if (cmd == RTM_NEWROUTE)
 
1449
        for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
 
1450
          SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
 
1451
      goto skip;
 
1452
    }
 
1453
 
 
1454
  /* Multipath case. */
 
1455
  if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
 
1456
    {
 
1457
      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
 
1458
        {
 
1459
 
 
1460
          if ((cmd == RTM_NEWROUTE
 
1461
               && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
 
1462
              || (cmd == RTM_DELROUTE
 
1463
                  && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
 
1464
            {
 
1465
 
 
1466
              if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
 
1467
                {
 
1468
                  if (IS_ZEBRA_DEBUG_KERNEL)
 
1469
                    {
 
1470
                      zlog_debug
 
1471
                        ("netlink_route_multipath() (recursive, 1 hop): "
 
1472
                         "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
 
1473
                         (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
 
1474
                         inet6_ntoa (p->u.prefix6), p->prefixlen,
 
1475
                         nexthop_types_desc[nexthop->rtype]);
 
1476
                    }
 
1477
 
 
1478
                  if (nexthop->rtype == NEXTHOP_TYPE_IPV4
 
1479
                      || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
 
1480
                    {
 
1481
                      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 
1482
                                 &nexthop->rgate.ipv4, bytelen);
 
1483
 
 
1484
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1485
                        zlog_debug("netlink_route_multipath() (recursive, "
 
1486
                                   "1 hop): nexthop via %s if %u",
 
1487
                                   inet_ntoa (nexthop->rgate.ipv4),
 
1488
                                   nexthop->rifindex);
 
1489
                    }
 
1490
#ifdef HAVE_IPV6
 
1491
                  if (nexthop->rtype == NEXTHOP_TYPE_IPV6
 
1492
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
 
1493
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
 
1494
                    {
 
1495
                      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 
1496
                                 &nexthop->rgate.ipv6, bytelen);
 
1497
 
 
1498
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1499
                        zlog_debug("netlink_route_multipath() (recursive, "
 
1500
                                   "1 hop): nexthop via %s if %u",
 
1501
                                   inet6_ntoa (nexthop->rgate.ipv6),
 
1502
                                   nexthop->rifindex);
 
1503
                    }
 
1504
#endif /* HAVE_IPV6 */
 
1505
                  if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
 
1506
                      || nexthop->rtype == NEXTHOP_TYPE_IFNAME
 
1507
                      || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
 
1508
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
 
1509
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
 
1510
                    {
 
1511
                      addattr32 (&req.n, sizeof req, RTA_OIF,
 
1512
                                 nexthop->rifindex);
 
1513
 
 
1514
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1515
                        zlog_debug("netlink_route_multipath() (recursive, "
 
1516
                                   "1 hop): nexthop via if %u",
 
1517
                                   nexthop->rifindex);
 
1518
                    }
 
1519
                }
 
1520
              else
 
1521
                {
 
1522
                  if (IS_ZEBRA_DEBUG_KERNEL)
 
1523
                    {
 
1524
                      zlog_debug
 
1525
                        ("netlink_route_multipath() (single hop): "
 
1526
                         "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
 
1527
                         (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
 
1528
                         inet6_ntoa (p->u.prefix6), p->prefixlen,
 
1529
                         nexthop_types_desc[nexthop->type]);
 
1530
                    }
 
1531
 
 
1532
                  if (nexthop->type == NEXTHOP_TYPE_IPV4
 
1533
                      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
 
1534
                    {
 
1535
                      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 
1536
                                 &nexthop->gate.ipv4, bytelen);
 
1537
 
 
1538
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1539
                        zlog_debug("netlink_route_multipath() (single hop): "
 
1540
                                   "nexthop via %s if %u",
 
1541
                                   inet_ntoa (nexthop->gate.ipv4),
 
1542
                                   nexthop->ifindex);
 
1543
                    }
 
1544
#ifdef HAVE_IPV6
 
1545
                  if (nexthop->type == NEXTHOP_TYPE_IPV6
 
1546
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
 
1547
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
 
1548
                    {
 
1549
                      addattr_l (&req.n, sizeof req, RTA_GATEWAY,
 
1550
                                 &nexthop->gate.ipv6, bytelen);
 
1551
 
 
1552
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1553
                        zlog_debug("netlink_route_multipath() (single hop): "
 
1554
                                   "nexthop via %s if %u",
 
1555
                                   inet6_ntoa (nexthop->gate.ipv6),
 
1556
                                   nexthop->ifindex);
 
1557
                    }
 
1558
#endif /* HAVE_IPV6 */
 
1559
                  if (nexthop->type == NEXTHOP_TYPE_IFINDEX
 
1560
                      || nexthop->type == NEXTHOP_TYPE_IFNAME
 
1561
                      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
 
1562
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX
 
1563
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME)
 
1564
                    {
 
1565
                      addattr32 (&req.n, sizeof req, RTA_OIF, nexthop->ifindex);
 
1566
 
 
1567
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1568
                        zlog_debug("netlink_route_multipath() (single hop): "
 
1569
                                   "nexthop via if %u", nexthop->ifindex);
 
1570
                    }
 
1571
                }
 
1572
 
 
1573
              if (cmd == RTM_NEWROUTE)
 
1574
                SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
 
1575
 
 
1576
              nexthop_num++;
 
1577
              break;
 
1578
            }
 
1579
        }
 
1580
    }
 
1581
  else
 
1582
    {
 
1583
      char buf[1024];
 
1584
      struct rtattr *rta = (void *) buf;
 
1585
      struct rtnexthop *rtnh;
 
1586
 
 
1587
      rta->rta_type = RTA_MULTIPATH;
 
1588
      rta->rta_len = RTA_LENGTH (0);
 
1589
      rtnh = RTA_DATA (rta);
 
1590
 
 
1591
      nexthop_num = 0;
 
1592
      for (nexthop = rib->nexthop;
 
1593
           nexthop && (MULTIPATH_NUM == 0 || nexthop_num < MULTIPATH_NUM);
 
1594
           nexthop = nexthop->next)
 
1595
        {
 
1596
          if ((cmd == RTM_NEWROUTE
 
1597
               && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
 
1598
              || (cmd == RTM_DELROUTE
 
1599
                  && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
 
1600
            {
 
1601
              nexthop_num++;
 
1602
 
 
1603
              rtnh->rtnh_len = sizeof (*rtnh);
 
1604
              rtnh->rtnh_flags = 0;
 
1605
              rtnh->rtnh_hops = 0;
 
1606
              rta->rta_len += rtnh->rtnh_len;
 
1607
 
 
1608
              if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
 
1609
                {
 
1610
                  if (IS_ZEBRA_DEBUG_KERNEL)
 
1611
                    {
 
1612
                      zlog_debug ("netlink_route_multipath() "
 
1613
                         "(recursive, multihop): %s %s/%d type %s",
 
1614
                         lookup (nlmsg_str, cmd), (family == AF_INET) ? 
 
1615
                         inet_ntoa (p->u.prefix4) : inet6_ntoa (p->u.prefix6),
 
1616
                         p->prefixlen, nexthop_types_desc[nexthop->rtype]);
 
1617
                    }
 
1618
                  if (nexthop->rtype == NEXTHOP_TYPE_IPV4
 
1619
                      || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)
 
1620
                    {
 
1621
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,
 
1622
                                     &nexthop->rgate.ipv4, bytelen);
 
1623
                      rtnh->rtnh_len += sizeof (struct rtattr) + 4;
 
1624
 
 
1625
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1626
                        zlog_debug("netlink_route_multipath() (recursive, "
 
1627
                                   "multihop): nexthop via %s if %u",
 
1628
                                   inet_ntoa (nexthop->rgate.ipv4),
 
1629
                                   nexthop->rifindex);
 
1630
                    }
 
1631
#ifdef HAVE_IPV6
 
1632
                  if (nexthop->rtype == NEXTHOP_TYPE_IPV6
 
1633
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME
 
1634
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)
 
1635
                    {
 
1636
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,
 
1637
                                     &nexthop->rgate.ipv6, bytelen);
 
1638
 
 
1639
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1640
                        zlog_debug("netlink_route_multipath() (recursive, "
 
1641
                                   "multihop): nexthop via %s if %u",
 
1642
                                   inet6_ntoa (nexthop->rgate.ipv6),
 
1643
                                   nexthop->rifindex);
 
1644
                    }
 
1645
#endif /* HAVE_IPV6 */
 
1646
                  /* ifindex */
 
1647
                  if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX
 
1648
                      || nexthop->rtype == NEXTHOP_TYPE_IFNAME
 
1649
                      || nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX
 
1650
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX
 
1651
                      || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME)
 
1652
                    {
 
1653
                      rtnh->rtnh_ifindex = nexthop->rifindex;
 
1654
 
 
1655
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1656
                        zlog_debug("netlink_route_multipath() (recursive, "
 
1657
                                   "multihop): nexthop via if %u",
 
1658
                                   nexthop->rifindex);
 
1659
                    }
 
1660
                  else
 
1661
                    {
 
1662
                      rtnh->rtnh_ifindex = 0;
 
1663
                    }
 
1664
                }
 
1665
              else
 
1666
                {
 
1667
                  if (IS_ZEBRA_DEBUG_KERNEL)
 
1668
                    {
 
1669
                      zlog_debug ("netlink_route_multipath() (multihop): "
 
1670
                         "%s %s/%d, type %s", lookup (nlmsg_str, cmd),
 
1671
                         (family == AF_INET) ? inet_ntoa (p->u.prefix4) :
 
1672
                         inet6_ntoa (p->u.prefix6), p->prefixlen,
 
1673
                         nexthop_types_desc[nexthop->type]);
 
1674
                    }
 
1675
                  if (nexthop->type == NEXTHOP_TYPE_IPV4
 
1676
                      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
 
1677
                    {
 
1678
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,
 
1679
                                     &nexthop->gate.ipv4, bytelen);
 
1680
                      rtnh->rtnh_len += sizeof (struct rtattr) + 4;
 
1681
 
 
1682
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1683
                        zlog_debug("netlink_route_multipath() (multihop): "
 
1684
                                   "nexthop via %s if %u",
 
1685
                                   inet_ntoa (nexthop->gate.ipv4),
 
1686
                                   nexthop->ifindex);
 
1687
                    }
 
1688
#ifdef HAVE_IPV6
 
1689
                  if (nexthop->type == NEXTHOP_TYPE_IPV6
 
1690
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
 
1691
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
 
1692
                    { 
 
1693
                      rta_addattr_l (rta, 4096, RTA_GATEWAY,
 
1694
                                     &nexthop->gate.ipv6, bytelen);
 
1695
 
 
1696
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1697
                        zlog_debug("netlink_route_multipath() (multihop): "
 
1698
                                   "nexthop via %s if %u",
 
1699
                                   inet6_ntoa (nexthop->gate.ipv6),
 
1700
                                   nexthop->ifindex);
 
1701
                    }
 
1702
#endif /* HAVE_IPV6 */
 
1703
                  /* ifindex */
 
1704
                  if (nexthop->type == NEXTHOP_TYPE_IFINDEX
 
1705
                      || nexthop->type == NEXTHOP_TYPE_IFNAME
 
1706
                      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
 
1707
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
 
1708
                      || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
 
1709
                    {
 
1710
                      rtnh->rtnh_ifindex = nexthop->ifindex;
 
1711
 
 
1712
                      if (IS_ZEBRA_DEBUG_KERNEL)
 
1713
                        zlog_debug("netlink_route_multipath() (multihop): "
 
1714
                                   "nexthop via if %u", nexthop->ifindex);
 
1715
                    }
 
1716
                  else
 
1717
                    {
 
1718
                      rtnh->rtnh_ifindex = 0;
 
1719
                    }
 
1720
                }
 
1721
              rtnh = RTNH_NEXT (rtnh);
 
1722
 
 
1723
              if (cmd == RTM_NEWROUTE)
 
1724
                SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
 
1725
            }
 
1726
        }
 
1727
 
 
1728
      if (rta->rta_len > RTA_LENGTH (0))
 
1729
        addattr_l (&req.n, 1024, RTA_MULTIPATH, RTA_DATA (rta),
 
1730
                   RTA_PAYLOAD (rta));
 
1731
    }
 
1732
 
 
1733
  /* If there is no useful nexthop then return. */
 
1734
  if (nexthop_num == 0)
 
1735
    {
 
1736
      if (IS_ZEBRA_DEBUG_KERNEL)
 
1737
        zlog_debug ("netlink_route_multipath(): No useful nexthop.");
 
1738
      return 0;
 
1739
    }
 
1740
 
 
1741
skip:
 
1742
 
 
1743
  /* Destination netlink address. */
 
1744
  memset (&snl, 0, sizeof snl);
 
1745
  snl.nl_family = AF_NETLINK;
 
1746
 
 
1747
  /* Talk to netlink socket. */
 
1748
  return netlink_talk (&req.n, &netlink_cmd);
 
1749
}
 
1750
 
 
1751
int
 
1752
kernel_add_ipv4 (struct prefix *p, struct rib *rib)
 
1753
{
 
1754
  return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET);
 
1755
}
 
1756
 
 
1757
int
 
1758
kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
 
1759
{
 
1760
  return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET);
 
1761
}
 
1762
 
 
1763
#ifdef HAVE_IPV6
 
1764
int
 
1765
kernel_add_ipv6 (struct prefix *p, struct rib *rib)
 
1766
{
 
1767
  return netlink_route_multipath (RTM_NEWROUTE, p, rib, AF_INET6);
 
1768
}
 
1769
 
 
1770
int
 
1771
kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
 
1772
{
 
1773
  return netlink_route_multipath (RTM_DELROUTE, p, rib, AF_INET6);
 
1774
}
 
1775
 
 
1776
/* Delete IPv6 route from the kernel. */
 
1777
int
 
1778
kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
 
1779
                        int index, int flags, int table)
 
1780
{
 
1781
  return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix,
 
1782
                        dest->prefixlen, gate, index, flags, table);
 
1783
}
 
1784
#endif /* HAVE_IPV6 */
 
1785
 
 
1786
/* Interface address modification. */
 
1787
int
 
1788
netlink_address (int cmd, int family, struct interface *ifp,
 
1789
                 struct connected *ifc)
 
1790
{
 
1791
  int bytelen;
 
1792
  struct prefix *p;
 
1793
 
 
1794
  struct
 
1795
  {
 
1796
    struct nlmsghdr n;
 
1797
    struct ifaddrmsg ifa;
 
1798
    char buf[1024];
 
1799
  } req;
 
1800
 
 
1801
  p = ifc->address;
 
1802
  memset (&req, 0, sizeof req);
 
1803
 
 
1804
  bytelen = (family == AF_INET ? 4 : 16);
 
1805
 
 
1806
  req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg));
 
1807
  req.n.nlmsg_flags = NLM_F_REQUEST;
 
1808
  req.n.nlmsg_type = cmd;
 
1809
  req.ifa.ifa_family = family;
 
1810
 
 
1811
  req.ifa.ifa_index = ifp->ifindex;
 
1812
  req.ifa.ifa_prefixlen = p->prefixlen;
 
1813
 
 
1814
  addattr_l (&req.n, sizeof req, IFA_LOCAL, &p->u.prefix, bytelen);
 
1815
 
 
1816
  if (family == AF_INET && cmd == RTM_NEWADDR)
 
1817
    {
 
1818
      if (if_is_broadcast (ifp) && ifc->destination)
 
1819
        {
 
1820
          p = ifc->destination;
 
1821
          addattr_l (&req.n, sizeof req, IFA_BROADCAST, &p->u.prefix,
 
1822
                     bytelen);
 
1823
        }
 
1824
    }
 
1825
 
 
1826
  if (CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY))
 
1827
    SET_FLAG (req.ifa.ifa_flags, IFA_F_SECONDARY);
 
1828
 
 
1829
  if (ifc->label)
 
1830
    addattr_l (&req.n, sizeof req, IFA_LABEL, ifc->label,
 
1831
               strlen (ifc->label) + 1);
 
1832
 
 
1833
  return netlink_talk (&req.n, &netlink_cmd);
 
1834
}
 
1835
 
 
1836
int
 
1837
kernel_address_add_ipv4 (struct interface *ifp, struct connected *ifc)
 
1838
{
 
1839
  return netlink_address (RTM_NEWADDR, AF_INET, ifp, ifc);
 
1840
}
 
1841
 
 
1842
int
 
1843
kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc)
 
1844
{
 
1845
  return netlink_address (RTM_DELADDR, AF_INET, ifp, ifc);
 
1846
}
 
1847
 
 
1848
 
 
1849
extern struct thread_master *master;
 
1850
 
 
1851
/* Kernel route reflection. */
 
1852
int
 
1853
kernel_read (struct thread *thread)
 
1854
{
 
1855
  int ret;
 
1856
  int sock;
 
1857
 
 
1858
  sock = THREAD_FD (thread);
 
1859
  ret = netlink_parse_info (netlink_information_fetch, &netlink);
 
1860
  thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
 
1861
 
 
1862
  return 0;
 
1863
}
 
1864
 
 
1865
/* Exported interface function.  This function simply calls
 
1866
   netlink_socket (). */
 
1867
void
 
1868
kernel_init ()
 
1869
{
 
1870
  unsigned long groups;
 
1871
 
 
1872
  groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
 
1873
#ifdef HAVE_IPV6
 
1874
  groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR;
 
1875
#endif /* HAVE_IPV6 */
 
1876
  netlink_socket (&netlink, groups);
 
1877
  netlink_socket (&netlink_cmd, 0);
 
1878
 
 
1879
  /* Register kernel socket. */
 
1880
  if (netlink.sock > 0)
 
1881
    thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock);
 
1882
}