mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
*BSD port added. (Tested on FreeBSD and NetBSD)
This commit is contained in:
parent
781aa475aa
commit
b1a1fabac7
@ -41,5 +41,15 @@
|
|||||||
/* We have <syslog.h> and syslog() */
|
/* We have <syslog.h> and syslog() */
|
||||||
#undef HAVE_SYSLOG
|
#undef HAVE_SYSLOG
|
||||||
|
|
||||||
|
/* We have <alloca.h> */
|
||||||
|
#undef HAVE_ALLOCA_H
|
||||||
|
|
||||||
/* Are we using dmalloc? */
|
/* Are we using dmalloc? */
|
||||||
#undef HAVE_LIBDMALLOC
|
#undef HAVE_LIBDMALLOC
|
||||||
|
|
||||||
|
/* Readline stuff */
|
||||||
|
#undef HAVE_RL_CRLF
|
||||||
|
#undef HAVE_RL_DING
|
||||||
|
|
||||||
|
/* struct sockaddr_in(6) */
|
||||||
|
#undef HAVE_SIN_LEN
|
||||||
|
6
sysdep/bsd/Modules
Normal file
6
sysdep/bsd/Modules
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
krt-scan.h
|
||||||
|
krt-iface.h
|
||||||
|
sysio.h
|
||||||
|
krt-set.h
|
||||||
|
krt-sock.c
|
||||||
|
krt-sock.h
|
17
sysdep/bsd/krt-iface.h
Normal file
17
sysdep/bsd/krt-iface.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* BIRD -- Unix Kernel Socket Route Syncer -- Dummy Include File
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_KRT_IFACE_H_
|
||||||
|
#define _BIRD_KRT_IFACE_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't have split iface/scan/set parts. See krt-sock.h.
|
||||||
|
*/
|
||||||
|
static inline int kif_params_same(struct krt_if_params *old, struct krt_if_params *new) { return 1; }
|
||||||
|
|
||||||
|
#endif
|
137
sysdep/bsd/krt-scan.c
Normal file
137
sysdep/bsd/krt-scan.c
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* BIRD -- *BSD Table Scanning
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
|
||||||
|
#undef LOCAL_DEBUG
|
||||||
|
#define LOCAL_DEBUG
|
||||||
|
|
||||||
|
#include "nest/bird.h"
|
||||||
|
#include "nest/route.h"
|
||||||
|
#include "nest/protocol.h"
|
||||||
|
#include "nest/iface.h"
|
||||||
|
#include "lib/timer.h"
|
||||||
|
#include "lib/unix.h"
|
||||||
|
#include "lib/krt.h"
|
||||||
|
#include "lib/string.h"
|
||||||
|
|
||||||
|
static int krt_scan_fd = -1;
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
krt_temp_iface(struct krt_proto *p, char *name)
|
||||||
|
{
|
||||||
|
struct iface *i;
|
||||||
|
|
||||||
|
WALK_LIST(i, p->scan.temp_ifs)
|
||||||
|
if (!strcmp(i->name, name))
|
||||||
|
return i;
|
||||||
|
i = mb_allocz(p->p.pool, sizeof(struct iface));
|
||||||
|
strcpy(i->name, name);
|
||||||
|
add_tail(&p->scan.temp_ifs, &i->n);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_construct(struct krt_config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_preconfig(struct config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_postconfig(struct krt_config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_start(struct krt_proto *x, int first)
|
||||||
|
{
|
||||||
|
init_list(&x->scan.temp_ifs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_shutdown(struct krt_proto *x, int last)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, int *bl, int cmd)
|
||||||
|
{
|
||||||
|
byte *next;
|
||||||
|
int obl, needed, mib[6], on;
|
||||||
|
struct ks_msg *m;
|
||||||
|
|
||||||
|
mib[0] = CTL_NET;
|
||||||
|
mib[1] = PF_ROUTE;
|
||||||
|
mib[2] = 0;
|
||||||
|
mib[3] = BIRD_PF;
|
||||||
|
mib[4] = cmd;
|
||||||
|
mib[5] = 0;
|
||||||
|
|
||||||
|
if( sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
die("RT scan...");
|
||||||
|
}
|
||||||
|
|
||||||
|
obl = *bl;
|
||||||
|
|
||||||
|
while(needed > *bl) *bl *= 2;
|
||||||
|
while(needed < (*bl/2)) *bl /= 2;
|
||||||
|
|
||||||
|
if( (obl!=*bl) || !*buf)
|
||||||
|
{
|
||||||
|
if(*buf) mb_free(*buf);
|
||||||
|
if( (*buf = mb_alloc(pool, *bl)) == NULL ) die("RT scan buf alloc");
|
||||||
|
}
|
||||||
|
|
||||||
|
on = needed;
|
||||||
|
|
||||||
|
if( sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
if(on != needed) return; /* The buffer size changed since last sysctl */
|
||||||
|
die("RT scan 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (next = *buf; next < (*buf + needed); next += m->rtm.rtm_msglen)
|
||||||
|
{
|
||||||
|
m = (struct ks_msg *)next;
|
||||||
|
krt_read_msg(p, m, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_fire(struct krt_proto *p)
|
||||||
|
{
|
||||||
|
static byte *buf = NULL;
|
||||||
|
static int bl = 32768;
|
||||||
|
krt_sysctl_scan((struct proto *)p , p->krt_pool, &buf, &bl, NET_RT_DUMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_if_scan(struct kif_proto *p)
|
||||||
|
{
|
||||||
|
static byte *buf = NULL;
|
||||||
|
static int bl = 4096;
|
||||||
|
struct proto *P = (struct proto *)p;
|
||||||
|
if_start_update();
|
||||||
|
krt_sysctl_scan(P, P->pool, &buf, &bl, NET_RT_IFLIST);
|
||||||
|
if_end_update();
|
||||||
|
}
|
||||||
|
|
21
sysdep/bsd/krt-scan.h
Normal file
21
sysdep/bsd/krt-scan.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* BIRD -- *BSD Kernel Route Syncer -- Scanning
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_KRT_SCAN_H_
|
||||||
|
#define _BIRD_KRT_SCAN_H_
|
||||||
|
|
||||||
|
struct krt_scan_params {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct krt_scan_status {
|
||||||
|
list temp_ifs; /* Temporary interfaces */
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int krt_scan_params_same(struct krt_scan_params *o, struct krt_scan_params *n) { return 1; }
|
||||||
|
|
||||||
|
#endif
|
17
sysdep/bsd/krt-set.h
Normal file
17
sysdep/bsd/krt-set.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* BIRD -- Unix Kernel Socket Route Syncer -- Dummy Include File
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_KRT_SET_H_
|
||||||
|
#define _BIRD_KRT_SET_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't have split iface/scan/set parts. See krt-sock.h.
|
||||||
|
*/
|
||||||
|
#include "lib/krt-sock.h"
|
||||||
|
|
||||||
|
#endif
|
703
sysdep/bsd/krt-sock.c
Normal file
703
sysdep/bsd/krt-sock.c
Normal file
@ -0,0 +1,703 @@
|
|||||||
|
/*
|
||||||
|
* BIRD -- Unix Routing Table Syncing
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
|
||||||
|
#undef LOCAL_DEBUG
|
||||||
|
|
||||||
|
#include "nest/bird.h"
|
||||||
|
#include "nest/iface.h"
|
||||||
|
#include "nest/route.h"
|
||||||
|
#include "nest/protocol.h"
|
||||||
|
#include "nest/iface.h"
|
||||||
|
#include "lib/timer.h"
|
||||||
|
#include "lib/unix.h"
|
||||||
|
#include "lib/krt.h"
|
||||||
|
#include "lib/string.h"
|
||||||
|
#include "lib/socket.h"
|
||||||
|
|
||||||
|
#ifdef IPV6
|
||||||
|
#define HOST_MASK 128
|
||||||
|
#else
|
||||||
|
#define HOST_MASK 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int rt_sock = 0;
|
||||||
|
|
||||||
|
#define CHECK_FAMILY(sa) \
|
||||||
|
((((struct sockaddr *)sa)->sa_family) == BIRD_AF)
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
krt_temp_iface_index(struct krt_proto *p, unsigned index)
|
||||||
|
{
|
||||||
|
struct iface *i, *j;
|
||||||
|
|
||||||
|
WALK_LIST(i, p->scan.temp_ifs)
|
||||||
|
if (i->index == index)
|
||||||
|
return i;
|
||||||
|
i = mb_allocz(p->p.pool, sizeof(struct iface));
|
||||||
|
if (j = if_find_by_index(index))
|
||||||
|
{
|
||||||
|
strcpy(i->name, j->name);
|
||||||
|
i->addr = j->addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strcpy(i->name, "?");
|
||||||
|
i->index = index;
|
||||||
|
add_tail(&p->scan.temp_ifs, &i->n);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
krt_capable(rte *e)
|
||||||
|
{
|
||||||
|
rta *a = e->attrs;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUTO_ROUTES
|
||||||
|
if (a->source == RTS_DEVICE)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
return
|
||||||
|
a->cast == RTC_UNICAST &&
|
||||||
|
(a->dest == RTD_ROUTER
|
||||||
|
|| a->dest == RTD_DEVICE
|
||||||
|
#ifdef RTF_REJECT
|
||||||
|
|| a->dest == RTD_UNREACHABLE
|
||||||
|
#endif
|
||||||
|
#ifdef RTF_BLACKHOLE
|
||||||
|
|| a->dest == RTD_BLACKHOLE /* FIXME Prohibited? */
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ROUNDUP(a) \
|
||||||
|
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||||
|
|
||||||
|
#define NEXTADDR(w, u) \
|
||||||
|
if (msg.rtm.rtm_addrs & (w)) {\
|
||||||
|
l = ROUNDUP(((struct sockaddr *)&(u))->sa_len);\
|
||||||
|
memmove(body, &(u), l); body += l;}
|
||||||
|
|
||||||
|
static void
|
||||||
|
krt_sock_send(int cmd, rte *e, char *name)
|
||||||
|
{
|
||||||
|
net *net = e->net;
|
||||||
|
rta *a = e->attrs;
|
||||||
|
static int msg_seq;
|
||||||
|
struct iface *j, *i = a->iface;
|
||||||
|
int l;
|
||||||
|
struct ks_msg msg;
|
||||||
|
char *body = (char *)msg.buf;
|
||||||
|
sockaddr gate, mask, dst;
|
||||||
|
|
||||||
|
log("KRT sock send: %I/%d via %I", net->n.prefix, net->n.pxlen, a->gw);
|
||||||
|
|
||||||
|
fill_in_sockaddr(&dst, net->n.prefix, 0);
|
||||||
|
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0);
|
||||||
|
fill_in_sockaddr(&gate, a->gw, 0);
|
||||||
|
|
||||||
|
memset (&msg, 0, sizeof (struct rt_msghdr));
|
||||||
|
msg.rtm.rtm_version = RTM_VERSION;
|
||||||
|
msg.rtm.rtm_type = cmd;
|
||||||
|
msg.rtm.rtm_seq = msg_seq++;
|
||||||
|
msg.rtm.rtm_addrs = RTA_DST;
|
||||||
|
msg.rtm.rtm_flags = RTF_UP;
|
||||||
|
|
||||||
|
if (net->n.pxlen == HOST_MASK)
|
||||||
|
{
|
||||||
|
msg.rtm.rtm_flags |= RTF_HOST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg.rtm.rtm_addrs |= RTA_NETMASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RTF_REJECT
|
||||||
|
if(a->dest == RTD_UNREACHABLE)
|
||||||
|
msg.rtm.rtm_flags |= RTF_REJECT;
|
||||||
|
#endif
|
||||||
|
#ifdef RTF_BLACKHOLE
|
||||||
|
if(a->dest == RTD_BLACKHOLE)
|
||||||
|
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* This is really very nasty, but I'm not able
|
||||||
|
* to add "(reject|blackhole)" route without
|
||||||
|
* gateway set
|
||||||
|
*/
|
||||||
|
if(!i)
|
||||||
|
{
|
||||||
|
i = HEAD(iface_list);
|
||||||
|
|
||||||
|
WALK_LIST(j, iface_list)
|
||||||
|
{
|
||||||
|
if (j->flags & IF_LOOPBACK)
|
||||||
|
{
|
||||||
|
i = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a->dest)
|
||||||
|
{
|
||||||
|
case RTD_ROUTER:
|
||||||
|
msg.rtm.rtm_flags |= RTF_GATEWAY;
|
||||||
|
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
||||||
|
break;
|
||||||
|
#ifdef RTF_REJECT
|
||||||
|
case RTD_UNREACHABLE:
|
||||||
|
#endif
|
||||||
|
#ifdef RTF_BLACKHOLE
|
||||||
|
case RTD_BLACKHOLE:
|
||||||
|
#endif
|
||||||
|
case RTD_DEVICE:
|
||||||
|
if(i)
|
||||||
|
{
|
||||||
|
if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */
|
||||||
|
msg.rtm.rtm_flags |= RTF_CLONING;
|
||||||
|
|
||||||
|
if(!i->addr) {
|
||||||
|
log(L_ERR "KIF: interface \"%s\" has no IP addess", i->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_in_sockaddr(&gate, i->addr->ip, 0);
|
||||||
|
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bug("krt-sock: interface route %I/%d without interface", net->n.prefix, net->n.pxlen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bug("krt-sock: unknown flags, but not filtered");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i) msg.rtm.rtm_index = i->index;
|
||||||
|
|
||||||
|
NEXTADDR(RTA_DST, dst);
|
||||||
|
NEXTADDR(RTA_GATEWAY, gate);
|
||||||
|
NEXTADDR(RTA_NETMASK, mask);
|
||||||
|
|
||||||
|
l = body - (char *)&msg;
|
||||||
|
msg.rtm.rtm_msglen = l;
|
||||||
|
|
||||||
|
if ((l = write(rt_sock, (char *)&msg, l)) < 0) {
|
||||||
|
log(L_ERR "KIF: error writting route to socket (%I/%d)", net->n.prefix, net->n.pxlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_set_notify(struct krt_proto *p, net *net, rte *new, rte *old)
|
||||||
|
{
|
||||||
|
if (old)
|
||||||
|
{
|
||||||
|
DBG("krt_remove_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
|
||||||
|
krt_sock_send(RTM_DELETE, old, "RTM_DELETE");
|
||||||
|
|
||||||
|
}
|
||||||
|
if (new)
|
||||||
|
{
|
||||||
|
DBG("krt_add_route(%I/%d)\n", net->n.prefix, net->n.pxlen);
|
||||||
|
krt_sock_send(RTM_ADD, new, "RTM_ADD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_set_start(struct krt_proto *x, int first)
|
||||||
|
{
|
||||||
|
sock *sk_rt;
|
||||||
|
static int ks_open_tried = 0;
|
||||||
|
|
||||||
|
if (ks_open_tried)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ks_open_tried = 1;
|
||||||
|
|
||||||
|
DBG("KRT: Opening kernel socket\n");
|
||||||
|
|
||||||
|
if( (rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0)
|
||||||
|
die("Cannot open kernel socket for routes");
|
||||||
|
|
||||||
|
sk_rt = sk_new(krt_pool);
|
||||||
|
sk_rt->type = SK_MAGIC;
|
||||||
|
sk_rt->rx_hook = krt_set_hook;
|
||||||
|
sk_rt->fd = rt_sock;
|
||||||
|
sk_rt->data = x;
|
||||||
|
if (sk_open(sk_rt))
|
||||||
|
bug("Krt_sock: sk_rt_open failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
krt_set_hook(sock *sk, int size)
|
||||||
|
{
|
||||||
|
int l;
|
||||||
|
struct ks_msg msg;
|
||||||
|
|
||||||
|
l = read(sk->fd, (char *)&msg, sizeof(msg));
|
||||||
|
|
||||||
|
krt_read_msg((struct proto *)sk->data, &msg, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||||
|
{
|
||||||
|
sockaddr gate, mask, dst;
|
||||||
|
rta a;
|
||||||
|
rte *e;
|
||||||
|
net *net;
|
||||||
|
u32 oif;
|
||||||
|
ip_addr idst, igate, imask;
|
||||||
|
void *body = (char *)msg->buf;
|
||||||
|
int new = (msg->rtm.rtm_type == RTM_ADD);
|
||||||
|
int src;
|
||||||
|
int flags = msg->rtm.rtm_flags;
|
||||||
|
int addrs = msg->rtm.rtm_addrs;
|
||||||
|
int masklen = -1;
|
||||||
|
|
||||||
|
if (!(flags & RTF_UP))
|
||||||
|
{
|
||||||
|
DBG("Down.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & RTF_HOST)
|
||||||
|
masklen = HOST_MASK;
|
||||||
|
|
||||||
|
if(!CHECK_FAMILY(body)) return;
|
||||||
|
|
||||||
|
if(msg->rtm.rtm_flags & RTF_LLINFO) return; /* ARPs etc. */
|
||||||
|
|
||||||
|
#define GETADDR(p, F) \
|
||||||
|
memset(p, 0, sizeof(*p));\
|
||||||
|
if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
|
||||||
|
unsigned int l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
|
||||||
|
memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
|
||||||
|
body += l;}
|
||||||
|
|
||||||
|
GETADDR (&dst, RTA_DST);
|
||||||
|
GETADDR (&gate, RTA_GATEWAY);
|
||||||
|
GETADDR (&mask, RTA_NETMASK);
|
||||||
|
|
||||||
|
idst = IPA_NONE;
|
||||||
|
igate = IPA_NONE;
|
||||||
|
imask = IPA_NONE;
|
||||||
|
|
||||||
|
get_sockaddr(&dst, &idst, NULL, 0);
|
||||||
|
if(CHECK_FAMILY(&gate)) get_sockaddr(&gate, &igate, NULL, 0);
|
||||||
|
get_sockaddr(&mask, &imask, NULL, 0);
|
||||||
|
|
||||||
|
if (masklen < 0) masklen = ipa_mklen(imask);
|
||||||
|
|
||||||
|
if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
|
||||||
|
{
|
||||||
|
log(L_WARN "krt: Ignoring redirect to %I/%d via %I", idst, masklen, igate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (masklen < 0)
|
||||||
|
{
|
||||||
|
log(L_WARN "krt: Got invalid route from kernel!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
net = net_get(p->p.table, idst, masklen);
|
||||||
|
|
||||||
|
memset(&a, 0, sizeof(a));
|
||||||
|
|
||||||
|
a.proto = &p->p;
|
||||||
|
a.source = RTS_INHERIT;
|
||||||
|
a.scope = SCOPE_UNIVERSE;
|
||||||
|
a.cast = RTC_UNICAST;
|
||||||
|
a.flags = a.aflags = 0;
|
||||||
|
a.from = IPA_NONE;
|
||||||
|
a.gw = IPA_NONE;
|
||||||
|
a.iface = NULL;
|
||||||
|
a.eattrs = NULL;
|
||||||
|
|
||||||
|
a.dest = RTD_NONE;
|
||||||
|
|
||||||
|
|
||||||
|
if (flags & RTF_GATEWAY)
|
||||||
|
{
|
||||||
|
neighbor *ng = neigh_find(&p->p, &igate, 0);
|
||||||
|
if (ng && ng->scope)
|
||||||
|
a.iface = ng->iface;
|
||||||
|
else
|
||||||
|
log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", igate, net->n.prefix, net->n.pxlen);
|
||||||
|
|
||||||
|
a.dest = RTD_ROUTER;
|
||||||
|
a.gw = igate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a.dest = RTD_DEVICE;
|
||||||
|
a.gw = IPA_NONE;
|
||||||
|
a.iface = krt_temp_iface_index(p, msg->rtm.rtm_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RTF_REJECT
|
||||||
|
if(flags & RTF_REJECT) {
|
||||||
|
a.dest = RTD_UNREACHABLE;
|
||||||
|
a.gw = IPA_NONE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef RTF_BLACKHOLE
|
||||||
|
if(flags & RTF_BLACKHOLE) {
|
||||||
|
a.dest = RTD_BLACKHOLE;
|
||||||
|
a.gw = IPA_NONE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (a.dest == RTD_NONE)
|
||||||
|
{
|
||||||
|
log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = KRT_SRC_UNKNOWN; /* FIXME */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
e = rte_get_temp(&a);
|
||||||
|
e->net = net;
|
||||||
|
e->u.krt.src = src;
|
||||||
|
//e->u.krt.proto = i->rtm_protocol;
|
||||||
|
//e->u.krt.type = i->rtm_type;
|
||||||
|
e->u.krt.metric = 0;
|
||||||
|
|
||||||
|
if (scan)
|
||||||
|
krt_got_route(p, e);
|
||||||
|
else
|
||||||
|
krt_got_route_async(p, e, new);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_read_ifinfo(struct ks_msg *msg)
|
||||||
|
{
|
||||||
|
struct if_msghdr *ifm = (struct if_msghdr *)&msg->rtm;
|
||||||
|
void *body = (void *)(ifm + 1);
|
||||||
|
struct sockaddr_dl *dl = NULL;
|
||||||
|
unsigned int i;
|
||||||
|
struct iface *iface = NULL, f;
|
||||||
|
char *ifname = "(none)";
|
||||||
|
int fl = ifm->ifm_flags;
|
||||||
|
|
||||||
|
for(i = 1; i!=0; i <<= 1)
|
||||||
|
{
|
||||||
|
if((i & ifm->ifm_addrs) && (i == RTA_IFP))
|
||||||
|
{
|
||||||
|
if( i == RTA_IFP)
|
||||||
|
{
|
||||||
|
dl = (struct sockaddr_dl *)body;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
body += ROUNDUP(((struct sockaddr *)&(body))->sa_len);\
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dl && (dl->sdl_family != AF_LINK))
|
||||||
|
{
|
||||||
|
log("Ignoring strange IFINFO");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dl) ifname = dl->sdl_data;
|
||||||
|
|
||||||
|
iface = if_find_by_index(ifm->ifm_index);
|
||||||
|
|
||||||
|
if(!iface)
|
||||||
|
{
|
||||||
|
/* New interface */
|
||||||
|
if(!dl) return; /* No interface name, ignoring */
|
||||||
|
DBG("New interface \"%s\" found", ifname);
|
||||||
|
bzero(&f, sizeof(f));
|
||||||
|
f.index = ifm->ifm_index;
|
||||||
|
strncpy(f.name, ifname, sizeof(f.name) -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(&f, iface, sizeof(struct iface));
|
||||||
|
}
|
||||||
|
|
||||||
|
f.mtu = ifm->ifm_data.ifi_mtu;
|
||||||
|
f.flags = 0;
|
||||||
|
|
||||||
|
if (fl & IFF_UP)
|
||||||
|
{
|
||||||
|
//f.flags |= IF_UP; /* FIXME */
|
||||||
|
f.flags |= IF_LINK_UP;
|
||||||
|
}
|
||||||
|
if (fl & IFF_LOOPBACK) /* Loopback */
|
||||||
|
f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
|
||||||
|
else if (fl & IFF_POINTOPOINT) /* PtP */
|
||||||
|
f.flags |= IF_MULTICAST;
|
||||||
|
else if (fl & IFF_BROADCAST) /* Broadcast */
|
||||||
|
f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
|
||||||
|
else
|
||||||
|
f.flags |= IF_MULTIACCESS; /* NBMA */
|
||||||
|
|
||||||
|
if((!iface) || memcmp(&f, iface, sizeof(struct iface)))
|
||||||
|
if_update(&f); /* Just if something happens */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_read_addr(struct ks_msg *msg)
|
||||||
|
{
|
||||||
|
struct ifa_msghdr *ifam = (struct ifa_msghdr *)&msg->rtm;
|
||||||
|
void *body = (void *)(ifam + 1);
|
||||||
|
sockaddr addr, mask, brd;
|
||||||
|
unsigned int i;
|
||||||
|
struct iface *iface = NULL;
|
||||||
|
struct ifa ifa;
|
||||||
|
struct sockaddr null;
|
||||||
|
ip_addr iaddr, imask, ibrd;
|
||||||
|
int addrs = ifam->ifam_addrs;
|
||||||
|
int scope, masklen = -1;
|
||||||
|
int new = (ifam->ifam_type == RTM_NEWADDR);
|
||||||
|
int fl = ifam->ifam_flags;
|
||||||
|
|
||||||
|
if(!(iface = if_find_by_index(ifam->ifam_index)))
|
||||||
|
{
|
||||||
|
log(L_ERR "KIF: Received address message for unknown interface %d", ifam->ifam_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GETADDR (&null, RTA_DST);
|
||||||
|
GETADDR (&null, RTA_GATEWAY);
|
||||||
|
GETADDR (&mask, RTA_NETMASK);
|
||||||
|
GETADDR (&null, RTA_GENMASK);
|
||||||
|
GETADDR (&null, RTA_IFP);
|
||||||
|
GETADDR (&addr, RTA_IFA);
|
||||||
|
GETADDR (&null, RTA_AUTHOR);
|
||||||
|
GETADDR (&brd, RTA_BRD);
|
||||||
|
|
||||||
|
if(!CHECK_FAMILY(&addr)) return; /* Some other family address */
|
||||||
|
|
||||||
|
get_sockaddr(&addr, &iaddr, NULL, 0);
|
||||||
|
get_sockaddr(&mask, &imask, NULL, 0);
|
||||||
|
get_sockaddr(&brd, &ibrd, NULL, 0);
|
||||||
|
|
||||||
|
if ((masklen = ipa_mklen(imask)) < 0)
|
||||||
|
{
|
||||||
|
log("Invalid masklen");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ifa, 0, sizeof(ifa));
|
||||||
|
|
||||||
|
ifa.iface = iface;
|
||||||
|
|
||||||
|
memcpy(&ifa.ip, &iaddr, sizeof(ip_addr));
|
||||||
|
ifa.pxlen = masklen;
|
||||||
|
memcpy(&ifa.brd, &ibrd, sizeof(ip_addr));
|
||||||
|
|
||||||
|
scope = ipa_classify(ifa.ip);
|
||||||
|
|
||||||
|
ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen));
|
||||||
|
|
||||||
|
if (scope < 0)
|
||||||
|
{
|
||||||
|
log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, iface->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ifa.scope = scope & IADDR_SCOPE_MASK;
|
||||||
|
|
||||||
|
if (new)
|
||||||
|
ifa_update(&ifa);
|
||||||
|
else
|
||||||
|
ifa_delete(&ifa);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_read_msg(struct proto *p, struct ks_msg *msg, int scan)
|
||||||
|
{
|
||||||
|
switch (msg->rtm.rtm_type)
|
||||||
|
{
|
||||||
|
case RTM_GET:
|
||||||
|
if(!scan) return;
|
||||||
|
case RTM_ADD:
|
||||||
|
case RTM_DELETE:
|
||||||
|
//log("KRT_ADD/DELETE");
|
||||||
|
krt_read_rt(msg, (struct krt_proto *)p, scan);
|
||||||
|
break;
|
||||||
|
case RTM_IFINFO:
|
||||||
|
//log("KRT_IFINFO");
|
||||||
|
krt_read_ifinfo(msg);
|
||||||
|
break;
|
||||||
|
case RTM_NEWADDR:
|
||||||
|
case RTM_DELADDR:
|
||||||
|
//log("KRT_NEWADDR/DELADDR");
|
||||||
|
krt_read_addr(msg);
|
||||||
|
break;
|
||||||
|
#ifdef RTM_IFANNOUNCE
|
||||||
|
case RTM_IFANNOUNCE:
|
||||||
|
log("KRT_IFANNOUNCE");
|
||||||
|
//ifan_read (&buf.ian.ifan);
|
||||||
|
break;
|
||||||
|
#endif /* RTM_IFANNOUNCE */
|
||||||
|
default:
|
||||||
|
log("Unprocessed RTM_type: %d", msg->rtm.rtm_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct iface *
|
||||||
|
krt_temp_iface(struct krt_proto *p, char *name)
|
||||||
|
{
|
||||||
|
struct iface *i;
|
||||||
|
|
||||||
|
WALK_LIST(i, p->scan.temp_ifs)
|
||||||
|
if (!strcmp(i->name, name))
|
||||||
|
return i;
|
||||||
|
i = mb_allocz(p->p.pool, sizeof(struct iface));
|
||||||
|
strcpy(i->name, name);
|
||||||
|
add_tail(&p->scan.temp_ifs, &i->n);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_construct(struct krt_config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_preconfig(struct config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_postconfig(struct krt_config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_start(struct krt_proto *x, int first)
|
||||||
|
{
|
||||||
|
init_list(&x->scan.temp_ifs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_shutdown(struct krt_proto *x, int last)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, int *bl, int cmd)
|
||||||
|
{
|
||||||
|
byte *next;
|
||||||
|
int obl, needed, mib[6], on;
|
||||||
|
struct ks_msg *m;
|
||||||
|
|
||||||
|
mib[0] = CTL_NET;
|
||||||
|
mib[1] = PF_ROUTE;
|
||||||
|
mib[2] = 0;
|
||||||
|
mib[3] = BIRD_PF;
|
||||||
|
mib[4] = cmd;
|
||||||
|
mib[5] = 0;
|
||||||
|
|
||||||
|
if( sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
die("RT scan...");
|
||||||
|
}
|
||||||
|
|
||||||
|
obl = *bl;
|
||||||
|
|
||||||
|
while(needed > *bl) *bl *= 2;
|
||||||
|
while(needed < (*bl/2)) *bl /= 2;
|
||||||
|
|
||||||
|
if( (obl!=*bl) || !*buf)
|
||||||
|
{
|
||||||
|
if(*buf) mb_free(*buf);
|
||||||
|
if( (*buf = mb_alloc(pool, *bl)) == NULL ) die("RT scan buf alloc");
|
||||||
|
}
|
||||||
|
|
||||||
|
on = needed;
|
||||||
|
|
||||||
|
if( sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
|
||||||
|
{
|
||||||
|
if(on != needed) return; /* The buffer size changed since last sysctl */
|
||||||
|
die("RT scan 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (next = *buf; next < (*buf + needed); next += m->rtm.rtm_msglen)
|
||||||
|
{
|
||||||
|
m = (struct ks_msg *)next;
|
||||||
|
krt_read_msg(p, m, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_scan_fire(struct krt_proto *p)
|
||||||
|
{
|
||||||
|
static byte *buf = NULL;
|
||||||
|
static int bl = 32768;
|
||||||
|
krt_sysctl_scan((struct proto *)p , p->krt_pool, &buf, &bl, NET_RT_DUMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_if_scan(struct kif_proto *p)
|
||||||
|
{
|
||||||
|
static byte *buf = NULL;
|
||||||
|
static int bl = 4096;
|
||||||
|
struct proto *P = (struct proto *)p;
|
||||||
|
if_start_update();
|
||||||
|
krt_sysctl_scan(P, P->pool, &buf, &bl, NET_RT_IFLIST);
|
||||||
|
if_end_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_set_construct(struct krt_config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_set_shutdown(struct krt_proto *x, int last)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_if_io_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_if_construct(struct kif_config *c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_if_start(struct kif_proto *p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_if_shutdown(struct kif_proto *p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
47
sysdep/bsd/krt-sock.h
Normal file
47
sysdep/bsd/krt-sock.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* BIRD -- Unix Kernel Route Syncer -- Setting
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_KRT_SOCK_H_
|
||||||
|
#define _BIRD_KRT_SOCK_H_
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/route.h>
|
||||||
|
#include "lib/socket.h"
|
||||||
|
|
||||||
|
#ifndef RTAX_MAX
|
||||||
|
#define RTAX_MAX 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct ks_msg
|
||||||
|
{
|
||||||
|
struct rt_msghdr rtm;
|
||||||
|
struct sockaddr_storage buf[RTAX_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extern int krt_set_sock;
|
||||||
|
|
||||||
|
struct krt_set_params {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct krt_set_status {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct krt_if_params {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct krt_if_status {
|
||||||
|
};
|
||||||
|
|
||||||
|
static int krt_set_hook(sock *sk, int size);
|
||||||
|
static inline int krt_set_params_same(struct krt_set_params *o, struct krt_set_params *n) { return 1; }
|
||||||
|
void krt_read_msg(struct proto *p, struct ks_msg *msg, int scan);
|
||||||
|
|
||||||
|
#endif
|
83
sysdep/bsd/sysio.h
Normal file
83
sysdep/bsd/sysio.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* BIRD Internet Routing Daemon -- NetBSD Multicasting and Network Includes
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef IPV6
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_inaddr(struct in6_addr * ia, ip_addr a)
|
||||||
|
{
|
||||||
|
ipa_hton(a);
|
||||||
|
memcpy(ia, &a, sizeof(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_inaddr(struct in_addr * ia, ip_addr a)
|
||||||
|
{
|
||||||
|
ipa_hton(a);
|
||||||
|
memcpy(&ia->s_addr, &a, sizeof(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
sysio_mcast_setup(sock * s)
|
||||||
|
{
|
||||||
|
u8 zero = 0;
|
||||||
|
u8 one = 1;
|
||||||
|
|
||||||
|
if (ipa_nonzero(s->daddr)) {
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0) {
|
||||||
|
log("IP_MULTICAST_LOOP");
|
||||||
|
return "IP_MULTICAST_LOOP";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &one, sizeof(one)) < 0) {
|
||||||
|
log("IP_MULTICAST_TTL");
|
||||||
|
return "IP_MULTICAST_TTL";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
sysio_mcast_join(sock * s)
|
||||||
|
{
|
||||||
|
struct in_addr m;
|
||||||
|
struct ip_mreq mreq;
|
||||||
|
char *err;
|
||||||
|
|
||||||
|
set_inaddr(&m, s->iface->addr->ip );
|
||||||
|
|
||||||
|
memset(&mreq, 0, sizeof(mreq));
|
||||||
|
set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
|
||||||
|
set_inaddr(&mreq.imr_multiaddr, s->daddr);
|
||||||
|
|
||||||
|
/* And this one sets interface for _receiving_ multicasts from */
|
||||||
|
if (ipa_nonzero(s->daddr) && setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
|
||||||
|
log("IP_ADD_MEMBERSHIP");
|
||||||
|
return "IP_ADD_MEMBERSHIP";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This defines where should we send _outgoing_ multicasts */
|
||||||
|
if (ipa_nonzero(s->daddr) && setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0) {
|
||||||
|
log("IP_MULTICAST_IF");
|
||||||
|
return "IP_MULTICAST_IF";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err = sysio_mcast_setup(s))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
24
sysdep/cf/bsd-v6.h
Normal file
24
sysdep/cf/bsd-v6.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Configuration for *BSD based systems (tested on FreeBSD and NetBSD)
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IPV6
|
||||||
|
|
||||||
|
#define CONFIG_AUTO_ROUTES
|
||||||
|
#undef CONFIG_SELF_CONSCIOUS
|
||||||
|
#undef CONFIG_MULTIPLE_TABLES
|
||||||
|
|
||||||
|
#undef CONFIG_UNIX_IFACE
|
||||||
|
#undef CONFIG_UNIX_SET
|
||||||
|
|
||||||
|
#define CONFIG_ALL_MULTICAST
|
||||||
|
#define CONFIG_UNNUM_MULTICAST
|
||||||
|
|
||||||
|
/*
|
||||||
|
Link: sysdep/unix
|
||||||
|
Link: sysdep/bsd
|
||||||
|
*/
|
22
sysdep/cf/bsd.h
Normal file
22
sysdep/cf/bsd.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Configuration for *BSD based systems (tested on FreeBSD and NetBSD)
|
||||||
|
*
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CONFIG_AUTO_ROUTES
|
||||||
|
#undef CONFIG_SELF_CONSCIOUS
|
||||||
|
#undef CONFIG_MULTIPLE_TABLES
|
||||||
|
|
||||||
|
#undef CONFIG_UNIX_IFACE
|
||||||
|
#undef CONFIG_UNIX_SET
|
||||||
|
|
||||||
|
#define CONFIG_ALL_MULTICAST
|
||||||
|
#define CONFIG_UNNUM_MULTICAST
|
||||||
|
|
||||||
|
/*
|
||||||
|
Link: sysdep/unix
|
||||||
|
Link: sysdep/bsd
|
||||||
|
*/
|
@ -2,6 +2,7 @@
|
|||||||
* BIRD Internet Routing Daemon -- Unix I/O
|
* BIRD Internet Routing Daemon -- Unix I/O
|
||||||
*
|
*
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
*
|
*
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*/
|
*/
|
||||||
@ -29,6 +30,7 @@
|
|||||||
#include "lib/unix.h"
|
#include "lib/unix.h"
|
||||||
#include "lib/sysio.h"
|
#include "lib/sysio.h"
|
||||||
|
|
||||||
|
#define LOCAL_DEBUG
|
||||||
/*
|
/*
|
||||||
* Tracked Files
|
* Tracked Files
|
||||||
*/
|
*/
|
||||||
@ -399,6 +401,14 @@ tm_format_reltime(char *x, bird_clock_t t)
|
|||||||
#define SOL_IP IPPROTO_IP
|
#define SOL_IP IPPROTO_IP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef SOL_IPV6
|
||||||
|
#define SOL_IPV6 IPPROTO_IPV6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IPV6_ADD_MEMBERSHIP
|
||||||
|
#define IPV6_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP
|
||||||
|
#endif
|
||||||
|
|
||||||
static list sock_list;
|
static list sock_list;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -476,17 +486,21 @@ sk_new(pool *p)
|
|||||||
void
|
void
|
||||||
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
|
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
|
||||||
{
|
{
|
||||||
|
memset (sa, 0, sizeof (struct sockaddr_in6));
|
||||||
sa->sin6_family = AF_INET6;
|
sa->sin6_family = AF_INET6;
|
||||||
sa->sin6_port = htons(port);
|
sa->sin6_port = htons(port);
|
||||||
sa->sin6_flowinfo = 0;
|
sa->sin6_flowinfo = 0;
|
||||||
|
#ifdef HAVE_SIN_LEN
|
||||||
|
sa->sin6_len = sizeof(struct sockaddr_in6);
|
||||||
|
#endif
|
||||||
set_inaddr(&sa->sin6_addr, a);
|
set_inaddr(&sa->sin6_addr, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port)
|
get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, unsigned *port, int check)
|
||||||
{
|
{
|
||||||
if (sa->sin6_family != AF_INET6)
|
if (check && sa->sin6_family != AF_INET6)
|
||||||
bug("get_sockaddr called for wrong address family");
|
bug("get_sockaddr called for wrong address family (%d)", sa->sin6_family);
|
||||||
if (port)
|
if (port)
|
||||||
*port = ntohs(sa->sin6_port);
|
*port = ntohs(sa->sin6_port);
|
||||||
memcpy(a, &sa->sin6_addr, sizeof(*a));
|
memcpy(a, &sa->sin6_addr, sizeof(*a));
|
||||||
@ -498,16 +512,20 @@ get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port)
|
|||||||
void
|
void
|
||||||
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
|
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
|
||||||
{
|
{
|
||||||
|
memset (sa, 0, sizeof (struct sockaddr_in));
|
||||||
sa->sin_family = AF_INET;
|
sa->sin_family = AF_INET;
|
||||||
sa->sin_port = htons(port);
|
sa->sin_port = htons(port);
|
||||||
|
#ifdef HAVE_SIN_LEN
|
||||||
|
sa->sin_len = sizeof(struct sockaddr_in);
|
||||||
|
#endif
|
||||||
set_inaddr(&sa->sin_addr, a);
|
set_inaddr(&sa->sin_addr, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port)
|
get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
|
||||||
{
|
{
|
||||||
if (sa->sin_family != AF_INET)
|
if (check && sa->sin_family != AF_INET)
|
||||||
bug("get_sockaddr called for wrong address family");
|
bug("get_sockaddr called for wrong address family (%d)", sa->sin_family);
|
||||||
if (port)
|
if (port)
|
||||||
*port = ntohs(sa->sin_port);
|
*port = ntohs(sa->sin_port);
|
||||||
memcpy(a, &sa->sin_addr.s_addr, sizeof(*a));
|
memcpy(a, &sa->sin_addr.s_addr, sizeof(*a));
|
||||||
@ -536,8 +554,8 @@ sk_setup(sock *s)
|
|||||||
WARN("IP_TOS");
|
WARN("IP_TOS");
|
||||||
if (s->ttl >= 0 && setsockopt(fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
if (s->ttl >= 0 && setsockopt(fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
||||||
ERR("IP_TTL");
|
ERR("IP_TTL");
|
||||||
if (s->ttl == 1 && setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
|
//if (s->ttl == 1 && setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
|
||||||
ERR("SO_DONTROUTE");
|
// ERR("SO_DONTROUTE");
|
||||||
#endif
|
#endif
|
||||||
err = NULL;
|
err = NULL;
|
||||||
bad:
|
bad:
|
||||||
@ -578,7 +596,7 @@ sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
|
|||||||
t->rbsize = s->rbsize;
|
t->rbsize = s->rbsize;
|
||||||
t->tbsize = s->tbsize;
|
t->tbsize = s->tbsize;
|
||||||
if (type == SK_TCP)
|
if (type == SK_TCP)
|
||||||
get_sockaddr((sockaddr *) sa, &t->daddr, &t->dport);
|
get_sockaddr((sockaddr *) sa, &t->daddr, &t->dport, 1);
|
||||||
add_tail(&sock_list, &t->n);
|
add_tail(&sock_list, &t->n);
|
||||||
if (err = sk_setup(t))
|
if (err = sk_setup(t))
|
||||||
{
|
{
|
||||||
@ -645,7 +663,9 @@ sk_open(sock *s)
|
|||||||
s->fd = fd;
|
s->fd = fd;
|
||||||
|
|
||||||
if (err = sk_setup(s))
|
if (err = sk_setup(s))
|
||||||
|
{
|
||||||
goto bad;
|
goto bad;
|
||||||
|
}
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case SK_UDP:
|
case SK_UDP:
|
||||||
@ -683,7 +703,7 @@ sk_open(sock *s)
|
|||||||
mreq.ipv6mr_ifindex = s->iface->index;
|
mreq.ipv6mr_ifindex = s->iface->index;
|
||||||
#else
|
#else
|
||||||
mreq.ipv6mr_interface = s->iface->index;
|
mreq.ipv6mr_interface = s->iface->index;
|
||||||
#endif
|
#endif /* CONFIG_IPV6_GLIBC_20 */
|
||||||
if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||||
ERR("IPV6_ADD_MEMBERSHIP");
|
ERR("IPV6_ADD_MEMBERSHIP");
|
||||||
}
|
}
|
||||||
@ -692,7 +712,7 @@ sk_open(sock *s)
|
|||||||
ASSERT(s->iface && s->iface->addr);
|
ASSERT(s->iface && s->iface->addr);
|
||||||
if (err = sysio_mcast_join(s))
|
if (err = sysio_mcast_join(s))
|
||||||
goto bad;
|
goto bad;
|
||||||
#endif
|
#endif /* IPV6 */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -842,6 +862,7 @@ sk_maybe_write(sock *s)
|
|||||||
if (s->tbuf == s->tpos)
|
if (s->tbuf == s->tpos)
|
||||||
return 1;
|
return 1;
|
||||||
fill_in_sockaddr(&sa, s->faddr, s->fport);
|
fill_in_sockaddr(&sa, s->faddr, s->fport);
|
||||||
|
|
||||||
e = sendto(s->fd, s->tbuf, s->tpos - s->tbuf, 0, (struct sockaddr *) &sa, sizeof(sa));
|
e = sendto(s->fd, s->tbuf, s->tpos - s->tbuf, 0, (struct sockaddr *) &sa, sizeof(sa));
|
||||||
if (e < 0)
|
if (e < 0)
|
||||||
{
|
{
|
||||||
@ -955,7 +976,7 @@ sk_read(sock *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
s->rpos = s->rbuf + e;
|
s->rpos = s->rbuf + e;
|
||||||
get_sockaddr(&sa, &s->faddr, &s->fport);
|
get_sockaddr(&sa, &s->faddr, &s->fport, 1);
|
||||||
s->rx_hook(s, e);
|
s->rx_hook(s, e);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* BIRD -- Unix Interface Scanning and Syncing
|
* BIRD -- Unix Interface Scanning and Syncing
|
||||||
*
|
*
|
||||||
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
|
||||||
|
* (c) 2004 Ondrej Filip <feela@network.cz>
|
||||||
*
|
*
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*/
|
*/
|
||||||
@ -36,6 +37,7 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||||||
unsigned fl;
|
unsigned fl;
|
||||||
ip_addr netmask;
|
ip_addr netmask;
|
||||||
int l, scope;
|
int l, scope;
|
||||||
|
sockaddr *sa;
|
||||||
|
|
||||||
if_start_update();
|
if_start_update();
|
||||||
for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
|
for (cnt /= sizeof(struct ifreq); cnt; cnt--, r++)
|
||||||
@ -43,7 +45,6 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||||||
int sec = 0;
|
int sec = 0;
|
||||||
bzero(&i, sizeof(i));
|
bzero(&i, sizeof(i));
|
||||||
bzero(&a, sizeof(a));
|
bzero(&a, sizeof(a));
|
||||||
DBG("%s\n", r->ifr_name);
|
|
||||||
if (colon = strchr(r->ifr_name, ':'))
|
if (colon = strchr(r->ifr_name, ':'))
|
||||||
{
|
{
|
||||||
/* It's an alias -- let's interpret it as a secondary interface address */
|
/* It's an alias -- let's interpret it as a secondary interface address */
|
||||||
@ -51,7 +52,10 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||||||
*colon = 0;
|
*colon = 0;
|
||||||
}
|
}
|
||||||
strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);
|
strncpy(i.name, r->ifr_name, sizeof(i.name) - 1);
|
||||||
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL);
|
|
||||||
|
if(ioctl(if_scan_sock, SIOCGIFADDR,r)<0) continue;
|
||||||
|
|
||||||
|
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.ip, NULL, 1);
|
||||||
if (ipa_nonzero(a.ip))
|
if (ipa_nonzero(a.ip))
|
||||||
{
|
{
|
||||||
l = ipa_classify(a.ip);
|
l = ipa_classify(a.ip);
|
||||||
@ -83,11 +87,11 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||||||
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
|
if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
|
||||||
{ err = "SIOCGIFNETMASK"; goto faulty; }
|
{ err = "SIOCGIFNETMASK"; goto faulty; }
|
||||||
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &netmask, NULL);
|
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &netmask, NULL, 0);
|
||||||
l = ipa_mklen(netmask);
|
l = ipa_mklen(netmask);
|
||||||
if (l < 0 || l == 31)
|
if (l < 0 || l == 31)
|
||||||
{
|
{
|
||||||
log(L_ERR "%s: Invalid netmask", i.name);
|
log(L_ERR "%s: Invalid netmask (%x)", i.name, netmask);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
a.pxlen = l;
|
a.pxlen = l;
|
||||||
@ -97,7 +101,7 @@ scan_ifs(struct ifreq *r, int cnt)
|
|||||||
a.flags |= IA_UNNUMBERED;
|
a.flags |= IA_UNNUMBERED;
|
||||||
if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
|
if (ioctl(if_scan_sock, SIOCGIFDSTADDR, r) < 0)
|
||||||
{ err = "SIOCGIFDSTADDR"; goto faulty; }
|
{ err = "SIOCGIFDSTADDR"; goto faulty; }
|
||||||
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL);
|
get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &a.opposite, NULL, 1);
|
||||||
a.prefix = a.opposite;
|
a.prefix = a.opposite;
|
||||||
a.pxlen = BITS_PER_IP_ADDRESS;
|
a.pxlen = BITS_PER_IP_ADDRESS;
|
||||||
}
|
}
|
||||||
@ -188,40 +192,17 @@ krt_if_scan(struct kif_proto *p)
|
|||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
if (last_ifbuf_size)
|
ic.ifc_buf = alloca(last_ifbuf_size);
|
||||||
{
|
ic.ifc_len = last_ifbuf_size;
|
||||||
struct ifreq *r = alloca(last_ifbuf_size);
|
res = ioctl(if_scan_sock, SIOCGIFCONF, &ic);
|
||||||
ic.ifc_ifcu.ifcu_req = r;
|
if (res < 0 && errno != EFAULT)
|
||||||
ic.ifc_len = last_ifbuf_size;
|
die("SIOCCGIFCONF: %m");
|
||||||
res = ioctl(if_scan_sock, SIOCGIFCONF, &ic);
|
if (res >= 0 && ic.ifc_len <= last_ifbuf_size)
|
||||||
if (res < 0 && errno != EFAULT)
|
break;
|
||||||
die("SIOCCGIFCONF: %m");
|
|
||||||
if (res >= 0 && ic.ifc_len < last_ifbuf_size)
|
|
||||||
{
|
|
||||||
scan_ifs(r, ic.ifc_len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* Linux 2.1 and higher supports this, but it's not needed since
|
|
||||||
* we prefer to use Netlink there anyway.
|
|
||||||
*/
|
|
||||||
ic.ifc_req = NULL;
|
|
||||||
ic.ifc_len = 999999999;
|
|
||||||
if (ioctl(if_scan_sock, SIOCGIFCONF, &ic) < 0)
|
|
||||||
die("SIOCIFCONF: %m");
|
|
||||||
ic.ifc_len += sizeof(struct ifreq);
|
|
||||||
if (last_ifbuf_size < ic.ifc_len)
|
|
||||||
{
|
|
||||||
last_ifbuf_size = ic.ifc_len;
|
|
||||||
DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
last_ifbuf_size *= 2;
|
last_ifbuf_size *= 2;
|
||||||
DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size);
|
DBG("Increased ifconf buffer size to %d\n", last_ifbuf_size);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
scan_ifs(ic.ifc_req, ic.ifc_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -247,3 +228,4 @@ krt_if_io_init(void)
|
|||||||
if (if_scan_sock < 0)
|
if (if_scan_sock < 0)
|
||||||
die("Cannot create scanning socket: %m");
|
die("Cannot create scanning socket: %m");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <net/route.h>
|
#include <net/route.h>
|
||||||
|
|
||||||
#undef LOCAL_DEBUG
|
#undef LOCAL_DEBUG
|
||||||
|
#define LOCAL_DEBUG
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
@ -36,7 +37,7 @@ krt_capable(rte *e)
|
|||||||
(a->dest == RTD_ROUTER
|
(a->dest == RTD_ROUTER
|
||||||
|| a->dest == RTD_DEVICE
|
|| a->dest == RTD_DEVICE
|
||||||
#ifdef RTF_REJECT
|
#ifdef RTF_REJECT
|
||||||
|| a->dest == RTD_UNREACHABLE
|
|| a->dest == RTD_UNREACHABLE /* FIXME Blackhole, prohibited?? */
|
||||||
#endif
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -45,12 +46,12 @@ static void
|
|||||||
krt_ioctl(int ioc, rte *e, char *name)
|
krt_ioctl(int ioc, rte *e, char *name)
|
||||||
{
|
{
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
struct rtentry re;
|
struct ortentry re;
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
|
|
||||||
bzero(&re, sizeof(re));
|
bzero(&re, sizeof(re));
|
||||||
fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
|
fill_in_sockaddr((struct sockaddr_in *) &re.rt_dst, net->n.prefix, 0);
|
||||||
fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
|
//fill_in_sockaddr((struct sockaddr_in *) &re.rt_genmask, ipa_mkmask(net->n.pxlen), 0);
|
||||||
re.rt_flags = RTF_UP;
|
re.rt_flags = RTF_UP;
|
||||||
if (net->n.pxlen == 32)
|
if (net->n.pxlen == 32)
|
||||||
re.rt_flags |= RTF_HOST;
|
re.rt_flags |= RTF_HOST;
|
||||||
@ -61,7 +62,7 @@ krt_ioctl(int ioc, rte *e, char *name)
|
|||||||
re.rt_flags |= RTF_GATEWAY;
|
re.rt_flags |= RTF_GATEWAY;
|
||||||
break;
|
break;
|
||||||
case RTD_DEVICE:
|
case RTD_DEVICE:
|
||||||
re.rt_dev = a->iface->name;
|
//re.rt_dev = a->iface->name;
|
||||||
break;
|
break;
|
||||||
#ifdef RTF_REJECT
|
#ifdef RTF_REJECT
|
||||||
case RTD_UNREACHABLE:
|
case RTD_UNREACHABLE:
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "lib/lists.h"
|
#include "lib/lists.h"
|
||||||
|
@ -43,7 +43,7 @@ struct birdsock;
|
|||||||
void io_init(void);
|
void io_init(void);
|
||||||
void io_loop(void);
|
void io_loop(void);
|
||||||
void fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port);
|
void fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port);
|
||||||
void get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port);
|
void get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port, int check);
|
||||||
int sk_open_unix(struct birdsock *s, char *name);
|
int sk_open_unix(struct birdsock *s, char *name);
|
||||||
void *tracked_fopen(struct pool *, char *name, char *mode);
|
void *tracked_fopen(struct pool *, char *name, char *mode);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user