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