and added files
[bcm963xx.git] / userapps / opensource / zebra / zebra / kernel_socket.c
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. */
51 struct 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
82 struct 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. */
126 int routing_sock = -1;
127
128 /* Yes I'm checking ugly routing socket behavior. */
129 /* #define DEBUG */
130
131 /* Supported address family check. */
132 static int
133 af_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 \f
144 /* Dump routing table flag for debug purpose. */
145 void
146 rtm_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 */
164 int
165 ifan_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. */
196 int
197 ifm_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 \f
266 /* Address read from struct ifa_msghdr. */
267 void
268 ifam_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. */
316 int
317 ifam_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 \f
375 /* Interface function for reading kernel routing table information. */
376 int
377 rtm_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
438 void
439 rtm_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. */
528 int
529 rtm_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 \f
664 #include "thread.h"
665 #include "zebra/zserv.h"
666
667 extern struct thread_master *master;
668
669 /* For debug purpose. */
670 void
671 rtmsg_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. */
699 int
700 kernel_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. */
785 void
786 routing_socket ()
787 {
788   routing_sock = socket (AF_ROUTE, SOCK_RAW, 0);
789
790   if (routing_sock < 0) 
791     {
792       zlog_warn ("Can't init kernel routing socket");
793       return;
794     }
795
796   if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0) 
797     zlog_warn ("Can't set O_NONBLOCK to routing socket");
798
799   /* kernel_read needs rewrite. */
800   thread_add_read (master, kernel_read, NULL, routing_sock);
801 }
802
803 /* Exported interface function.  This function simply calls
804    routing_socket (). */
805 void
806 kernel_init ()
807 {
808   routing_socket ();
809 }