]>
git.ipfire.org Git - thirdparty/bird.git/blob - sysdep/bsd/krt-sock.c
2 * BIRD -- BSD Routing Table Syncing
4 * (c) 2004 Ondrej Filip <feela@network.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
14 #include <sys/param.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/sysctl.h>
18 #include <sys/ioctl.h>
19 #include <netinet/in.h>
20 #include <net/route.h>
22 #include <net/if_dl.h>
26 #include "nest/bird.h"
27 #include "nest/iface.h"
28 #include "nest/route.h"
29 #include "nest/protocol.h"
30 #include "nest/iface.h"
31 #include "lib/timer.h"
34 #include "lib/string.h"
35 #include "lib/socket.h"
39 * There are significant differences in multiple tables support between BSD variants.
41 * OpenBSD has table_id field for routes in route socket protocol, therefore all
42 * tables could be managed by one kernel socket. FreeBSD lacks such field,
43 * therefore multiple sockets (locked to specific table using SO_SETFIB socket
44 * option) must be used.
46 * Both FreeBSD and OpenBSD uses separate scans for each table. In OpenBSD,
47 * table_id is specified explicitly as sysctl scan argument, while in FreeBSD it
48 * is handled implicitly by changing default table using setfib() syscall.
50 * KRT_SHARED_SOCKET - use shared kernel socked instead of one for each krt_proto
51 * KRT_USE_SETFIB_SCAN - use setfib() for sysctl() route scan
52 * KRT_USE_SETFIB_SOCK - use SO_SETFIB socket option for kernel sockets
53 * KRT_USE_SYSCTL_7 - use 7-th arg of sysctl() as table id for route scans
54 * KRT_USE_SYSCTL_NET_FIBS - use net.fibs sysctl() for dynamic max number of fibs
58 #define KRT_MAX_TABLES 256
59 #define KRT_USE_SETFIB_SCAN
60 #define KRT_USE_SETFIB_SOCK
61 #define KRT_USE_SYSCTL_NET_FIBS
65 #define KRT_MAX_TABLES (RT_TABLEID_MAX+1)
66 #define KRT_SHARED_SOCKET
67 #define KRT_USE_SYSCTL_7
70 #ifndef KRT_MAX_TABLES
71 #define KRT_MAX_TABLES 1
76 /* Dynamic max number of tables */
80 #ifdef KRT_USE_SYSCTL_NET_FIBS
83 krt_get_max_tables(void)
86 size_t fibs_len
= sizeof(fibs
);
88 if (sysctlbyname("net.fibs", &fibs
, &fibs_len
, NULL
, 0) < 0)
90 log(L_WARN
"KRT: unable to get max number of fib tables: %m");
94 return MIN(fibs
, KRT_MAX_TABLES
);
100 krt_get_max_tables(void)
102 return KRT_MAX_TABLES
;
105 #endif /* KRT_USE_SYSCTL_NET_FIBS */
108 /* setfib() syscall for FreeBSD scans */
110 #ifdef KRT_USE_SETFIB_SCAN
113 static int krt_default_fib;
116 krt_get_active_fib(void)
119 size_t fib_len = sizeof(fib);
121 if (sysctlbyname("net.my_fibnum", &fib, &fib_len, NULL, 0) < 0)
123 log(L_WARN "KRT: unable to get active fib number: %m");
131 extern int setfib(int fib
);
133 #endif /* KRT_USE_SETFIB_SCAN */
136 /* table_id -> krt_proto map */
138 #ifdef KRT_SHARED_SOCKET
139 static struct krt_proto
*krt_table_map
[KRT_MAX_TABLES
];
143 /* Route socket message processing */
151 a
->cast
== RTC_UNICAST
&&
152 (a
->dest
== RTD_ROUTER
153 || a
->dest
== RTD_DEVICE
155 || a
->dest
== RTD_UNREACHABLE
158 || a
->dest
== RTD_BLACKHOLE
169 struct rt_msghdr rtm
;
170 struct sockaddr_storage buf
[RTAX_MAX
];
174 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
176 #define NEXTADDR(w, u) \
177 if (msg.rtm.rtm_addrs & (w)) {\
178 l = ROUNDUP(((struct sockaddr *)&(u))->sa_len);\
179 memmove(body, &(u), l); body += l;}
181 #define GETADDR(p, F) \
182 bzero(p, sizeof(*p));\
183 if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
184 uint l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
185 memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
189 krt_send_route(struct krt_proto
*p
, int cmd
, rte
*e
)
194 struct iface
*j
, *i
= a
->iface
;
197 char *body
= (char *)msg
.buf
;
198 sockaddr gate
, mask
, dst
;
201 DBG("krt-sock: send %I/%d via %I\n", net
->n
.prefix
, net
->n
.pxlen
, a
->gw
);
203 bzero(&msg
,sizeof (struct rt_msghdr
));
204 msg
.rtm
.rtm_version
= RTM_VERSION
;
205 msg
.rtm
.rtm_type
= cmd
;
206 msg
.rtm
.rtm_seq
= msg_seq
++;
207 msg
.rtm
.rtm_addrs
= RTA_DST
;
208 msg
.rtm
.rtm_flags
= RTF_UP
| RTF_PROTO1
;
210 if (net
->n
.pxlen
== MAX_PREFIX_LENGTH
)
211 msg
.rtm
.rtm_flags
|= RTF_HOST
;
213 msg
.rtm
.rtm_addrs
|= RTA_NETMASK
;
215 #ifdef KRT_SHARED_SOCKET
216 msg
.rtm
.rtm_tableid
= KRT_CF
->sys
.table_id
;
220 if(a
->dest
== RTD_UNREACHABLE
)
221 msg
.rtm
.rtm_flags
|= RTF_REJECT
;
224 if(a
->dest
== RTD_BLACKHOLE
)
225 msg
.rtm
.rtm_flags
|= RTF_BLACKHOLE
;
228 /* This is really very nasty, but I'm not able
229 * to add "(reject|blackhole)" route without
234 i
= HEAD(iface_list
);
236 WALK_LIST(j
, iface_list
)
238 if (j
->flags
& IF_LOOPBACK
)
249 /* Embed interface ID to link-local address */
250 if (ipa_is_link_local(gw
))
251 _I0(gw
) = 0xfe800000 | (i
->index
& 0x0000ffff);
254 sockaddr_fill(&dst
, BIRD_AF
, net
->n
.prefix
, NULL
, 0);
255 sockaddr_fill(&mask
, BIRD_AF
, ipa_mkmask(net
->n
.pxlen
), NULL
, 0);
256 sockaddr_fill(&gate
, BIRD_AF
, gw
, NULL
, 0);
261 msg
.rtm
.rtm_flags
|= RTF_GATEWAY
;
262 msg
.rtm
.rtm_addrs
|= RTA_GATEWAY
;
266 case RTD_UNREACHABLE
:
275 if (cmd
== RTM_ADD
&& (i
->flags
& IF_MULTIACCESS
) != IF_MULTIACCESS
) /* PTP */
276 msg
.rtm
.rtm_flags
|= RTF_CLONING
;
280 log(L_ERR
"KRT: interface %s has no IP addess", i
->name
);
284 sockaddr_fill(&gate
, BIRD_AF
, i
->addr
->ip
, NULL
, 0);
285 msg
.rtm
.rtm_addrs
|= RTA_GATEWAY
;
289 bug("krt-sock: unknown flags, but not filtered");
292 msg
.rtm
.rtm_index
= i
->index
;
294 NEXTADDR(RTA_DST
, dst
);
295 NEXTADDR(RTA_GATEWAY
, gate
);
296 NEXTADDR(RTA_NETMASK
, mask
);
298 l
= body
- (char *)&msg
;
299 msg
.rtm
.rtm_msglen
= l
;
301 if ((l
= write(p
->sys
.sk
->fd
, (char *)&msg
, l
)) < 0) {
302 log(L_ERR
"KRT: Error sending route %I/%d to kernel: %m", net
->n
.prefix
, net
->n
.pxlen
);
310 krt_replace_rte(struct krt_proto
*p
, net
*n
, rte
*new, rte
*old
,
311 struct ea_list
*eattrs UNUSED
)
316 krt_send_route(p
, RTM_DELETE
, old
);
319 err
= krt_send_route(p
, RTM_ADD
, new);
322 n
->n
.flags
|= KRF_SYNC_ERROR
;
324 n
->n
.flags
&= ~KRF_SYNC_ERROR
;
327 #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
330 krt_read_route(struct ks_msg
*msg
, struct krt_proto
*p
, int scan
)
332 /* p is NULL iff KRT_SHARED_SOCKET and !scan */
336 sockaddr dst
, gate
, mask
;
337 ip_addr idst
, igate
, imask
;
338 void *body
= (char *)msg
->buf
;
339 int new = (msg
->rtm
.rtm_type
!= RTM_DELETE
);
340 char *errmsg
= "KRT: Invalid route received";
341 int flags
= msg
->rtm
.rtm_flags
;
342 int addrs
= msg
->rtm
.rtm_addrs
;
346 if (!(flags
& RTF_UP
) && scan
)
347 SKIP("not up in scan\n");
349 if (!(flags
& RTF_DONE
) && !scan
)
350 SKIP("not done in async\n");
352 if (flags
& RTF_LLINFO
)
353 SKIP("link-local\n");
355 #ifdef KRT_SHARED_SOCKET
358 int table_id
= msg
->rtm
.rtm_tableid
;
359 p
= (table_id
< KRT_MAX_TABLES
) ? krt_table_map
[table_id
] : NULL
;
362 SKIP("unknown table id %d\n", table_id
);
366 GETADDR(&dst
, RTA_DST
);
367 GETADDR(&gate
, RTA_GATEWAY
);
368 GETADDR(&mask
, RTA_NETMASK
);
370 if (dst
.sa
.sa_family
!= BIRD_AF
)
373 idst
= ipa_from_sa(&dst
);
374 imask
= ipa_from_sa(&mask
);
375 igate
= (gate
.sa
.sa_family
== BIRD_AF
) ? ipa_from_sa(&gate
) : IPA_NONE
;
377 /* We do not test family for RTA_NETMASK, because BSD sends us
378 some strange values, but interpreting them as IPv4/IPv6 works */
381 int c
= ipa_classify_net(idst
);
382 if ((c
< 0) || !(c
& IADDR_HOST
) || ((c
& IADDR_SCOPE_MASK
) <= SCOPE_LINK
))
383 SKIP("strange class/scope\n");
385 int pxlen
= (flags
& RTF_HOST
) ? MAX_PREFIX_LENGTH
: ipa_masklen(imask
);
387 { log(L_ERR
"%s (%I) - netmask %I", errmsg
, idst
, imask
); return; }
389 if ((flags
& RTF_GATEWAY
) && ipa_zero(igate
))
390 { log(L_ERR
"%s (%I/%d) - missing gateway", errmsg
, idst
, pxlen
); return; }
392 u32 self_mask
= RTF_PROTO1
;
393 u32 alien_mask
= RTF_STATIC
| RTF_PROTO1
| RTF_GATEWAY
;
395 src2
= (flags
& RTF_STATIC
) ? 1 : 0;
396 src2
|= (flags
& RTF_PROTO1
) ? 2 : 0;
399 alien_mask
|= RTF_PROTO2
;
400 src2
|= (flags
& RTF_PROTO2
) ? 4 : 0;
404 alien_mask
|= RTF_PROTO3
;
405 src2
|= (flags
& RTF_PROTO3
) ? 8 : 0;
409 alien_mask
|= RTF_REJECT
;
413 alien_mask
|= RTF_BLACKHOLE
;
416 if (flags
& (RTF_DYNAMIC
| RTF_MODIFIED
))
417 src
= KRT_SRC_REDIRECT
;
418 else if (flags
& self_mask
)
424 else if (flags
& alien_mask
)
427 src
= KRT_SRC_KERNEL
;
429 net
= net_get(p
->p
.table
, idst
, pxlen
);
432 .src
= p
->p
.main_source
,
433 .source
= RTS_INHERIT
,
434 .scope
= SCOPE_UNIVERSE
,
438 /* reject/blackhole routes have also set RTF_GATEWAY,
439 we wil check them first. */
442 if(flags
& RTF_REJECT
) {
443 a
.dest
= RTD_UNREACHABLE
;
449 if(flags
& RTF_BLACKHOLE
) {
450 a
.dest
= RTD_BLACKHOLE
;
455 a
.iface
= if_find_by_index(msg
->rtm
.rtm_index
);
458 log(L_ERR
"KRT: Received route %I/%d with unknown ifindex %u",
459 net
->n
.prefix
, net
->n
.pxlen
, msg
->rtm
.rtm_index
);
463 if (flags
& RTF_GATEWAY
)
470 /* Clean up embedded interface ID returned in link-local address */
471 if (ipa_is_link_local(a
.gw
))
472 _I0(a
.gw
) = 0xfe800000;
475 ng
= neigh_find2(&p
->p
, &a
.gw
, a
.iface
, 0);
476 if (!ng
|| (ng
->scope
== SCOPE_HOST
))
478 /* Ignore routes with next-hop 127.0.0.1, host routes with such
479 next-hop appear on OpenBSD for address aliases. */
480 if (ipa_classify(a
.gw
) == (IADDR_HOST
| SCOPE_HOST
))
483 log(L_ERR
"KRT: Received route %I/%d with strange next-hop %I",
484 net
->n
.prefix
, net
->n
.pxlen
, a
.gw
);
492 e
= rte_get_temp(&a
);
495 e
->u
.krt
.proto
= src2
;
503 krt_got_route_async(p
, e
, new);
507 krt_read_ifannounce(struct ks_msg
*msg
)
509 struct if_announcemsghdr
*ifam
= (struct if_announcemsghdr
*)&msg
->rtm
;
511 if (ifam
->ifan_what
== IFAN_ARRIVAL
)
513 /* Not enough info to create the iface, so we just trigger iface scan */
516 else if (ifam
->ifan_what
== IFAN_DEPARTURE
)
518 struct iface
*iface
= if_find_by_index(ifam
->ifan_index
);
520 /* Interface is destroyed */
523 DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam
->ifan_name
, ifam
->ifan_index
);
530 DBG("KRT: IFANNOUNCE what: %d index %d name %s\n", ifam
->ifan_what
, ifam
->ifan_index
, ifam
->ifan_name
);
534 krt_read_ifinfo(struct ks_msg
*msg
, int scan
)
536 struct if_msghdr
*ifm
= (struct if_msghdr
*)&msg
->rtm
;
537 void *body
= (void *)(ifm
+ 1);
538 struct sockaddr_dl
*dl
= NULL
;
540 struct iface
*iface
= NULL
, f
= {};
541 int fl
= ifm
->ifm_flags
;
544 for (i
= 1; i
<=RTA_IFP
; i
<<= 1)
546 if (i
& ifm
->ifm_addrs
)
550 dl
= (struct sockaddr_dl
*)body
;
553 body
+= ROUNDUP(((struct sockaddr
*)&(body
))->sa_len
);
557 if (dl
&& (dl
->sdl_family
!= AF_LINK
))
559 log(L_WARN
"Ignoring strange IFINFO");
564 nlen
= MIN(sizeof(f
.name
)-1, dl
->sdl_nlen
);
566 /* Note that asynchronous IFINFO messages do not contain iface
567 name, so we have to found an existing iface by iface index */
569 iface
= if_find_by_index(ifm
->ifm_index
);
574 return; /* No interface name, ignoring */
576 memcpy(f
.name
, dl
->sdl_data
, nlen
);
577 DBG("New interface '%s' found\n", f
.name
);
579 else if (dl
&& memcmp(iface
->name
, dl
->sdl_data
, nlen
))
581 /* Interface renamed */
583 memcpy(f
.name
, dl
->sdl_data
, nlen
);
588 memcpy(f
.name
, iface
->name
, sizeof(f
.name
));
591 f
.index
= ifm
->ifm_index
;
592 f
.mtu
= ifm
->ifm_data
.ifi_mtu
;
595 f
.flags
|= IF_ADMIN_UP
;
596 if (ifm
->ifm_data
.ifi_link_state
!= LINK_STATE_DOWN
)
597 f
.flags
|= IF_LINK_UP
; /* up or unknown */
598 if (fl
& IFF_LOOPBACK
) /* Loopback */
599 f
.flags
|= IF_MULTIACCESS
| IF_LOOPBACK
| IF_IGNORE
;
600 else if (fl
& IFF_POINTOPOINT
) /* PtP */
601 f
.flags
|= IF_MULTICAST
;
602 else if (fl
& IFF_BROADCAST
) /* Broadcast */
603 f
.flags
|= IF_MULTIACCESS
| IF_BROADCAST
| IF_MULTICAST
;
605 f
.flags
|= IF_MULTIACCESS
; /* NBMA */
607 iface
= if_update(&f
);
610 if_end_partial_update(iface
);
614 krt_read_addr(struct ks_msg
*msg
, int scan
)
616 struct ifa_msghdr
*ifam
= (struct ifa_msghdr
*)&msg
->rtm
;
617 void *body
= (void *)(ifam
+ 1);
618 sockaddr addr
, mask
, brd
;
619 struct iface
*iface
= NULL
;
621 struct sockaddr null
;
622 ip_addr iaddr
, imask
, ibrd
;
623 int addrs
= ifam
->ifam_addrs
;
624 int scope
, masklen
= -1;
625 int new = (ifam
->ifam_type
== RTM_NEWADDR
);
627 /* Strange messages with zero (invalid) ifindex appear on OpenBSD */
628 if (ifam
->ifam_index
== 0)
631 if(!(iface
= if_find_by_index(ifam
->ifam_index
)))
633 log(L_ERR
"KIF: Received address message for unknown interface %d", ifam
->ifam_index
);
637 GETADDR (&null
, RTA_DST
);
638 GETADDR (&null
, RTA_GATEWAY
);
639 GETADDR (&mask
, RTA_NETMASK
);
640 GETADDR (&null
, RTA_GENMASK
);
641 GETADDR (&null
, RTA_IFP
);
642 GETADDR (&addr
, RTA_IFA
);
643 GETADDR (&null
, RTA_AUTHOR
);
644 GETADDR (&brd
, RTA_BRD
);
646 /* Some other family address */
647 if (addr
.sa
.sa_family
!= BIRD_AF
)
650 iaddr
= ipa_from_sa(&addr
);
651 imask
= ipa_from_sa(&mask
);
652 ibrd
= ipa_from_sa(&brd
);
655 if ((masklen
= ipa_masklen(imask
)) < 0)
657 log(L_ERR
"KIF: Invalid masklen %I for %s", imask
, iface
->name
);
662 /* Clean up embedded interface ID returned in link-local address */
664 if (ipa_is_link_local(iaddr
))
665 _I0(iaddr
) = 0xfe800000;
667 if (ipa_is_link_local(ibrd
))
668 _I0(ibrd
) = 0xfe800000;
672 bzero(&ifa
, sizeof(ifa
));
677 scope
= ipa_classify(ifa
.ip
);
680 log(L_ERR
"KIF: Invalid interface address %I for %s", ifa
.ip
, iface
->name
);
683 ifa
.scope
= scope
& IADDR_SCOPE_MASK
;
685 if (masklen
< BITS_PER_IP_ADDRESS
)
687 ifa
.prefix
= ipa_and(ifa
.ip
, ipa_mkmask(masklen
));
689 if (masklen
== (BITS_PER_IP_ADDRESS
- 1))
690 ifa
.opposite
= ipa_opposite_m1(ifa
.ip
);
693 if (masklen
== (BITS_PER_IP_ADDRESS
- 2))
694 ifa
.opposite
= ipa_opposite_m2(ifa
.ip
);
697 if (iface
->flags
& IF_BROADCAST
)
700 if (!(iface
->flags
& IF_MULTIACCESS
))
703 else if (!(iface
->flags
& IF_MULTIACCESS
) && ipa_nonzero(ibrd
))
705 ifa
.prefix
= ifa
.opposite
= ibrd
;
706 ifa
.flags
|= IA_PEER
;
711 ifa
.flags
|= IA_HOST
;
720 if_end_partial_update(iface
);
724 krt_read_msg(struct proto
*p
, struct ks_msg
*msg
, int scan
)
726 /* p is NULL iff KRT_SHARED_SOCKET and !scan */
728 switch (msg
->rtm
.rtm_type
)
735 krt_read_route(msg
, (struct krt_proto
*)p
, scan
);
738 krt_read_ifannounce(msg
);
741 krt_read_ifinfo(msg
, scan
);
745 krt_read_addr(msg
, scan
);
753 /* Sysctl based scans */
755 static byte
*krt_buffer
;
756 static size_t krt_buflen
, krt_bufmin
;
757 static struct proto
*krt_buffer_owner
;
760 krt_buffer_update(struct proto
*p
, size_t *needed
)
762 size_t req
= *needed
;
764 if ((req
> krt_buflen
) ||
765 ((p
== krt_buffer_owner
) && (req
< krt_bufmin
)))
767 /* min buflen is 32 kB, step is 8 kB, or 128 kB if > 1 MB */
768 size_t step
= (req
< 0x100000) ? 0x2000 : 0x20000;
769 krt_buflen
= (req
< 0x6000) ? 0x8000 : (req
+ step
);
770 krt_bufmin
= (req
< 0x8000) ? 0 : (req
- 2*step
);
774 krt_buffer
= mb_alloc(krt_pool
, krt_buflen
);
775 krt_buffer_owner
= p
;
778 *needed
= krt_buflen
;
783 krt_buffer_release(struct proto
*p
)
785 if (p
== krt_buffer_owner
)
790 krt_buffer_owner
= 0;
795 krt_sysctl_scan(struct proto
*p
, int cmd
, int table_id
)
812 #ifdef KRT_USE_SYSCTL_7
820 #ifdef KRT_USE_SETFIB_SCAN
822 if (setfib(table_id
) < 0)
824 log(L_ERR
"KRT: setfib(%d) failed: %m", table_id
);
830 rv
= sysctl(mib
, mcnt
, NULL
, &needed
, NULL
, 0);
833 /* OpenBSD returns EINVAL for not yet used tables */
834 if ((errno
== EINVAL
) && (table_id
> 0))
837 log(L_ERR
"KRT: Route scan estimate failed: %m");
841 /* The table is empty */
845 buf
= krt_buffer_update(p
, &needed
);
847 rv
= sysctl(mib
, mcnt
, buf
, &needed
, NULL
, 0);
850 /* The buffer size changed since last sysctl ('needed' is not changed) */
851 if ((errno
== ENOMEM
) && retries
--)
854 log(L_ERR
"KRT: Route scan failed: %m");
858 #ifdef KRT_USE_SETFIB_SCAN
861 die("KRT: setfib(%d) failed: %m", 0);
864 /* Process received messages */
865 for (next
= buf
; next
< (buf
+ needed
); next
+= m
->rtm
.rtm_msglen
)
867 m
= (struct ks_msg
*)next
;
868 krt_read_msg(p
, m
, 1);
874 krt_buffer_release(p
);
876 #ifdef KRT_USE_SETFIB_SCAN
879 die("KRT: setfib(%d) failed: %m", 0);
884 krt_do_scan(struct krt_proto
*p
)
886 krt_sysctl_scan(&p
->p
, NET_RT_DUMP
, KRT_CF
->sys
.table_id
);
890 kif_do_scan(struct kif_proto
*p
)
893 krt_sysctl_scan(&p
->p
, NET_RT_IFLIST
, -1);
901 krt_sock_hook(sock
*sk
, int size UNUSED
)
904 int l
= read(sk
->fd
, (char *)&msg
, sizeof(msg
));
907 log(L_ERR
"krt-sock: read failed");
909 krt_read_msg((struct proto
*) sk
->data
, &msg
, 0);
915 krt_sock_open(pool
*pool
, void *data
, int table_id
)
920 fd
= socket(PF_ROUTE
, SOCK_RAW
, AF_UNSPEC
);
922 die("Cannot open kernel socket for routes");
924 #ifdef KRT_USE_SETFIB_SOCK
927 if (setsockopt(fd
, SOL_SOCKET
, SO_SETFIB
, &table_id
, sizeof(table_id
)) < 0)
928 die("Cannot set FIB %d for kernel socket: %m", table_id
);
934 sk
->rx_hook
= krt_sock_hook
;
939 bug("krt-sock: sk_open failed");
945 #ifdef KRT_SHARED_SOCKET
947 static sock
*krt_sock
;
948 static int krt_sock_count
;
952 krt_sock_open_shared(void)
955 krt_sock
= krt_sock_open(krt_pool
, NULL
, -1);
961 krt_sock_close_shared(void)
973 krt_sys_start(struct krt_proto
*p
)
975 krt_table_map
[KRT_CF
->sys
.table_id
] = p
;
977 krt_sock_open_shared();
978 p
->sys
.sk
= krt_sock
;
984 krt_sys_shutdown(struct krt_proto
*p
)
986 krt_sock_close_shared();
989 krt_table_map
[KRT_CF
->sys
.table_id
] = NULL
;
991 krt_buffer_release(&p
->p
);
997 krt_sys_start(struct krt_proto
*p
)
999 p
->sys
.sk
= krt_sock_open(p
->p
.pool
, p
, KRT_CF
->sys
.table_id
);
1004 krt_sys_shutdown(struct krt_proto
*p
)
1009 krt_buffer_release(&p
->p
);
1012 #endif /* KRT_SHARED_SOCKET */
1015 /* KRT configuration callbacks */
1017 static u32 krt_table_cf
[(KRT_MAX_TABLES
+31) / 32];
1020 krt_sys_reconfigure(struct krt_proto
*p UNUSED
, struct krt_config
*n
, struct krt_config
*o
)
1022 return n
->sys
.table_id
== o
->sys
.table_id
;
1026 krt_sys_preconfig(struct config
*c UNUSED
)
1028 krt_max_tables
= krt_get_max_tables();
1029 bzero(&krt_table_cf
, sizeof(krt_table_cf
));
1033 krt_sys_postconfig(struct krt_config
*x
)
1035 u32
*tbl
= krt_table_cf
;
1036 int id
= x
->sys
.table_id
;
1038 if (tbl
[id
/32] & (1 << (id
%32)))
1039 cf_error("Multiple kernel syncers defined for table #%d", id
);
1041 tbl
[id
/32] |= (1 << (id
%32));
1044 void krt_sys_init_config(struct krt_config
*c
)
1046 c
->sys
.table_id
= 0; /* Default table */
1049 void krt_sys_copy_config(struct krt_config
*d
, struct krt_config
*s
)
1051 d
->sys
.table_id
= s
->sys
.table_id
;
1058 kif_sys_start(struct kif_proto
*p UNUSED
)
1063 kif_sys_shutdown(struct kif_proto
*p
)
1065 krt_buffer_release(&p
->p
);
1070 kif_get_primary_ip(struct iface
*i
)
1076 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1079 memset(&ifr
, 0, sizeof(ifr
));
1080 strncpy(ifr
.ifr_name
, i
->name
, IFNAMSIZ
);
1082 int rv
= ioctl(fd
, SIOCGIFADDR
, (char *) &ifr
);
1087 struct sockaddr_in
*sin
= (struct sockaddr_in
*) &ifr
.ifr_addr
;
1088 memcpy(&addr
, &sin
->sin_addr
.s_addr
, sizeof(ip_addr
));
1092 WALK_LIST(a
, i
->addrs
)
1094 if (ipa_equal(a
->ip
, addr
))