]>
git.ipfire.org Git - thirdparty/bird.git/blob - sysdep/bsd/krt-sock.c
29203d1b8168a4ea5d76637d43d7d2a73f765df9
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
;
497 /* These are probably too Linux-specific */
504 krt_got_route_async(p
, e
, new);
508 krt_read_ifannounce(struct ks_msg
*msg
)
510 struct if_announcemsghdr
*ifam
= (struct if_announcemsghdr
*)&msg
->rtm
;
512 if (ifam
->ifan_what
== IFAN_ARRIVAL
)
514 /* Not enough info to create the iface, so we just trigger iface scan */
517 else if (ifam
->ifan_what
== IFAN_DEPARTURE
)
519 struct iface
*iface
= if_find_by_index(ifam
->ifan_index
);
521 /* Interface is destroyed */
524 DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam
->ifan_name
, ifam
->ifan_index
);
531 DBG("KRT: IFANNOUNCE what: %d index %d name %s\n", ifam
->ifan_what
, ifam
->ifan_index
, ifam
->ifan_name
);
535 krt_read_ifinfo(struct ks_msg
*msg
, int scan
)
537 struct if_msghdr
*ifm
= (struct if_msghdr
*)&msg
->rtm
;
538 void *body
= (void *)(ifm
+ 1);
539 struct sockaddr_dl
*dl
= NULL
;
541 struct iface
*iface
= NULL
, f
= {};
542 int fl
= ifm
->ifm_flags
;
545 for (i
= 1; i
<=RTA_IFP
; i
<<= 1)
547 if (i
& ifm
->ifm_addrs
)
551 dl
= (struct sockaddr_dl
*)body
;
554 body
+= ROUNDUP(((struct sockaddr
*)&(body
))->sa_len
);
558 if (dl
&& (dl
->sdl_family
!= AF_LINK
))
560 log(L_WARN
"Ignoring strange IFINFO");
565 nlen
= MIN(sizeof(f
.name
)-1, dl
->sdl_nlen
);
567 /* Note that asynchronous IFINFO messages do not contain iface
568 name, so we have to found an existing iface by iface index */
570 iface
= if_find_by_index(ifm
->ifm_index
);
575 return; /* No interface name, ignoring */
577 memcpy(f
.name
, dl
->sdl_data
, nlen
);
578 DBG("New interface '%s' found\n", f
.name
);
580 else if (dl
&& memcmp(iface
->name
, dl
->sdl_data
, nlen
))
582 /* Interface renamed */
584 memcpy(f
.name
, dl
->sdl_data
, nlen
);
589 memcpy(f
.name
, iface
->name
, sizeof(f
.name
));
592 f
.index
= ifm
->ifm_index
;
593 f
.mtu
= ifm
->ifm_data
.ifi_mtu
;
596 f
.flags
|= IF_ADMIN_UP
;
597 if (ifm
->ifm_data
.ifi_link_state
!= LINK_STATE_DOWN
)
598 f
.flags
|= IF_LINK_UP
; /* up or unknown */
599 if (fl
& IFF_LOOPBACK
) /* Loopback */
600 f
.flags
|= IF_MULTIACCESS
| IF_LOOPBACK
| IF_IGNORE
;
601 else if (fl
& IFF_POINTOPOINT
) /* PtP */
602 f
.flags
|= IF_MULTICAST
;
603 else if (fl
& IFF_BROADCAST
) /* Broadcast */
604 f
.flags
|= IF_MULTIACCESS
| IF_BROADCAST
| IF_MULTICAST
;
606 f
.flags
|= IF_MULTIACCESS
; /* NBMA */
608 iface
= if_update(&f
);
611 if_end_partial_update(iface
);
615 krt_read_addr(struct ks_msg
*msg
, int scan
)
617 struct ifa_msghdr
*ifam
= (struct ifa_msghdr
*)&msg
->rtm
;
618 void *body
= (void *)(ifam
+ 1);
619 sockaddr addr
, mask
, brd
;
620 struct iface
*iface
= NULL
;
622 struct sockaddr null
;
623 ip_addr iaddr
, imask
, ibrd
;
624 int addrs
= ifam
->ifam_addrs
;
625 int scope
, masklen
= -1;
626 int new = (ifam
->ifam_type
== RTM_NEWADDR
);
628 /* Strange messages with zero (invalid) ifindex appear on OpenBSD */
629 if (ifam
->ifam_index
== 0)
632 if(!(iface
= if_find_by_index(ifam
->ifam_index
)))
634 log(L_ERR
"KIF: Received address message for unknown interface %d", ifam
->ifam_index
);
638 GETADDR (&null
, RTA_DST
);
639 GETADDR (&null
, RTA_GATEWAY
);
640 GETADDR (&mask
, RTA_NETMASK
);
641 GETADDR (&null
, RTA_GENMASK
);
642 GETADDR (&null
, RTA_IFP
);
643 GETADDR (&addr
, RTA_IFA
);
644 GETADDR (&null
, RTA_AUTHOR
);
645 GETADDR (&brd
, RTA_BRD
);
647 /* Some other family address */
648 if (addr
.sa
.sa_family
!= BIRD_AF
)
651 iaddr
= ipa_from_sa(&addr
);
652 imask
= ipa_from_sa(&mask
);
653 ibrd
= ipa_from_sa(&brd
);
656 if ((masklen
= ipa_masklen(imask
)) < 0)
658 log(L_ERR
"KIF: Invalid masklen %I for %s", imask
, iface
->name
);
663 /* Clean up embedded interface ID returned in link-local address */
665 if (ipa_is_link_local(iaddr
))
666 _I0(iaddr
) = 0xfe800000;
668 if (ipa_is_link_local(ibrd
))
669 _I0(ibrd
) = 0xfe800000;
673 bzero(&ifa
, sizeof(ifa
));
678 scope
= ipa_classify(ifa
.ip
);
681 log(L_ERR
"KIF: Invalid interface address %I for %s", ifa
.ip
, iface
->name
);
684 ifa
.scope
= scope
& IADDR_SCOPE_MASK
;
686 if (masklen
< BITS_PER_IP_ADDRESS
)
688 ifa
.prefix
= ipa_and(ifa
.ip
, ipa_mkmask(masklen
));
690 if (masklen
== (BITS_PER_IP_ADDRESS
- 1))
691 ifa
.opposite
= ipa_opposite_m1(ifa
.ip
);
694 if (masklen
== (BITS_PER_IP_ADDRESS
- 2))
695 ifa
.opposite
= ipa_opposite_m2(ifa
.ip
);
698 if (iface
->flags
& IF_BROADCAST
)
701 if (!(iface
->flags
& IF_MULTIACCESS
))
704 else if (!(iface
->flags
& IF_MULTIACCESS
) && ipa_nonzero(ibrd
))
706 ifa
.prefix
= ifa
.opposite
= ibrd
;
707 ifa
.flags
|= IA_PEER
;
712 ifa
.flags
|= IA_HOST
;
721 if_end_partial_update(iface
);
725 krt_read_msg(struct proto
*p
, struct ks_msg
*msg
, int scan
)
727 /* p is NULL iff KRT_SHARED_SOCKET and !scan */
729 switch (msg
->rtm
.rtm_type
)
736 krt_read_route(msg
, (struct krt_proto
*)p
, scan
);
739 krt_read_ifannounce(msg
);
742 krt_read_ifinfo(msg
, scan
);
746 krt_read_addr(msg
, scan
);
754 /* Sysctl based scans */
756 static byte
*krt_buffer
;
757 static size_t krt_buflen
, krt_bufmin
;
758 static struct proto
*krt_buffer_owner
;
761 krt_buffer_update(struct proto
*p
, size_t *needed
)
763 size_t req
= *needed
;
765 if ((req
> krt_buflen
) ||
766 ((p
== krt_buffer_owner
) && (req
< krt_bufmin
)))
768 /* min buflen is 32 kB, step is 8 kB, or 128 kB if > 1 MB */
769 size_t step
= (req
< 0x100000) ? 0x2000 : 0x20000;
770 krt_buflen
= (req
< 0x6000) ? 0x8000 : (req
+ step
);
771 krt_bufmin
= (req
< 0x8000) ? 0 : (req
- 2*step
);
775 krt_buffer
= mb_alloc(krt_pool
, krt_buflen
);
776 krt_buffer_owner
= p
;
779 *needed
= krt_buflen
;
784 krt_buffer_release(struct proto
*p
)
786 if (p
== krt_buffer_owner
)
791 krt_buffer_owner
= 0;
796 krt_sysctl_scan(struct proto
*p
, int cmd
, int table_id
)
813 #ifdef KRT_USE_SYSCTL_7
821 #ifdef KRT_USE_SETFIB_SCAN
823 if (setfib(table_id
) < 0)
825 log(L_ERR
"KRT: setfib(%d) failed: %m", table_id
);
831 rv
= sysctl(mib
, mcnt
, NULL
, &needed
, NULL
, 0);
834 /* OpenBSD returns EINVAL for not yet used tables */
835 if ((errno
== EINVAL
) && (table_id
> 0))
838 log(L_ERR
"KRT: Route scan estimate failed: %m");
842 /* The table is empty */
846 buf
= krt_buffer_update(p
, &needed
);
848 rv
= sysctl(mib
, mcnt
, buf
, &needed
, NULL
, 0);
851 /* The buffer size changed since last sysctl ('needed' is not changed) */
852 if ((errno
== ENOMEM
) && retries
--)
855 log(L_ERR
"KRT: Route scan failed: %m");
859 #ifdef KRT_USE_SETFIB_SCAN
862 die("KRT: setfib(%d) failed: %m", 0);
865 /* Process received messages */
866 for (next
= buf
; next
< (buf
+ needed
); next
+= m
->rtm
.rtm_msglen
)
868 m
= (struct ks_msg
*)next
;
869 krt_read_msg(p
, m
, 1);
875 krt_buffer_release(p
);
877 #ifdef KRT_USE_SETFIB_SCAN
880 die("KRT: setfib(%d) failed: %m", 0);
885 krt_do_scan(struct krt_proto
*p
)
887 krt_sysctl_scan(&p
->p
, NET_RT_DUMP
, KRT_CF
->sys
.table_id
);
891 kif_do_scan(struct kif_proto
*p
)
894 krt_sysctl_scan(&p
->p
, NET_RT_IFLIST
, -1);
902 krt_sock_hook(sock
*sk
, int size UNUSED
)
905 int l
= read(sk
->fd
, (char *)&msg
, sizeof(msg
));
908 log(L_ERR
"krt-sock: read failed");
910 krt_read_msg((struct proto
*) sk
->data
, &msg
, 0);
916 krt_sock_open(pool
*pool
, void *data
, int table_id
)
921 fd
= socket(PF_ROUTE
, SOCK_RAW
, AF_UNSPEC
);
923 die("Cannot open kernel socket for routes");
925 #ifdef KRT_USE_SETFIB_SOCK
928 if (setsockopt(fd
, SOL_SOCKET
, SO_SETFIB
, &table_id
, sizeof(table_id
)) < 0)
929 die("Cannot set FIB %d for kernel socket: %m", table_id
);
935 sk
->rx_hook
= krt_sock_hook
;
940 bug("krt-sock: sk_open failed");
946 #ifdef KRT_SHARED_SOCKET
948 static sock
*krt_sock
;
949 static int krt_sock_count
;
953 krt_sock_open_shared(void)
956 krt_sock
= krt_sock_open(krt_pool
, NULL
, -1);
962 krt_sock_close_shared(void)
974 krt_sys_start(struct krt_proto
*p
)
976 krt_table_map
[KRT_CF
->sys
.table_id
] = p
;
978 krt_sock_open_shared();
979 p
->sys
.sk
= krt_sock
;
985 krt_sys_shutdown(struct krt_proto
*p
)
987 krt_sock_close_shared();
990 krt_table_map
[KRT_CF
->sys
.table_id
] = NULL
;
992 krt_buffer_release(&p
->p
);
998 krt_sys_start(struct krt_proto
*p
)
1000 p
->sys
.sk
= krt_sock_open(p
->p
.pool
, p
, KRT_CF
->sys
.table_id
);
1005 krt_sys_shutdown(struct krt_proto
*p
)
1010 krt_buffer_release(&p
->p
);
1013 #endif /* KRT_SHARED_SOCKET */
1016 /* KRT configuration callbacks */
1018 static u32 krt_table_cf
[(KRT_MAX_TABLES
+31) / 32];
1021 krt_sys_reconfigure(struct krt_proto
*p UNUSED
, struct krt_config
*n
, struct krt_config
*o
)
1023 return n
->sys
.table_id
== o
->sys
.table_id
;
1027 krt_sys_preconfig(struct config
*c UNUSED
)
1029 krt_max_tables
= krt_get_max_tables();
1030 bzero(&krt_table_cf
, sizeof(krt_table_cf
));
1034 krt_sys_postconfig(struct krt_config
*x
)
1036 u32
*tbl
= krt_table_cf
;
1037 int id
= x
->sys
.table_id
;
1039 if (tbl
[id
/32] & (1 << (id
%32)))
1040 cf_error("Multiple kernel syncers defined for table #%d", id
);
1042 tbl
[id
/32] |= (1 << (id
%32));
1045 void krt_sys_init_config(struct krt_config
*c
)
1047 c
->sys
.table_id
= 0; /* Default table */
1050 void krt_sys_copy_config(struct krt_config
*d
, struct krt_config
*s
)
1052 d
->sys
.table_id
= s
->sys
.table_id
;
1059 kif_sys_start(struct kif_proto
*p UNUSED
)
1064 kif_sys_shutdown(struct kif_proto
*p
)
1066 krt_buffer_release(&p
->p
);
1071 kif_get_primary_ip(struct iface
*i
)
1077 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
1080 memset(&ifr
, 0, sizeof(ifr
));
1081 strncpy(ifr
.ifr_name
, i
->name
, IFNAMSIZ
);
1083 int rv
= ioctl(fd
, SIOCGIFADDR
, (char *) &ifr
);
1088 struct sockaddr_in
*sin
= (struct sockaddr_in
*) &ifr
.ifr_addr
;
1089 memcpy(&addr
, &sin
->sin_addr
.s_addr
, sizeof(ip_addr
));
1093 WALK_LIST(a
, i
->addrs
)
1095 if (ipa_equal(a
->ip
, addr
))