~ubuntu-branches/ubuntu/warty/quagga/warty

« back to all changes in this revision

Viewing changes to zebra/rt_netlink.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-06-29 09:50:59 UTC
  • Revision ID: james.westby@ubuntu.com-20040629095059-px1m2m108z4qw1mr
Tags: upstream-0.96.5
ImportĀ upstreamĀ versionĀ 0.96.5

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