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