1/* Kernel communication using routing socket.
2 * Copyright (C) 1999 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#include "if.h"
25#include "prefix.h"
26#include "sockunion.h"
27#include "connected.h"
28#include "memory.h"
29#include "ioctl.h"
30#include "log.h"
31#include "str.h"
32#include "table.h"
33#include "rib.h"
34
35#include "zebra/interface.h"
36#include "zebra/zserv.h"
37#include "zebra/debug.h"
38
39/* Socket length roundup function. */
40#define ROUNDUP(a) \
41  ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
42
43/* And this macro is wrapper for handling sa_len. */
44#ifdef HAVE_SA_LEN
45#define WRAPUP(X)   ROUNDUP(((struct sockaddr *)(X))->sa_len)
46#else
47#define WRAPUP(X)   ROUNDUP(sizeof (struct sockaddr))
48#endif /* HAVE_SA_LEN */
49
50/* Routing socket message types. */
51struct message rtm_type_str[] =
52{
53  {RTM_ADD,      "RTM_ADD"},
54  {RTM_DELETE,   "RTM_DELETE"},
55  {RTM_CHANGE,   "RTM_CHANGE"},
56  {RTM_GET,      "RTM_GET"},
57  {RTM_LOSING,   "RTM_LOSING"},
58  {RTM_REDIRECT, "RTM_REDIRECT"},
59  {RTM_MISS,     "RTM_MISS"},
60  {RTM_LOCK,     "RTM_LOCK"},
61  {RTM_OLDADD,   "RTM_OLDADD"},
62  {RTM_OLDDEL,   "RTM_OLDDEL"},
63  {RTM_RESOLVE,  "RTM_RESOLVE"},
64  {RTM_NEWADDR,  "RTM_NEWADDR"},
65  {RTM_DELADDR,  "RTM_DELADDR"},
66  {RTM_IFINFO,   "RTM_IFINFO"},
67#ifdef RTM_OIFINFO
68  {RTM_OIFINFO,   "RTM_OIFINFO"},
69#endif /* RTM_OIFINFO */
70#ifdef RTM_NEWMADDR
71  {RTM_NEWMADDR, "RTM_NEWMADDR"},
72#endif /* RTM_NEWMADDR */
73#ifdef RTM_DELMADDR
74  {RTM_DELMADDR, "RTM_DELMADDR"},
75#endif /* RTM_DELMADDR */
76#ifdef RTM_IFANNOUNCE
77  {RTM_IFANNOUNCE, "RTM_IFANNOUNCE"},
78#endif /* RTM_IFANNOUNCE */
79  {0,            NULL}
80};
81
82struct message rtm_flag_str[] =
83{
84  {RTF_UP,        "UP"},
85  {RTF_GATEWAY,   "GATEWAY"},
86  {RTF_HOST,      "HOST"},
87  {RTF_REJECT,    "REJECT"},
88  {RTF_DYNAMIC,   "DYNAMIC"},
89  {RTF_MODIFIED,  "MODIFIED"},
90  {RTF_DONE,      "DONE"},
91#ifdef RTF_MASK
92  {RTF_MASK,      "MASK"},
93#endif /* RTF_MASK */
94  {RTF_CLONING,   "CLONING"},
95  {RTF_XRESOLVE,  "XRESOLVE"},
96  {RTF_LLINFO,    "LLINFO"},
97  {RTF_STATIC,    "STATIC"},
98  {RTF_BLACKHOLE, "BLACKHOLE"},
99  {RTF_PROTO1,    "PROTO1"},
100  {RTF_PROTO2,    "PROTO2"},
101#ifdef RTF_PRCLONING
102  {RTF_PRCLONING, "PRCLONING"},
103#endif /* RTF_PRCLONING */
104#ifdef RTF_WASCLONED
105  {RTF_WASCLONED, "WASCLONED"},
106#endif /* RTF_WASCLONED */
107#ifdef RTF_PROTO3
108  {RTF_PROTO3,    "PROTO3"},
109#endif /* RTF_PROTO3 */
110#ifdef RTF_PINNED
111  {RTF_PINNED,    "PINNED"},
112#endif /* RTF_PINNED */
113#ifdef RTF_LOCAL
114  {RTF_LOCAL,    "LOCAL"},
115#endif /* RTF_LOCAL */
116#ifdef RTF_BROADCAST
117  {RTF_BROADCAST, "BROADCAST"},
118#endif /* RTF_BROADCAST */
119#ifdef RTF_MULTICAST
120  {RTF_MULTICAST, "MULTICAST"},
121#endif /* RTF_MULTICAST */
122  {0,             NULL}
123};
124
125/* Kernel routing update socket. */
126int routing_sock = -1;
127
128/* Yes I'm checking ugly routing socket behavior. */
129/* #define DEBUG */
130
131/* Supported address family check. */
132static int
133af_check (int family)
134{
135  if (family == AF_INET)
136    return 1;
137#ifdef HAVE_IPV6
138  if (family == AF_INET6)
139    return 1;
140#endif /* HAVE_IPV6 */
141  return 0;
142}
143
144/* Dump routing table flag for debug purpose. */
145void
146rtm_flag_dump (int flag)
147{
148  struct message *mes;
149  static char buf[BUFSIZ];
150
151  for (mes = rtm_flag_str; mes->key != 0; mes++)
152    {
153      if (mes->key & flag)
154	{
155	  strlcat (buf, mes->str, BUFSIZ);
156	  strlcat (buf, " ", BUFSIZ);
157	}
158    }
159  zlog_info ("Kernel: %s", buf);
160}
161
162#ifdef RTM_IFANNOUNCE
163/* Interface adding function */
164int
165ifan_read (struct if_announcemsghdr *ifan)
166{
167  struct interface *ifp;
168
169  ifp = if_lookup_by_index (ifan->ifan_index);
170  if (ifp == NULL && ifan->ifan_what == IFAN_ARRIVAL)
171    {
172      /* Create Interface */
173      ifp = if_get_by_name (ifan->ifan_name);
174      ifp->ifindex = ifan->ifan_index;
175
176      if_add_update (ifp);
177    }
178  else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
179    {
180      if_delete_update (ifp);
181      if_delete (ifp);
182    }
183
184  if_get_flags (ifp);
185  if_get_mtu (ifp);
186  if_get_metric (ifp);
187
188  if (IS_ZEBRA_DEBUG_KERNEL)
189    zlog_info ("interface %s index %d", ifp->name, ifp->ifindex);
190
191  return 0;
192}
193#endif /* RTM_IFANNOUNCE */
194
195/* Interface adding function called from interface_list. */
196int
197ifm_read (struct if_msghdr *ifm)
198{
199  struct interface *ifp;
200  struct sockaddr_dl *sdl = NULL;
201
202  sdl = (struct sockaddr_dl *)(ifm + 1);
203
204  /* Use sdl index. */
205  ifp = if_lookup_by_index (ifm->ifm_index);
206
207  if (ifp == NULL)
208    {
209      /* Check interface's address.*/
210      if (! (ifm->ifm_addrs & RTA_IFP))
211	{
212	  zlog_warn ("There must be RTA_IFP address for ifindex %d\n",
213		     ifm->ifm_index);
214	  return -1;
215	}
216
217      ifp = if_create ();
218
219      strncpy (ifp->name, sdl->sdl_data, sdl->sdl_nlen);
220      ifp->ifindex = ifm->ifm_index;
221      ifp->flags = ifm->ifm_flags;
222#if defined(__bsdi__)
223      if_kvm_get_mtu (ifp);
224#else
225      if_get_mtu (ifp);
226#endif /* __bsdi__ */
227      if_get_metric (ifp);
228
229      /* Fetch hardware address. */
230      if (sdl->sdl_family != AF_LINK)
231	{
232	  zlog_warn ("sockaddr_dl->sdl_family is not AF_LINK");
233	  return -1;
234	}
235      memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl));
236
237      if_add_update (ifp);
238    }
239  else
240    {
241      /* There is a case of promisc, allmulti flag modification. */
242      if (if_is_up (ifp))
243	{
244	  ifp->flags = ifm->ifm_flags;
245	  if (! if_is_up (ifp))
246	    if_down (ifp);
247	}
248      else
249	{
250	  ifp->flags = ifm->ifm_flags;
251	  if (if_is_up (ifp))
252	    if_up (ifp);
253	}
254    }
255
256#ifdef HAVE_NET_RT_IFLIST
257  ifp->stats = ifm->ifm_data;
258#endif /* HAVE_NET_RT_IFLIST */
259
260  if (IS_ZEBRA_DEBUG_KERNEL)
261    zlog_info ("interface %s index %d", ifp->name, ifp->ifindex);
262
263  return 0;
264}
265
266/* Address read from struct ifa_msghdr. */
267void
268ifam_read_mesg (struct ifa_msghdr *ifm,
269		union sockunion *addr,
270		union sockunion *mask,
271		union sockunion *dest)
272{
273  caddr_t pnt, end;
274
275  pnt = (caddr_t)(ifm + 1);
276  end = ((caddr_t)ifm) + ifm->ifam_msglen;
277
278#define IFAMADDRGET(X,R) \
279    if (ifm->ifam_addrs & (R)) \
280      { \
281        int len = WRAPUP(pnt); \
282        if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \
283          memcpy ((caddr_t)(X), pnt, len); \
284        pnt += len; \
285      }
286#define IFAMMASKGET(X,R) \
287    if (ifm->ifam_addrs & (R)) \
288      { \
289	int len = WRAPUP(pnt); \
290        if ((X) != NULL) \
291	  memcpy ((caddr_t)(X), pnt, len); \
292	pnt += len; \
293      }
294
295  /* Be sure structure is cleared */
296  memset (mask, 0, sizeof (union sockunion));
297  memset (addr, 0, sizeof (union sockunion));
298  memset (dest, 0, sizeof (union sockunion));
299
300  /* We fetch each socket variable into sockunion. */
301  IFAMADDRGET (NULL, RTA_DST);
302  IFAMADDRGET (NULL, RTA_GATEWAY);
303  IFAMMASKGET (mask, RTA_NETMASK);
304  IFAMADDRGET (NULL, RTA_GENMASK);
305  IFAMADDRGET (NULL, RTA_IFP);
306  IFAMADDRGET (addr, RTA_IFA);
307  IFAMADDRGET (NULL, RTA_AUTHOR);
308  IFAMADDRGET (dest, RTA_BRD);
309
310  /* Assert read up end point matches to end point */
311  if (pnt != end)
312    zlog_warn ("ifam_read() does't read all socket data");
313}
314
315/* Interface's address information get. */
316int
317ifam_read (struct ifa_msghdr *ifam)
318{
319  struct interface *ifp;
320  union sockunion addr, mask, gate;
321
322  /* Check does this interface exist or not. */
323  ifp = if_lookup_by_index (ifam->ifam_index);
324  if (ifp == NULL)
325    {
326      zlog_warn ("no interface for index %d", ifam->ifam_index);
327      return -1;
328    }
329
330  /* Allocate and read address information. */
331  ifam_read_mesg (ifam, &addr, &mask, &gate);
332
333  /* Check interface flag for implicit up of the interface. */
334  if_refresh (ifp);
335
336  /* Add connected address. */
337  switch (sockunion_family (&addr))
338    {
339    case AF_INET:
340      if (ifam->ifam_type == RTM_NEWADDR)
341	connected_add_ipv4 (ifp, 0, &addr.sin.sin_addr,
342			    ip_masklen (mask.sin.sin_addr),
343			    &gate.sin.sin_addr, NULL);
344      else
345	connected_delete_ipv4 (ifp, 0, &addr.sin.sin_addr,
346			       ip_masklen (mask.sin.sin_addr),
347			       &gate.sin.sin_addr, NULL);
348      break;
349#ifdef HAVE_IPV6
350    case AF_INET6:
351      /* Unset interface index from link-local address when IPv6 stack
352	 is KAME. */
353      if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
354	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);
355
356      if (ifam->ifam_type == RTM_NEWADDR)
357	connected_add_ipv6 (ifp,
358			    &addr.sin6.sin6_addr,
359			    ip6_masklen (mask.sin6.sin6_addr),
360			    &gate.sin6.sin6_addr);
361      else
362	connected_delete_ipv6 (ifp,
363			       &addr.sin6.sin6_addr,
364			       ip6_masklen (mask.sin6.sin6_addr),
365			       &gate.sin6.sin6_addr);
366      break;
367#endif /* HAVE_IPV6 */
368    default:
369      /* Unsupported family silently ignore... */
370      break;
371    }
372  return 0;
373}
374
375/* Interface function for reading kernel routing table information. */
376int
377rtm_read_mesg (struct rt_msghdr *rtm,
378	       union sockunion *dest,
379	       union sockunion *mask,
380	       union sockunion *gate)
381{
382  caddr_t pnt, end;
383
384  /* Pnt points out socket data start point. */
385  pnt = (caddr_t)(rtm + 1);
386  end = ((caddr_t)rtm) + rtm->rtm_msglen;
387
388  /* rt_msghdr version check. */
389  if (rtm->rtm_version != RTM_VERSION)
390      zlog (NULL, LOG_WARNING,
391	      "Routing message version different %d should be %d."
392	      "This may cause problem\n", rtm->rtm_version, RTM_VERSION);
393
394#define RTMADDRGET(X,R) \
395    if (rtm->rtm_addrs & (R)) \
396      { \
397	int len = WRAPUP (pnt); \
398        if (((X) != NULL) && af_check (((struct sockaddr *)pnt)->sa_family)) \
399	  memcpy ((caddr_t)(X), pnt, len); \
400	pnt += len; \
401      }
402#define RTMMASKGET(X,R) \
403    if (rtm->rtm_addrs & (R)) \
404      { \
405	int len = WRAPUP (pnt); \
406        if ((X) != NULL) \
407	  memcpy ((caddr_t)(X), pnt, len); \
408	pnt += len; \
409      }
410
411  /* Be sure structure is cleared */
412  memset (dest, 0, sizeof (union sockunion));
413  memset (gate, 0, sizeof (union sockunion));
414  memset (mask, 0, sizeof (union sockunion));
415
416  /* We fetch each socket variable into sockunion. */
417  RTMADDRGET (dest, RTA_DST);
418  RTMADDRGET (gate, RTA_GATEWAY);
419  RTMMASKGET (mask, RTA_NETMASK);
420  RTMADDRGET (NULL, RTA_GENMASK);
421  RTMADDRGET (NULL, RTA_IFP);
422  RTMADDRGET (NULL, RTA_IFA);
423  RTMADDRGET (NULL, RTA_AUTHOR);
424  RTMADDRGET (NULL, RTA_BRD);
425
426  /* If there is netmask information set it's family same as
427     destination family*/
428  if (rtm->rtm_addrs & RTA_NETMASK)
429    mask->sa.sa_family = dest->sa.sa_family;
430
431  /* Assert read up to the end of pointer. */
432  if (pnt != end)
433      zlog (NULL, LOG_WARNING, "rtm_read() does't read all socket data.");
434
435  return rtm->rtm_flags;
436}
437
438void
439rtm_read (struct rt_msghdr *rtm)
440{
441  int flags;
442  u_char zebra_flags;
443  union sockunion dest, mask, gate;
444
445  zebra_flags = 0;
446
447  /* Discard self send message. */
448  if (rtm->rtm_type != RTM_GET
449      && (rtm->rtm_pid == pid || rtm->rtm_pid == old_pid))
450    return;
451
452  /* Read destination and netmask and gateway from rtm message
453     structure. */
454  flags = rtm_read_mesg (rtm, &dest, &mask, &gate);
455
456#ifdef RTF_CLONED	/*bsdi, netbsd 1.6*/
457  if (flags & RTF_CLONED)
458    return;
459#endif
460#ifdef RTF_WASCLONED	/*freebsd*/
461  if (flags & RTF_WASCLONED)
462    return;
463#endif
464
465  if ((rtm->rtm_type == RTM_ADD) && ! (flags & RTF_UP))
466    return;
467
468  /* Ignore route which has both HOST and GATEWAY attribute. */
469  if ((flags & RTF_GATEWAY) && (flags & RTF_HOST))
470    return;
471
472  /* This is connected route. */
473  if (! (flags & RTF_GATEWAY))
474      return;
475
476  if (flags & RTF_PROTO1)
477    SET_FLAG (zebra_flags, ZEBRA_FLAG_SELFROUTE);
478
479  /* This is persistent route. */
480  if (flags & RTF_STATIC)
481    SET_FLAG (zebra_flags, ZEBRA_FLAG_STATIC);
482
483  if (dest.sa.sa_family == AF_INET)
484    {
485      struct prefix_ipv4 p;
486
487      p.family = AF_INET;
488      p.prefix = dest.sin.sin_addr;
489      p.prefixlen = ip_masklen (mask.sin.sin_addr);
490
491      if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
492	rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
493		      &p, &gate.sin.sin_addr, 0, 0, 0, 0);
494      else
495	rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags,
496		      &p, &gate.sin.sin_addr, 0, 0);
497    }
498#ifdef HAVE_IPV6
499  if (dest.sa.sa_family == AF_INET6)
500    {
501      struct prefix_ipv6 p;
502      unsigned int ifindex = 0;
503
504      p.family = AF_INET6;
505      p.prefix = dest.sin6.sin6_addr;
506      p.prefixlen = ip6_masklen (mask.sin6.sin6_addr);
507
508#ifdef KAME
509      if (IN6_IS_ADDR_LINKLOCAL (&gate.sin6.sin6_addr))
510	{
511	  ifindex = IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr);
512	  SET_IN6_LINKLOCAL_IFINDEX (gate.sin6.sin6_addr, 0);
513	}
514#endif /* KAME */
515
516      if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD)
517	rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
518		      &p, &gate.sin6.sin6_addr, ifindex, 0);
519      else
520	rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags,
521			 &p, &gate.sin6.sin6_addr, ifindex, 0);
522    }
523#endif /* HAVE_IPV6 */
524}
525
526/* Interface function for the kernel routing table updates.  Support
527   for RTM_CHANGE will be needed. */
528int
529rtm_write (int message,
530	   union sockunion *dest,
531	   union sockunion *mask,
532	   union sockunion *gate,
533	   unsigned int index,
534	   int zebra_flags,
535	   int metric)
536{
537  int ret;
538  caddr_t pnt;
539  struct interface *ifp;
540  struct sockaddr_in tmp_gate;
541#ifdef HAVE_IPV6
542  struct sockaddr_in6 tmp_gate6;
543#endif /* HAVE_IPV6 */
544
545  /* Sequencial number of routing message. */
546  static int msg_seq = 0;
547
548  /* Struct of rt_msghdr and buffer for storing socket's data. */
549  struct
550  {
551    struct rt_msghdr rtm;
552    char buf[512];
553  } msg;
554
555  memset (&tmp_gate, 0, sizeof (struct sockaddr_in));
556  tmp_gate.sin_family = AF_INET;
557#ifdef HAVE_SIN_LEN
558  tmp_gate.sin_len = sizeof (struct sockaddr_in);
559#endif /* HAVE_SIN_LEN */
560
561#ifdef HAVE_IPV6
562  memset (&tmp_gate6, 0, sizeof (struct sockaddr_in6));
563  tmp_gate6.sin6_family = AF_INET6;
564#ifdef SIN6_LEN
565  tmp_gate6.sin6_len = sizeof (struct sockaddr_in6);
566#endif /* SIN6_LEN */
567#endif /* HAVE_IPV6 */
568
569  if (routing_sock < 0)
570    return ZEBRA_ERR_EPERM;
571
572  /* Clear and set rt_msghdr values */
573  memset (&msg, 0, sizeof (struct rt_msghdr));
574  msg.rtm.rtm_version = RTM_VERSION;
575  msg.rtm.rtm_type = message;
576  msg.rtm.rtm_seq = msg_seq++;
577  msg.rtm.rtm_addrs = RTA_DST;
578  msg.rtm.rtm_addrs |= RTA_GATEWAY;
579  msg.rtm.rtm_flags = RTF_UP;
580  msg.rtm.rtm_index = index;
581
582  if (metric != 0)
583    {
584      msg.rtm.rtm_rmx.rmx_hopcount = metric;
585      msg.rtm.rtm_inits |= RTV_HOPCOUNT;
586    }
587
588  ifp = if_lookup_by_index (index);
589
590  if (gate && message == RTM_ADD)
591    msg.rtm.rtm_flags |= RTF_GATEWAY;
592
593  if (! gate && message == RTM_ADD && ifp &&
594      (ifp->flags & IFF_POINTOPOINT) == 0)
595    msg.rtm.rtm_flags |= RTF_CLONING;
596
597  /* If no protocol specific gateway is specified, use link
598     address for gateway. */
599  if (! gate)
600    {
601      if (!ifp)
602        {
603          zlog_warn ("no gateway found for interface index %d", index);
604          return -1;
605        }
606      gate = (union sockunion *) & ifp->sdl;
607    }
608
609  if (mask)
610    msg.rtm.rtm_addrs |= RTA_NETMASK;
611  else if (message == RTM_ADD)
612    msg.rtm.rtm_flags |= RTF_HOST;
613
614  /* Tagging route with flags */
615  msg.rtm.rtm_flags |= (RTF_PROTO1);
616
617  /* Additional flags. */
618  if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
619    msg.rtm.rtm_flags |= RTF_BLACKHOLE;
620
621#ifdef HAVE_SIN_LEN
622#define SOCKADDRSET(X,R) \
623  if (msg.rtm.rtm_addrs & (R)) \
624    { \
625      int len = ROUNDUP ((X)->sa.sa_len); \
626      memcpy (pnt, (caddr_t)(X), len); \
627      pnt += len; \
628    }
629#else
630#define SOCKADDRSET(X,R) \
631  if (msg.rtm.rtm_addrs & (R)) \
632    { \
633      int len = ROUNDUP (sizeof((X)->sa)); \
634      memcpy (pnt, (caddr_t)(X), len); \
635      pnt += len; \
636    }
637#endif /* HAVE_SIN_LEN */
638
639  pnt = (caddr_t) msg.buf;
640
641  /* Write each socket data into rtm message buffer */
642  SOCKADDRSET (dest, RTA_DST);
643  SOCKADDRSET (gate, RTA_GATEWAY);
644  SOCKADDRSET (mask, RTA_NETMASK);
645
646  msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;
647
648  ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);
649
650  if (ret != msg.rtm.rtm_msglen)
651    {
652      if (errno == EEXIST)
653	return ZEBRA_ERR_RTEXIST;
654      if (errno == ENETUNREACH)
655	return ZEBRA_ERR_RTUNREACH;
656
657      zlog_warn ("write : %s (%d)", strerror (errno), errno);
658      return -1;
659    }
660  return 0;
661}
662
663
664#include "thread.h"
665#include "zebra/zserv.h"
666
667extern struct thread_master *master;
668
669/* For debug purpose. */
670void
671rtmsg_debug (struct rt_msghdr *rtm)
672{
673  char *type = "Unknown";
674  struct message *mes;
675
676  for (mes = rtm_type_str; mes->str; mes++)
677    if (mes->key == rtm->rtm_type)
678      {
679	type = mes->str;
680	break;
681      }
682
683  zlog_info ("Kernel: Len: %d Type: %s", rtm->rtm_msglen, type);
684  rtm_flag_dump (rtm->rtm_flags);
685  zlog_info ("Kernel: message seq %d", rtm->rtm_seq);
686  zlog_info ("Kernel: pid %d", rtm->rtm_pid);
687}
688
689/* This is pretty gross, better suggestions welcome -- mhandler */
690#ifndef RTAX_MAX
691#ifdef RTA_NUMBITS
692#define RTAX_MAX	RTA_NUMBITS
693#else
694#define RTAX_MAX	8
695#endif /* RTA_NUMBITS */
696#endif /* RTAX_MAX */
697
698/* Kernel routing table and interface updates via routing socket. */
699int
700kernel_read (struct thread *thread)
701{
702  int sock;
703  int nbytes;
704  struct rt_msghdr *rtm;
705
706  union
707  {
708    /* Routing information. */
709    struct
710    {
711      struct rt_msghdr rtm;
712      struct sockaddr addr[RTAX_MAX];
713    } r;
714
715    /* Interface information. */
716    struct
717    {
718      struct if_msghdr ifm;
719      struct sockaddr addr[RTAX_MAX];
720    } im;
721
722    /* Interface address information. */
723    struct
724    {
725      struct ifa_msghdr ifa;
726      struct sockaddr addr[RTAX_MAX];
727    } ia;
728
729#ifdef RTM_IFANNOUNCE
730    /* Interface arrival/departure */
731    struct
732    {
733      struct if_announcemsghdr ifan;
734      struct sockaddr addr[RTAX_MAX];
735    } ian;
736#endif /* RTM_IFANNOUNCE */
737
738  } buf;
739
740  /* Fetch routing socket. */
741  sock = THREAD_FD (thread);
742
743  nbytes= read (sock, &buf, sizeof buf);
744
745  if (nbytes <= 0)
746    {
747      if (nbytes < 0 && errno != EWOULDBLOCK)
748	zlog_warn ("routing socket error: %s", strerror (errno));
749      return 0;
750    }
751
752  thread_add_read (master, kernel_read, NULL, sock);
753
754#ifdef DEBUG
755  rtmsg_debug (&buf.r.rtm);
756#endif /* DEBUG */
757
758  rtm = &buf.r.rtm;
759
760  switch (rtm->rtm_type)
761    {
762    case RTM_ADD:
763    case RTM_DELETE:
764      rtm_read (rtm);
765      break;
766    case RTM_IFINFO:
767      ifm_read (&buf.im.ifm);
768      break;
769    case RTM_NEWADDR:
770    case RTM_DELADDR:
771      ifam_read (&buf.ia.ifa);
772      break;
773#ifdef RTM_IFANNOUNCE
774    case RTM_IFANNOUNCE:
775      ifan_read (&buf.ian.ifan);
776      break;
777#endif /* RTM_IFANNOUNCE */
778    default:
779      break;
780    }
781  return 0;
782}
783
784/* Make routing socket. */
785void
786routing_socket ()
787{
788  routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
789
790  if (routing_sock < 0)
791    {
792#ifdef FOX_RIP_DEBUG
793      zlog_warn ("Can't init kernel routing socket");
794#endif /* FOX_RIP_DEBUG */
795      return;
796    }
797#ifdef FOX_RIP_DEBUG
798  if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
799    zlog_warn ("Can't set O_NONBLOCK to routing socket");
800#endif /* FOX_RIP_DEBUG */
801  /* kernel_read needs rewrite. */
802  thread_add_read (master, kernel_read, NULL, routing_sock);
803}
804
805/* Exported interface function.  This function simply calls
806   routing_socket (). */
807void
808kernel_init ()
809{
810  routing_socket ();
811}
812