mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
Update socket code to be synced with master branch.
This commit is contained in:
parent
621782ecee
commit
abffa9d421
@ -19,7 +19,6 @@
|
|||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "client/client.h"
|
#include "client/client.h"
|
||||||
#include "sysdep/unix/unix.h"
|
|
||||||
|
|
||||||
static int input_hidden_end;
|
static int input_hidden_end;
|
||||||
static int prompt_active;
|
static int prompt_active;
|
||||||
|
8
lib/ip.h
8
lib/ip.h
@ -149,7 +149,7 @@ static inline ip6_addr ip6_not(ip6_addr a)
|
|||||||
#define ipa_from_ip6(x) x
|
#define ipa_from_ip6(x) x
|
||||||
#define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
|
#define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
|
||||||
|
|
||||||
#define ipa_to_ip4(x) _I3(x)
|
#define ipa_to_ip4(x) _MI4(_I3(x))
|
||||||
#define ipa_to_ip6(x) x
|
#define ipa_to_ip6(x) x
|
||||||
#define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
|
#define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
|
||||||
|
|
||||||
@ -356,12 +356,6 @@ static inline ip6_addr ipa_get_in4(struct in_addr *in)
|
|||||||
static inline ip6_addr ipa_get_in6(struct in6_addr *in)
|
static inline ip6_addr ipa_get_in6(struct in6_addr *in)
|
||||||
{ return ip6_ntoh(*(ip6_addr *) in); }
|
{ return ip6_ntoh(*(ip6_addr *) in); }
|
||||||
|
|
||||||
// XXXX check callers
|
|
||||||
static inline void ipa_put_in4(struct in_addr *in, ip6_addr a)
|
|
||||||
{ ip6_put32_ip4(in, a); }
|
|
||||||
|
|
||||||
static inline void ipa_put_in6(struct in6_addr *in, ip6_addr a)
|
|
||||||
{ ip6_put32(in, a); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
10
lib/printf.c
10
lib/printf.c
@ -222,6 +222,16 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
|
if (flags & SPECIAL) {
|
||||||
|
if (!errno)
|
||||||
|
continue;
|
||||||
|
if (size < 2)
|
||||||
|
return -1;
|
||||||
|
*str++ = ':';
|
||||||
|
*str++ = ' ';
|
||||||
|
start += 2;
|
||||||
|
size -= 2;
|
||||||
|
}
|
||||||
s = strerror(errno);
|
s = strerror(errno);
|
||||||
goto str;
|
goto str;
|
||||||
case 'M':
|
case 'M':
|
||||||
|
34
lib/socket.h
34
lib/socket.h
@ -44,18 +44,21 @@ typedef struct birdsock {
|
|||||||
unsigned lifindex; /* local interface that received the datagram */
|
unsigned lifindex; /* local interface that received the datagram */
|
||||||
/* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */
|
/* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */
|
||||||
|
|
||||||
int fd; /* System-dependent data */
|
|
||||||
int af; /* Address family (AF_INET, AF_INET6 or 0 for non-IP) of fd */
|
int af; /* Address family (AF_INET, AF_INET6 or 0 for non-IP) of fd */
|
||||||
|
int fd; /* System-dependent data */
|
||||||
int index; /* Index in poll buffer */
|
int index; /* Index in poll buffer */
|
||||||
|
int rcv_ttl; /* TTL of last received datagram */
|
||||||
node n;
|
node n;
|
||||||
void *rbuf_alloc, *tbuf_alloc;
|
void *rbuf_alloc, *tbuf_alloc;
|
||||||
char *password; /* Password for MD5 authentication */
|
char *password; /* Password for MD5 authentication */
|
||||||
|
char *err; /* Error message */
|
||||||
} sock;
|
} sock;
|
||||||
|
|
||||||
sock *sock_new(pool *); /* Allocate new socket */
|
sock *sock_new(pool *); /* Allocate new socket */
|
||||||
#define sk_new(X) sock_new(X) /* Wrapper to avoid name collision with OpenSSL */
|
#define sk_new(X) sock_new(X) /* Wrapper to avoid name collision with OpenSSL */
|
||||||
|
|
||||||
int sk_open(sock *); /* Open socket */
|
int sk_open(sock *); /* Open socket */
|
||||||
|
int sk_rx_ready(sock *s);
|
||||||
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
|
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
|
||||||
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
|
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
|
||||||
void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */
|
void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */
|
||||||
@ -63,33 +66,32 @@ void sk_set_rbsize(sock *s, uint val); /* Resize RX buffer */
|
|||||||
void sk_set_tbsize(sock *s, uint val); /* Resize TX buffer, keeping content */
|
void sk_set_tbsize(sock *s, uint val); /* Resize TX buffer, keeping content */
|
||||||
void sk_set_tbuf(sock *s, void *tbuf); /* Switch TX buffer, NULL-> return to internal */
|
void sk_set_tbuf(sock *s, void *tbuf); /* Switch TX buffer, NULL-> return to internal */
|
||||||
void sk_dump_all(void);
|
void sk_dump_all(void);
|
||||||
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
|
|
||||||
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
|
|
||||||
|
|
||||||
/* Add or remove security associations for given passive socket */
|
|
||||||
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
|
|
||||||
int sk_rx_ready(sock *s);
|
|
||||||
|
|
||||||
/* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */
|
|
||||||
int sk_setup_multicast(sock *s);
|
|
||||||
int sk_join_group(sock *s, ip_addr maddr);
|
|
||||||
int sk_leave_group(sock *s, ip_addr maddr);
|
|
||||||
|
|
||||||
int sk_set_ipv6_checksum(sock *s, int offset);
|
|
||||||
int sk_set_icmp6_filter(sock *s, int p1, int p2);
|
|
||||||
int sk_set_broadcast(sock *s, int enable);
|
|
||||||
|
|
||||||
static inline int sk_send_buffer_empty(sock *sk)
|
static inline int sk_send_buffer_empty(sock *sk)
|
||||||
{ return sk->tbuf == sk->tpos; }
|
{ return sk->tbuf == sk->tpos; }
|
||||||
|
|
||||||
|
|
||||||
static inline int sk_is_ipv4(sock *sk)
|
static inline int sk_is_ipv4(sock *sk)
|
||||||
{ return sk->af == AF_INET; }
|
{ return sk->af == AF_INET; }
|
||||||
|
|
||||||
static inline int sk_is_ipv6(sock *sk)
|
static inline int sk_is_ipv6(sock *sk)
|
||||||
{ return sk->af == AF_INET6; }
|
{ return sk->af == AF_INET6; }
|
||||||
|
|
||||||
|
|
||||||
|
int sk_setup_multicast(sock *s); /* Prepare UDP or IP socket for multicasting */
|
||||||
|
int sk_join_group(sock *s, ip_addr maddr); /* Join multicast group on sk iface */
|
||||||
|
int sk_leave_group(sock *s, ip_addr maddr); /* Leave multicast group on sk iface */
|
||||||
|
int sk_setup_broadcast(sock *s);
|
||||||
|
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
|
||||||
|
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
|
||||||
|
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
|
||||||
|
int sk_set_ipv6_checksum(sock *s, int offset);
|
||||||
|
int sk_set_icmp6_filter(sock *s, int p1, int p2);
|
||||||
|
void sk_log_error(sock *s, const char *p);
|
||||||
|
|
||||||
extern int sk_priority_control; /* Suggested priority for control traffic, should be sysdep define */
|
extern int sk_priority_control; /* Suggested priority for control traffic, should be sysdep define */
|
||||||
|
|
||||||
|
|
||||||
/* Socket flags */
|
/* Socket flags */
|
||||||
|
|
||||||
#define SKF_V4ONLY 0x01 /* Use IPv4 for IP sockets */
|
#define SKF_V4ONLY 0x01 /* Use IPv4 for IP sockets */
|
||||||
|
@ -101,8 +101,8 @@ bfd_rx_hook(sock *sk, int len)
|
|||||||
uint err_val = 0;
|
uint err_val = 0;
|
||||||
char fb[8];
|
char fb[8];
|
||||||
|
|
||||||
if ((sk->sport == BFD_CONTROL_PORT) && (sk->ttl < 255))
|
if ((sk->sport == BFD_CONTROL_PORT) && (sk->rcv_ttl < 255))
|
||||||
DROP("wrong TTL", sk->ttl);
|
DROP("wrong TTL", sk->rcv_ttl);
|
||||||
|
|
||||||
if (len < BFD_BASE_LEN)
|
if (len < BFD_BASE_LEN)
|
||||||
DROP("too short", len);
|
DROP("too short", len);
|
||||||
@ -209,6 +209,7 @@ bfd_open_rx_sk(struct bfd_proto *p, int multihop)
|
|||||||
return sk;
|
return sk;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
sk_log_error(sk, p->p.name);
|
||||||
rfree(sk);
|
rfree(sk);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -243,6 +244,7 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
|
|||||||
return sk;
|
return sk;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
sk_log_error(sk, p->p.name);
|
||||||
rfree(sk);
|
rfree(sk);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -106,14 +106,11 @@ bgp_open(struct bgp_proto *p)
|
|||||||
struct config *cfg = p->cf->c.global;
|
struct config *cfg = p->cf->c.global;
|
||||||
int errcode;
|
int errcode;
|
||||||
|
|
||||||
bgp_counter++;
|
|
||||||
|
|
||||||
if (!bgp_listen_sk)
|
if (!bgp_listen_sk)
|
||||||
bgp_listen_sk = bgp_setup_listen_sk(cfg->listen_bgp_addr, cfg->listen_bgp_port, cfg->listen_bgp_flags);
|
bgp_listen_sk = bgp_setup_listen_sk(cfg->listen_bgp_addr, cfg->listen_bgp_port, cfg->listen_bgp_flags);
|
||||||
|
|
||||||
if (!bgp_listen_sk)
|
if (!bgp_listen_sk)
|
||||||
{
|
{
|
||||||
bgp_counter--;
|
|
||||||
errcode = BEM_NO_SOCKET;
|
errcode = BEM_NO_SOCKET;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -121,16 +118,16 @@ bgp_open(struct bgp_proto *p)
|
|||||||
if (!bgp_linpool)
|
if (!bgp_linpool)
|
||||||
bgp_linpool = lp_new(&root_pool, 4080);
|
bgp_linpool = lp_new(&root_pool, 4080);
|
||||||
|
|
||||||
|
bgp_counter++;
|
||||||
|
|
||||||
if (p->cf->password)
|
if (p->cf->password)
|
||||||
|
if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password) < 0)
|
||||||
{
|
{
|
||||||
int rv = sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, p->cf->password);
|
sk_log_error(bgp_listen_sk, p->p.name);
|
||||||
if (rv < 0)
|
|
||||||
{
|
|
||||||
bgp_close(p, 0);
|
bgp_close(p, 0);
|
||||||
errcode = BEM_INVALID_MD5;
|
errcode = BEM_INVALID_MD5;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -194,7 +191,8 @@ bgp_close(struct bgp_proto *p, int apply_md5)
|
|||||||
bgp_counter--;
|
bgp_counter--;
|
||||||
|
|
||||||
if (p->cf->password && apply_md5)
|
if (p->cf->password && apply_md5)
|
||||||
sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL);
|
if (sk_set_md5_auth(bgp_listen_sk, p->cf->remote_ip, p->cf->iface, NULL) < 0)
|
||||||
|
sk_log_error(bgp_listen_sk, p->p.name);
|
||||||
|
|
||||||
if (!bgp_counter)
|
if (!bgp_counter)
|
||||||
{
|
{
|
||||||
@ -697,25 +695,21 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
|
|||||||
bgp_conn_set_state(conn, BS_CONNECT);
|
bgp_conn_set_state(conn, BS_CONNECT);
|
||||||
|
|
||||||
if (sk_open(s) < 0)
|
if (sk_open(s) < 0)
|
||||||
{
|
goto err;
|
||||||
bgp_sock_err(s, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set minimal receive TTL if needed */
|
/* Set minimal receive TTL if needed */
|
||||||
if (p->cf->ttl_security)
|
if (p->cf->ttl_security)
|
||||||
{
|
|
||||||
DBG("Setting minimum received TTL to %d", 256 - hops);
|
|
||||||
if (sk_set_min_ttl(s, 256 - hops) < 0)
|
if (sk_set_min_ttl(s, 256 - hops) < 0)
|
||||||
{
|
goto err;
|
||||||
log(L_ERR "TTL security configuration failed, closing session");
|
|
||||||
bgp_sock_err(s, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG("BGP: Waiting for connect success\n");
|
DBG("BGP: Waiting for connect success\n");
|
||||||
bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
|
bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
sk_log_error(s, p->p.name);
|
||||||
|
bgp_sock_err(s, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -760,32 +754,33 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED)
|
|||||||
sk->dport, acc ? "accepted" : "rejected");
|
sk->dport, acc ? "accepted" : "rejected");
|
||||||
|
|
||||||
if (!acc)
|
if (!acc)
|
||||||
goto err;
|
goto reject;
|
||||||
|
|
||||||
int hops = p->cf->multihop ? : 1;
|
int hops = p->cf->multihop ? : 1;
|
||||||
if (p->cf->ttl_security)
|
|
||||||
{
|
if (sk_set_ttl(sk, p->cf->ttl_security ? 255 : hops) < 0)
|
||||||
/* TTL security support */
|
goto err;
|
||||||
if ((sk_set_ttl(sk, 255) < 0) ||
|
|
||||||
(sk_set_min_ttl(sk, 256 - hops) < 0))
|
if (p->cf->ttl_security)
|
||||||
{
|
if (sk_set_min_ttl(sk, 256 - hops) < 0)
|
||||||
log(L_ERR "TTL security configuration failed, closing session");
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
sk_set_ttl(sk, hops);
|
|
||||||
|
|
||||||
bgp_setup_conn(p, &p->incoming_conn);
|
bgp_setup_conn(p, &p->incoming_conn);
|
||||||
bgp_setup_sk(&p->incoming_conn, sk);
|
bgp_setup_sk(&p->incoming_conn, sk);
|
||||||
bgp_send_open(&p->incoming_conn);
|
bgp_send_open(&p->incoming_conn);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
sk_log_error(sk, p->p.name);
|
||||||
|
log(L_ERR "%s: Incoming connection aborted", p->p.name);
|
||||||
|
rfree(sk);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
|
log(L_WARN "BGP: Unexpected connect from unknown address %I%J (port %d)",
|
||||||
sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport);
|
sk->daddr, ipa_has_link_scope(sk->daddr) ? sk->iface : NULL, sk->dport);
|
||||||
err:
|
reject:
|
||||||
rfree(sk);
|
rfree(sk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -816,13 +811,15 @@ bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags)
|
|||||||
s->err_hook = bgp_listen_sock_err;
|
s->err_hook = bgp_listen_sock_err;
|
||||||
|
|
||||||
if (sk_open(s) < 0)
|
if (sk_open(s) < 0)
|
||||||
{
|
goto err;
|
||||||
log(L_ERR "BGP: Unable to open listening socket");
|
|
||||||
rfree(s);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
|
err:
|
||||||
|
sk_log_error(s, "BGP");
|
||||||
|
log(L_ERR "BGP: Cannot open listening socket");
|
||||||
|
rfree(s);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -123,7 +123,7 @@ ospf_sk_open(struct ospf_iface *ifa)
|
|||||||
ifa->all_routers = ifa->addr->brd;
|
ifa->all_routers = ifa->addr->brd;
|
||||||
ifa->des_routers = IPA_NONE;
|
ifa->des_routers = IPA_NONE;
|
||||||
|
|
||||||
if (sk_set_broadcast(sk, 1) < 0)
|
if (sk_setup_broadcast(sk) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -144,6 +144,7 @@ ospf_sk_open(struct ospf_iface *ifa)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
sk_log_error(sk, po->proto.name);
|
||||||
rfree(sk);
|
rfree(sk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -154,7 +155,9 @@ ospf_sk_join_dr(struct ospf_iface *ifa)
|
|||||||
if (ifa->sk_dr)
|
if (ifa->sk_dr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sk_join_group(ifa->sk, ifa->des_routers);
|
if (sk_join_group(ifa->sk, ifa->des_routers) < 0)
|
||||||
|
sk_log_error(sk, ifa->oa->po->proto.name);
|
||||||
|
|
||||||
ifa->sk_dr = 1;
|
ifa->sk_dr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +167,9 @@ ospf_sk_leave_dr(struct ospf_iface *ifa)
|
|||||||
if (!ifa->sk_dr)
|
if (!ifa->sk_dr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sk_leave_group(ifa->sk, ifa->des_routers);
|
if (sk_leave_group(ifa->sk, ifa->des_routers) < 0)
|
||||||
|
sk_log_error(sk, ifa->oa->po->proto.name);
|
||||||
|
|
||||||
ifa->sk_dr = 0;
|
ifa->sk_dr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,8 +203,9 @@ ospf_open_vlink_sk(struct proto_ospf *po)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
rfree(sk);
|
sk_log_error(sk, po->proto.name);
|
||||||
log(L_ERR "%s: Cannot open virtual link socket", po->proto.name);
|
log(L_ERR "%s: Cannot open virtual link socket", po->proto.name);
|
||||||
|
rfree(sk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -459,7 +465,7 @@ ospf_iface_add(struct object_lock *lock)
|
|||||||
/* Open socket if interface is not stub */
|
/* Open socket if interface is not stub */
|
||||||
if (! ifa->stub && ! ospf_sk_open(ifa))
|
if (! ifa->stub && ! ospf_sk_open(ifa))
|
||||||
{
|
{
|
||||||
log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->ifname);
|
log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->name, ifa->ifname);
|
||||||
ifa->ioprob = OSPF_I_SK;
|
ifa->ioprob = OSPF_I_SK;
|
||||||
ifa->stub = 1;
|
ifa->stub = 1;
|
||||||
}
|
}
|
||||||
|
@ -310,9 +310,9 @@ ospf_rx_hook(sock *sk, int size)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ifa->check_ttl && (sk->ttl < 255))
|
if (ifa->check_ttl && (sk->rcv_ttl < 255))
|
||||||
{
|
{
|
||||||
log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->ttl);
|
log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->rcv_ttl);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,7 +416,7 @@ radv_sk_open(struct radv_iface *ifa)
|
|||||||
sk->data = ifa;
|
sk->data = ifa;
|
||||||
sk->flags = SKF_LADDR_RX;
|
sk->flags = SKF_LADDR_RX;
|
||||||
|
|
||||||
if (sk_open(sk) != 0)
|
if (sk_open(sk) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* We want listen just to ICMPv6 messages of type RS and RA */
|
/* We want listen just to ICMPv6 messages of type RS and RA */
|
||||||
@ -433,6 +433,7 @@ radv_sk_open(struct radv_iface *ifa)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
sk_log_error(sk, ifa->ra->p.name);
|
||||||
rfree(sk);
|
rfree(sk);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -484,10 +484,10 @@ rip_rx(sock *s, int size)
|
|||||||
iface = i->iface;
|
iface = i->iface;
|
||||||
|
|
||||||
|
|
||||||
if (i->check_ttl && (s->ttl < 255))
|
if (i->check_ttl && (s->rcv_ttl < 255))
|
||||||
{
|
{
|
||||||
log( L_REMOTE "%s: Discarding packet with TTL %d (< 255) from %I on %s",
|
log( L_REMOTE "%s: Discarding packet with TTL %d (< 255) from %I on %s",
|
||||||
p->name, s->ttl, s->faddr, i->iface->name);
|
p->name, s->rcv_ttl, s->faddr, i->iface->name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,7 +743,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sk_set_broadcast(rif->sock, 1) < 0)
|
if (sk_setup_broadcast(rif->sock) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -753,7 +753,8 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
|||||||
return rif;
|
return rif;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
log( L_ERR "%s: could not create socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
|
sk_log_error(rif->sock, p->name);
|
||||||
|
log(L_ERR "%s: Cannot open socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
|
||||||
if (rif->iface) {
|
if (rif->iface) {
|
||||||
rfree(rif->sock);
|
rfree(rif->sock);
|
||||||
mb_free(rif);
|
mb_free(rif);
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* BIRD Internet Routing Daemon -- NetBSD Multicasting and Network Includes
|
* BIRD Internet Routing Daemon -- BSD Multicasting and Network Includes
|
||||||
*
|
*
|
||||||
* (c) 2004 Ondrej Filip <feela@network.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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
#include <netinet/in_systm.h> // Workaround for some BSDs
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __NetBSD__
|
#ifdef __NetBSD__
|
||||||
|
|
||||||
#ifndef IP_RECVTTL
|
#ifndef IP_RECVTTL
|
||||||
@ -23,127 +28,116 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <net/if.h>
|
#define SA_LEN(x) (x).sa.sa_len
|
||||||
#include <net/if_dl.h>
|
|
||||||
#include <netinet/in_systm.h> // Workaround for some BSDs
|
|
||||||
#include <netinet/ip.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* BSD Multicast handling for IPv4 */
|
/*
|
||||||
|
* BSD IPv4 multicast syscalls
|
||||||
|
*/
|
||||||
|
|
||||||
static inline char *
|
#define INIT_MREQ4(maddr,ifa) \
|
||||||
|
{ .imr_multiaddr = ipa_to_in4(maddr), .imr_interface = ipa_to_in4(ifa->addr->ip) }
|
||||||
|
|
||||||
|
static inline int
|
||||||
sk_setup_multicast4(sock *s)
|
sk_setup_multicast4(sock *s)
|
||||||
{
|
{
|
||||||
struct in_addr m;
|
struct in_addr ifa = ipa_to_in4(s->iface->addr->ip);
|
||||||
u8 zero = 0;
|
|
||||||
u8 ttl = s->ttl;
|
u8 ttl = s->ttl;
|
||||||
|
u8 n = 0;
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
|
||||||
return "IP_MULTICAST_LOOP";
|
|
||||||
|
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
|
||||||
return "IP_MULTICAST_TTL";
|
|
||||||
|
|
||||||
/* This defines where should we send _outgoing_ multicasts */
|
/* This defines where should we send _outgoing_ multicasts */
|
||||||
ipa_put_in4(&m, s->iface->addr->ip);
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &ifa, sizeof(ifa)) < 0)
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
ERR("IP_MULTICAST_IF");
|
||||||
return "IP_MULTICAST_IF";
|
|
||||||
|
|
||||||
return NULL;
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||||
|
ERR("IP_MULTICAST_TTL");
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
|
||||||
|
ERR("IP_MULTICAST_LOOP");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
static inline char *
|
|
||||||
sk_join_group4(sock *s, ip_addr maddr)
|
sk_join_group4(sock *s, ip_addr maddr)
|
||||||
{
|
{
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
|
||||||
|
|
||||||
bzero(&mreq, sizeof(mreq));
|
if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
|
||||||
ipa_put_in4(&mreq.imr_interface, s->iface->addr->ip);
|
ERR("IP_ADD_MEMBERSHIP");
|
||||||
ipa_put_in4(&mreq.imr_multiaddr, maddr);
|
|
||||||
|
|
||||||
/* And this one sets interface for _receiving_ multicasts from */
|
return 0;
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
|
||||||
return "IP_ADD_MEMBERSHIP";
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *
|
static inline int
|
||||||
sk_leave_group4(sock *s, ip_addr maddr)
|
sk_leave_group4(sock *s, ip_addr maddr)
|
||||||
{
|
{
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mr = INIT_MREQ4(maddr, s->iface);
|
||||||
|
|
||||||
bzero(&mreq, sizeof(mreq));
|
if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
|
||||||
ipa_put_in4(&mreq.imr_interface, s->iface->addr->ip);
|
ERR("IP_ADD_MEMBERSHIP");
|
||||||
ipa_put_in4(&mreq.imr_multiaddr, maddr);
|
|
||||||
|
|
||||||
/* And this one sets interface for _receiving_ multicasts from */
|
return 0;
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
|
||||||
return "IP_DROP_MEMBERSHIP";
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* BSD RX/TX packet info handling for IPv4 */
|
/*
|
||||||
/* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
|
* BSD IPv4 packet control messages
|
||||||
|
*/
|
||||||
|
|
||||||
#define CMSG_SPACE_PKTINFO4 (CMSG_SPACE(sizeof(struct in_addr)) + \
|
/* It uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
|
||||||
|
|
||||||
|
#define CMSG4_SPACE_PKTINFO (CMSG_SPACE(sizeof(struct in_addr)) + \
|
||||||
CMSG_SPACE(sizeof(struct sockaddr_dl)))
|
CMSG_SPACE(sizeof(struct sockaddr_dl)))
|
||||||
#define CMSG_SPACE_PKTINFO6 CMSG_SPACE(sizeof(struct in6_pktinfo))
|
#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(char))
|
||||||
|
|
||||||
#define CMSG_RX_SPACE (MAX(CMSG_SPACE_PKTINFO4,CMSG_SPACE_PKTINFO6) + CMSG_SPACE(sizeof(int)))
|
static inline int
|
||||||
#define CMSG_TX_SPACE MAX(CMSG_SPACE_PKTINFO4,CMSG_SPACE_PKTINFO6)
|
|
||||||
|
|
||||||
|
|
||||||
static inline char *
|
|
||||||
sk_request_cmsg4_pktinfo(sock *s)
|
sk_request_cmsg4_pktinfo(sock *s)
|
||||||
{
|
{
|
||||||
int ok = 1;
|
int y = 1;
|
||||||
|
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &y, sizeof(y)) < 0)
|
||||||
return "IP_RECVDSTADDR";
|
ERR("IP_RECVDSTADDR");
|
||||||
|
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &y, sizeof(y)) < 0)
|
||||||
return "IP_RECVIF";
|
ERR("IP_RECVIF");
|
||||||
|
|
||||||
return NULL;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_request_cmsg4_ttl(sock *s)
|
||||||
|
{
|
||||||
|
int y = 1;
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
|
||||||
|
ERR("IP_RECVTTL");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
|
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
|
||||||
{
|
{
|
||||||
if ((cm->cmsg_type == IP_RECVDSTADDR) && (s->flags & SKF_LADDR_RX))
|
if (cm->cmsg_type == IP_RECVDSTADDR)
|
||||||
s->laddr = ipa_get_in4((struct in_addr *) CMSG_DATA(cm));
|
s->laddr = ipa_from_in4(* (struct in_addr *) CMSG_DATA(cm));
|
||||||
|
|
||||||
if ((cm->cmsg_type == IP_RECVIF) && (s->flags & SKF_LADDR_RX))
|
if (cm->cmsg_type == IP_RECVIF)
|
||||||
s->lifindex = ((struct sockaddr_dl *) CMSG_DATA(cm))->sdl_index;
|
s->lifindex = ((struct sockaddr_dl *) CMSG_DATA(cm))->sdl_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *
|
|
||||||
sk_request_cmsg4_ttl(sock *s)
|
|
||||||
{
|
|
||||||
int ok = 1;
|
|
||||||
|
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0)
|
|
||||||
return "IP_RECVTTL";
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
||||||
{
|
{
|
||||||
if ((cm->cmsg_type == IP_RECVTTL) && (s->flags & SKF_TTL_RX))
|
if (cm->cmsg_type == IP_RECVTTL)
|
||||||
s->ttl = * (unsigned char *) CMSG_DATA(cm);
|
s->rcv_ttl = * (unsigned char *) CMSG_DATA(cm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||||
{
|
{
|
||||||
|
/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
|
||||||
|
|
||||||
#ifdef IP_SENDSRCADDR
|
#ifdef IP_SENDSRCADDR
|
||||||
struct cmsghdr *cm;
|
struct cmsghdr *cm;
|
||||||
struct in_addr *sa;
|
struct in_addr *sa;
|
||||||
@ -157,13 +151,12 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||||||
cm->cmsg_len = CMSG_LEN(sizeof(*sa));
|
cm->cmsg_len = CMSG_LEN(sizeof(*sa));
|
||||||
|
|
||||||
sa = (struct in_addr *) CMSG_DATA(cm);
|
sa = (struct in_addr *) CMSG_DATA(cm);
|
||||||
ipa_put_in4(&sa, s->saddr);
|
*sa = ipa_to_in4(s->saddr);
|
||||||
|
|
||||||
msg->msg_controllen = cm->cmsg_len;
|
msg->msg_controllen = cm->cmsg_len;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
||||||
{
|
{
|
||||||
@ -177,8 +170,8 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
|||||||
ip->ip_len = 20 + dlen;
|
ip->ip_len = 20 + dlen;
|
||||||
ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
|
ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
|
||||||
ip->ip_p = s->dport;
|
ip->ip_p = s->dport;
|
||||||
ipa_put_in4(&ip->ip_src, s->saddr);
|
ip->ip_src = ipa_to_in4(s->saddr);
|
||||||
ipa_put_in4(&ip->ip_dst, s->daddr);
|
ip->ip_dst = ipa_to_in4(s->daddr);
|
||||||
|
|
||||||
#ifdef __OpenBSD__
|
#ifdef __OpenBSD__
|
||||||
/* OpenBSD expects ip_len in network order, other BSDs expect host order */
|
/* OpenBSD expects ip_len in network order, other BSDs expect host order */
|
||||||
@ -187,7 +180,10 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#include <netinet/tcp.h>
|
/*
|
||||||
|
* Miscellaneous BSD socket syscalls
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef TCP_KEYLEN_MAX
|
#ifndef TCP_KEYLEN_MAX
|
||||||
#define TCP_KEYLEN_MAX 80
|
#define TCP_KEYLEN_MAX 80
|
||||||
#endif
|
#endif
|
||||||
@ -201,59 +197,69 @@ sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
|||||||
* management.
|
* management.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
int
|
||||||
sk_set_md5_auth_int(sock *s, struct sockaddr *sa, int sa_len, char *passwd)
|
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
|
||||||
{
|
{
|
||||||
int enable = 0;
|
int enable = 0;
|
||||||
if (passwd)
|
|
||||||
|
if (passwd && *passwd)
|
||||||
{
|
{
|
||||||
int len = strlen(passwd);
|
int len = strlen(passwd);
|
||||||
|
enable = TCP_SIG_SPI;
|
||||||
enable = len ? TCP_SIG_SPI : 0;
|
|
||||||
|
|
||||||
if (len > TCP_KEYLEN_MAX)
|
if (len > TCP_KEYLEN_MAX)
|
||||||
{
|
ERR_MSG("MD5 password too long");
|
||||||
log(L_ERR "MD5 password too long");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int rv = setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable));
|
if (setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &enable, sizeof(enable)) < 0)
|
||||||
|
|
||||||
if (rv < 0)
|
|
||||||
{
|
{
|
||||||
if (errno == ENOPROTOOPT)
|
if (errno == ENOPROTOOPT)
|
||||||
log(L_ERR "Kernel does not support TCP MD5 signatures");
|
ERR_MSG("Kernel does not support TCP MD5 signatures");
|
||||||
else
|
else
|
||||||
log(L_ERR "sk_set_md5_auth_int: setsockopt: %m");
|
ERR("TCP_MD5SIG");
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
static inline char *
|
|
||||||
sk_set_min_ttl4(sock *s, int ttl)
|
sk_set_min_ttl4(sock *s, int ttl)
|
||||||
{
|
{
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
||||||
return "IP_MINTTL";
|
{
|
||||||
|
if (errno == ENOPROTOOPT)
|
||||||
return NULL;
|
ERR_MSG("Kernel does not support IPv4 TTL security");
|
||||||
|
else
|
||||||
|
ERR("IP_MINTTL");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
sk_set_min_ttl6(sock *s, int ttl)
|
sk_set_min_ttl6(sock *s, int ttl)
|
||||||
{
|
{
|
||||||
errno = ENOPROTOOPT;
|
ERR_MSG("Kernel does not support IPv6 TTL security");
|
||||||
return "IP_MINTTL";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_disable_mtu_disc4(sock *s)
|
||||||
|
{
|
||||||
|
/* TODO: Set IP_DONTFRAG to 0 ? */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_disable_mtu_disc6(sock *s)
|
||||||
|
{
|
||||||
|
/* TODO: Set IPV6_DONTFRAG to 0 ? */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sk_priority_control = -1;
|
int sk_priority_control = -1;
|
||||||
|
|
||||||
static int
|
static inline int
|
||||||
sk_set_priority(sock *s, int prio UNUSED)
|
sk_set_priority(sock *s, int prio UNUSED)
|
||||||
{
|
{
|
||||||
log(L_WARN "Socket priority not supported");
|
ERR_MSG("Socket priority not supported");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ nl_open_sock(struct nl_sock *nl)
|
|||||||
{
|
{
|
||||||
if (nl->fd < 0)
|
if (nl->fd < 0)
|
||||||
{
|
{
|
||||||
nl->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
nl->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
if (nl->fd < 0)
|
if (nl->fd < 0)
|
||||||
die("Unable to open rtnetlink socket: %m");
|
die("Unable to open rtnetlink socket: %m");
|
||||||
nl->seq = now;
|
nl->seq = now;
|
||||||
@ -576,24 +576,24 @@ kif_do_scan(struct kif_proto *p UNUSED)
|
|||||||
|
|
||||||
if_start_update();
|
if_start_update();
|
||||||
|
|
||||||
/* Is it important which PF_* is used for link-level interface scan?
|
/* Is it important which AF_* is used for link-level interface scan?
|
||||||
It seems that some information is available only when PF_INET is used. */
|
It seems that some information is available only when AF_INET is used. */
|
||||||
|
|
||||||
nl_request_dump(PF_INET, RTM_GETLINK);
|
nl_request_dump(AF_INET, RTM_GETLINK);
|
||||||
while (h = nl_get_scan())
|
while (h = nl_get_scan())
|
||||||
if (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)
|
if (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)
|
||||||
nl_parse_link(h, 1);
|
nl_parse_link(h, 1);
|
||||||
else
|
else
|
||||||
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
|
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
|
||||||
|
|
||||||
nl_request_dump(PF_INET, RTM_GETADDR);
|
nl_request_dump(AF_INET, RTM_GETADDR);
|
||||||
while (h = nl_get_scan())
|
while (h = nl_get_scan())
|
||||||
if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||||
nl_parse_addr(h, 1);
|
nl_parse_addr(h, 1);
|
||||||
else
|
else
|
||||||
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
|
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
|
||||||
|
|
||||||
nl_request_dump(PF_INET6, RTM_GETADDR);
|
nl_request_dump(AF_INET6, RTM_GETADDR);
|
||||||
while (h = nl_get_scan())
|
while (h = nl_get_scan())
|
||||||
if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||||
nl_parse_addr(h, 1);
|
nl_parse_addr(h, 1);
|
||||||
@ -969,14 +969,14 @@ krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL
|
|||||||
{
|
{
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
|
|
||||||
nl_request_dump(PF_INET, RTM_GETROUTE);
|
nl_request_dump(AF_INET, RTM_GETROUTE);
|
||||||
while (h = nl_get_scan())
|
while (h = nl_get_scan())
|
||||||
if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
|
if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
|
||||||
nl_parse_route(h, 1);
|
nl_parse_route(h, 1);
|
||||||
else
|
else
|
||||||
log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
|
log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
|
||||||
|
|
||||||
nl_request_dump(PF_INET6, RTM_GETROUTE);
|
nl_request_dump(AF_INET6, RTM_GETROUTE);
|
||||||
while (h = nl_get_scan())
|
while (h = nl_get_scan())
|
||||||
if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
|
if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
|
||||||
nl_parse_route(h, 1);
|
nl_parse_route(h, 1);
|
||||||
@ -1076,7 +1076,7 @@ nl_open_async(void)
|
|||||||
|
|
||||||
DBG("KRT: Opening async netlink socket\n");
|
DBG("KRT: Opening async netlink socket\n");
|
||||||
|
|
||||||
fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
log(L_ERR "Unable to open asynchronous rtnetlink socket: %m");
|
log(L_ERR "Unable to open asynchronous rtnetlink socket: %m");
|
||||||
@ -1101,7 +1101,7 @@ nl_open_async(void)
|
|||||||
sk->type = SK_MAGIC;
|
sk->type = SK_MAGIC;
|
||||||
sk->rx_hook = nl_async_hook;
|
sk->rx_hook = nl_async_hook;
|
||||||
sk->fd = fd;
|
sk->fd = fd;
|
||||||
if (sk_open(sk))
|
if (sk_open(sk) < 0)
|
||||||
bug("Netlink: sk_open failed");
|
bug("Netlink: sk_open failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,15 +6,6 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef IPV6_UNICAST_HOPS
|
|
||||||
/* Needed on glibc 2.0 systems */
|
|
||||||
#include <linux/in6.h>
|
|
||||||
#define CONFIG_IPV6_GLIBC_20
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_STRUCT_IP_MREQN
|
#ifndef HAVE_STRUCT_IP_MREQN
|
||||||
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
|
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
|
||||||
@ -26,164 +17,138 @@ struct ip_mreqn
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef IP_MINTTL
|
||||||
|
#define IP_MINTTL 21
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline void fill_mreqn(struct ip_mreqn *m, ip_addr maddr, struct iface *ifa)
|
#ifndef IPV6_TCLASS
|
||||||
{
|
#define IPV6_TCLASS 67
|
||||||
bzero(m, sizeof(*m));
|
#endif
|
||||||
m->imr_ifindex = ifa->index;
|
|
||||||
ipa_put_in4(&m->imr_multiaddr, maddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline char *
|
#ifndef IPV6_MINHOPCOUNT
|
||||||
sk_setup_multicast4(sock *s)
|
#define IPV6_MINHOPCOUNT 73
|
||||||
{
|
#endif
|
||||||
struct ip_mreqn m;
|
|
||||||
int zero = 0;
|
|
||||||
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
|
||||||
return "IP_MULTICAST_LOOP";
|
|
||||||
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
|
||||||
return "IP_MULTICAST_TTL";
|
|
||||||
|
|
||||||
/* This defines where should we send _outgoing_ multicasts */
|
|
||||||
fill_mreqn(&m, IPA_NONE, s->iface);
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
|
||||||
return "IP_MULTICAST_IF";
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline char *
|
|
||||||
sk_join_group4(sock *s, ip_addr maddr)
|
|
||||||
{
|
|
||||||
struct ip_mreqn m;
|
|
||||||
|
|
||||||
fill_mreqn(&m, maddr, s->iface);
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
|
|
||||||
return "IP_ADD_MEMBERSHIP";
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline char *
|
|
||||||
sk_leave_group4(sock *s, ip_addr maddr)
|
|
||||||
{
|
|
||||||
struct ip_mreqn m;
|
|
||||||
|
|
||||||
fill_mreqn(&m, maddr, s->iface);
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
|
|
||||||
return "IP_DROP_MEMBERSHIP";
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* For the case that we have older libc headers */
|
|
||||||
/* Copied from Linux kernel file include/linux/tcp.h */
|
|
||||||
|
|
||||||
#ifndef TCP_MD5SIG
|
#ifndef TCP_MD5SIG
|
||||||
|
|
||||||
#define TCP_MD5SIG 14
|
#define TCP_MD5SIG 14
|
||||||
#define TCP_MD5SIG_MAXKEYLEN 80
|
#define TCP_MD5SIG_MAXKEYLEN 80
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
|
|
||||||
struct tcp_md5sig {
|
struct tcp_md5sig {
|
||||||
struct sockaddr_storage tcpm_addr; /* address associated */
|
struct sockaddr_storage tcpm_addr; /* address associated */
|
||||||
__u16 __tcpm_pad1; /* zero */
|
u16 __tcpm_pad1; /* zero */
|
||||||
__u16 tcpm_keylen; /* key length */
|
u16 tcpm_keylen; /* key length */
|
||||||
__u32 __tcpm_pad2; /* zero */
|
u32 __tcpm_pad2; /* zero */
|
||||||
__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
|
u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
|
||||||
sk_set_md5_auth_int(sock *s, struct sockaddr *sa, int sa_len, char *passwd)
|
|
||||||
{
|
|
||||||
struct tcp_md5sig md5;
|
|
||||||
|
|
||||||
memset(&md5, 0, sizeof(md5));
|
/* Linux does not care if sa_len is larger than needed */
|
||||||
memcpy(&md5.tcpm_addr, sa, sa_len);
|
#define SA_LEN(x) sizeof(sockaddr)
|
||||||
|
|
||||||
if (passwd)
|
|
||||||
{
|
|
||||||
int len = strlen(passwd);
|
|
||||||
|
|
||||||
if (len > TCP_MD5SIG_MAXKEYLEN)
|
/*
|
||||||
|
* Linux IPv4 multicast syscalls
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INIT_MREQ4(maddr,ifa) \
|
||||||
|
{ .imr_multiaddr = ipa_to_in4(maddr), .imr_ifindex = ifa->index }
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_setup_multicast4(sock *s)
|
||||||
{
|
{
|
||||||
log(L_ERR "MD5 password too long");
|
struct ip_mreqn mr = { .imr_ifindex = s->iface->index };
|
||||||
return -1;
|
int ttl = s->ttl;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
/* This defines where should we send _outgoing_ multicasts */
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mr, sizeof(mr)) < 0)
|
||||||
|
ERR("IP_MULTICAST_IF");
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||||
|
ERR("IP_MULTICAST_TTL");
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &n, sizeof(n)) < 0)
|
||||||
|
ERR("IP_MULTICAST_LOOP");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
md5.tcpm_keylen = len;
|
static inline int
|
||||||
memcpy(&md5.tcpm_key, passwd, len);
|
sk_join_group4(sock *s, ip_addr maddr)
|
||||||
}
|
|
||||||
|
|
||||||
int rv = setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5));
|
|
||||||
|
|
||||||
if (rv < 0)
|
|
||||||
{
|
{
|
||||||
if (errno == ENOPROTOOPT)
|
struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
|
||||||
log(L_ERR "Kernel does not support TCP MD5 signatures");
|
|
||||||
else
|
if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr)) < 0)
|
||||||
log(L_ERR "sk_set_md5_auth_int: TCP_MD5SIG: %m");
|
ERR("IP_ADD_MEMBERSHIP");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
static inline int
|
||||||
|
sk_leave_group4(sock *s, ip_addr maddr)
|
||||||
|
{
|
||||||
|
struct ip_mreqn mr = INIT_MREQ4(maddr, s->iface);
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr)) < 0)
|
||||||
|
ERR("IP_DROP_MEMBERSHIP");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* RX/TX packet info handling for IPv4 */
|
/*
|
||||||
|
* Linux IPv4 packet control messages
|
||||||
|
*/
|
||||||
|
|
||||||
/* Mostly similar to standardized IPv6 code */
|
/* Mostly similar to standardized IPv6 code */
|
||||||
|
|
||||||
#define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo))
|
#define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo))
|
||||||
|
#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(int))
|
||||||
|
|
||||||
static inline char *
|
static inline int
|
||||||
sk_request_cmsg4_pktinfo(sock *s)
|
sk_request_cmsg4_pktinfo(sock *s)
|
||||||
{
|
{
|
||||||
int ok = 1;
|
int y = 1;
|
||||||
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0)
|
if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &y, sizeof(y)) < 0)
|
||||||
return "IP_PKTINFO";
|
ERR("IP_PKTINFO");
|
||||||
|
|
||||||
return NULL;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_request_cmsg4_ttl(sock *s)
|
||||||
|
{
|
||||||
|
int y = 1;
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &y, sizeof(y)) < 0)
|
||||||
|
ERR("IP_RECVTTL");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
|
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
|
||||||
{
|
{
|
||||||
if ((cm->cmsg_type == IP_PKTINFO) && (s->flags & SKF_LADDR_RX))
|
if (cm->cmsg_type == IP_PKTINFO)
|
||||||
{
|
{
|
||||||
struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||||
s->laddr = ipa_get_in4(&pi->ipi_addr);
|
s->laddr = ipa_from_in4(pi->ipi_addr);
|
||||||
s->lifindex = pi->ipi_ifindex;
|
s->lifindex = pi->ipi_ifindex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define CMSG4_SPACE_TTL CMSG_SPACE(sizeof(int))
|
|
||||||
|
|
||||||
static inline char *
|
|
||||||
sk_request_cmsg4_ttl(sock *s)
|
|
||||||
{
|
|
||||||
int ok = 1;
|
|
||||||
|
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0)
|
|
||||||
return "IP_RECVTTL";
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
||||||
{
|
{
|
||||||
if ((cm->cmsg_type == IP_TTL) && (s->flags & SKF_TTL_RX))
|
if (cm->cmsg_type == IP_TTL)
|
||||||
s->ttl = * (int *) CMSG_DATA(cm);
|
s->rcv_ttl = * (int *) CMSG_DATA(cm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||||
{
|
{
|
||||||
@ -200,56 +165,105 @@ sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||||||
|
|
||||||
pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||||
pi->ipi_ifindex = s->iface ? s->iface->index : 0;
|
pi->ipi_ifindex = s->iface ? s->iface->index : 0;
|
||||||
ipa_put_in4(&pi->ipi_spec_dst, s->saddr);
|
pi->ipi_spec_dst = ipa_to_in4(s->saddr);
|
||||||
ipa_put_in4(&pi->ipi_addr, IPA_NONE);
|
pi->ipi_addr = ipa_to_in4(IPA_NONE);
|
||||||
|
|
||||||
msg->msg_controllen = cm->cmsg_len;
|
msg->msg_controllen = cm->cmsg_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Miscellaneous Linux socket syscalls
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef IP_MINTTL
|
int
|
||||||
#define IP_MINTTL 21
|
sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef IPV6_MINHOPCOUNT
|
|
||||||
#define IPV6_MINHOPCOUNT 73
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline char *
|
|
||||||
sk_set_min_ttl4(sock *s, int ttl)
|
|
||||||
{
|
{
|
||||||
if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
struct tcp_md5sig md5;
|
||||||
return "IP_MINTTL";
|
|
||||||
|
|
||||||
return NULL;
|
memset(&md5, 0, sizeof(md5));
|
||||||
|
sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, a, ifa, 0);
|
||||||
|
|
||||||
|
if (passwd)
|
||||||
|
{
|
||||||
|
int len = strlen(passwd);
|
||||||
|
|
||||||
|
if (len > TCP_MD5SIG_MAXKEYLEN)
|
||||||
|
ERR_MSG("MD5 password too long");
|
||||||
|
|
||||||
|
md5.tcpm_keylen = len;
|
||||||
|
memcpy(&md5.tcpm_key, passwd, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline char *
|
if (setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5)) < 0)
|
||||||
sk_set_min_ttl6(sock *s, int ttl)
|
|
||||||
{
|
{
|
||||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
|
if (errno == ENOPROTOOPT)
|
||||||
return "IPV6_MINHOPCOUNT";
|
ERR_MSG("Kernel does not support TCP MD5 signatures");
|
||||||
|
else
|
||||||
return NULL;
|
ERR("TCP_MD5SIG");
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef IPV6_TCLASS
|
|
||||||
#define IPV6_TCLASS 67
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int sk_priority_control = 7;
|
|
||||||
|
|
||||||
static int
|
|
||||||
sk_set_priority(sock *s, int prio)
|
|
||||||
{
|
|
||||||
if (setsockopt(s->fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0)
|
|
||||||
{
|
|
||||||
log(L_WARN "sk_set_priority: setsockopt: %m");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_set_min_ttl4(sock *s, int ttl)
|
||||||
|
{
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
||||||
|
{
|
||||||
|
if (errno == ENOPROTOOPT)
|
||||||
|
ERR_MSG("Kernel does not support IPv4 TTL security");
|
||||||
|
else
|
||||||
|
ERR("IP_MINTTL");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_set_min_ttl6(sock *s, int ttl)
|
||||||
|
{
|
||||||
|
if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
|
||||||
|
{
|
||||||
|
if (errno == ENOPROTOOPT)
|
||||||
|
ERR_MSG("Kernel does not support IPv6 TTL security");
|
||||||
|
else
|
||||||
|
ERR("IPV6_MINHOPCOUNT");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_disable_mtu_disc4(sock *s)
|
||||||
|
{
|
||||||
|
int dont = IP_PMTUDISC_DONT;
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, SOL_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
|
||||||
|
ERR("IP_MTU_DISCOVER");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_disable_mtu_disc6(sock *s)
|
||||||
|
{
|
||||||
|
int dont = IPV6_PMTUDISC_DONT;
|
||||||
|
|
||||||
|
if (setsockopt(s->fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
|
||||||
|
ERR("IPV6_MTU_DISCOVER");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sk_priority_control = 7;
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
sk_set_priority(sock *s, int prio)
|
||||||
|
{
|
||||||
|
if (setsockopt(s->fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)) < 0)
|
||||||
|
ERR("SO_PRIORITY");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
1557
sysdep/unix/io.c
1557
sysdep/unix/io.c
File diff suppressed because it is too large
Load Diff
@ -463,7 +463,12 @@ cli_init_unix(uid_t use_uid, gid_t use_gid)
|
|||||||
s->type = SK_UNIX_PASSIVE;
|
s->type = SK_UNIX_PASSIVE;
|
||||||
s->rx_hook = cli_connect;
|
s->rx_hook = cli_connect;
|
||||||
s->rbsize = 1024;
|
s->rbsize = 1024;
|
||||||
sk_open_unix(s, path_control_socket);
|
|
||||||
|
/* Return value intentionally ignored */
|
||||||
|
unlink(path_control_socket);
|
||||||
|
|
||||||
|
if (sk_open_unix(s, path_control_socket) < 0)
|
||||||
|
die("Cannot create control socket %s: %m", path_control_socket);
|
||||||
|
|
||||||
if (use_uid || use_gid)
|
if (use_uid || use_gid)
|
||||||
if (chown(path_control_socket, use_uid, use_gid) < 0)
|
if (chown(path_control_socket, use_uid, use_gid) < 0)
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
struct pool;
|
struct pool;
|
||||||
|
struct iface;
|
||||||
|
struct birdsock;
|
||||||
|
|
||||||
/* main.c */
|
/* main.c */
|
||||||
|
|
||||||
@ -27,29 +29,62 @@ void cmd_shutdown(void);
|
|||||||
|
|
||||||
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
|
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
|
||||||
|
|
||||||
|
|
||||||
/* io.c */
|
/* io.c */
|
||||||
|
|
||||||
volatile int async_config_flag;
|
#define ERR(c) do { s->err = c; return -1; } while (0)
|
||||||
volatile int async_dump_flag;
|
#define ERR2(c) do { s->err = c; goto err; } while (0)
|
||||||
volatile int async_shutdown_flag;
|
#define ERR_MSG(c) do { errno = 0; s->err = c; return -1; } while (0)
|
||||||
|
|
||||||
struct sockaddr;
|
|
||||||
struct iface;
|
|
||||||
|
|
||||||
void sockaddr_fill(struct sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port);
|
#define SOCKADDR_SIZE 32
|
||||||
void sockaddr_read(struct sockaddr *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check);
|
|
||||||
|
typedef struct sockaddr_bird {
|
||||||
|
struct sockaddr sa;
|
||||||
|
char padding[SOCKADDR_SIZE - sizeof(struct sockaddr)];
|
||||||
|
} sockaddr;
|
||||||
|
|
||||||
|
|
||||||
|
/* This is sloppy hack, it should be detected by configure script */
|
||||||
|
/* Linux systems have it defined so this is definition for BSD systems */
|
||||||
|
#ifndef s6_addr32
|
||||||
|
#define s6_addr32 __u6_addr.__u6_addr32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static inline ip_addr ipa_from_in4(struct in_addr a)
|
||||||
|
{ return ipa_from_u32(ntohl(a.s_addr)); }
|
||||||
|
|
||||||
|
static inline ip_addr ipa_from_in6(struct in6_addr a)
|
||||||
|
{ return _MI6(ntohl(a.s6_addr32[0]), ntohl(a.s6_addr32[1]), ntohl(a.s6_addr32[2]), ntohl(a.s6_addr32[3])); }
|
||||||
|
|
||||||
|
static inline ip_addr ipa_from_sa4(sockaddr *sa)
|
||||||
|
{ return ipa_from_in4(((struct sockaddr_in *) sa)->sin_addr); }
|
||||||
|
|
||||||
|
static inline ip_addr ipa_from_sa6(sockaddr *sa)
|
||||||
|
{ return ipa_from_in6(((struct sockaddr_in6 *) sa)->sin6_addr); }
|
||||||
|
|
||||||
|
static inline struct in_addr ipa_to_in4(ip_addr a)
|
||||||
|
{ return (struct in_addr) { htonl(ipa_to_u32(a)) }; }
|
||||||
|
|
||||||
|
static inline struct in6_addr ipa_to_in6(ip_addr a)
|
||||||
|
{ return (struct in6_addr) { .s6_addr32 = { htonl(_I0(a)), htonl(_I1(a)), htonl(_I2(a)), htonl(_I3(a)) } }; }
|
||||||
|
|
||||||
|
void sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port);
|
||||||
|
int sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port);
|
||||||
|
|
||||||
|
|
||||||
#ifndef SUN_LEN
|
#ifndef SUN_LEN
|
||||||
#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))
|
#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct birdsock;
|
volatile int async_config_flag;
|
||||||
struct iface;
|
volatile int async_dump_flag;
|
||||||
|
volatile int async_shutdown_flag;
|
||||||
|
|
||||||
void io_init(void);
|
void io_init(void);
|
||||||
void io_loop(void);
|
void io_loop(void);
|
||||||
void 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);
|
||||||
void test_old_bird(char *path);
|
void test_old_bird(char *path);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user