0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 09:41:54 +00:00

Better support for link-local addresses in IO code.

This commit is contained in:
Ondrej Zajicek 2012-01-08 15:27:04 +01:00
parent a03ede6493
commit eb1451a3a0
3 changed files with 29 additions and 35 deletions

View File

@ -58,7 +58,7 @@ 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_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
/* Add or remove security associations for given passive socket */ /* Add or remove security associations for given passive socket */
int sk_set_md5_auth(sock *s, ip_addr a, char *passwd); int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
int sk_rx_ready(sock *s); int sk_rx_ready(sock *s);
/* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */ /* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */

View File

@ -609,10 +609,10 @@ sk_insert(sock *s)
#ifdef IPV6 #ifdef IPV6
void static void
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port) fill_in_sockaddr(sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port)
{ {
memset (sa, 0, sizeof (struct sockaddr_in6)); 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;
@ -620,16 +620,13 @@ fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
sa->sin6_len = sizeof(struct sockaddr_in6); sa->sin6_len = sizeof(struct sockaddr_in6);
#endif #endif
set_inaddr(&sa->sin6_addr, a); set_inaddr(&sa->sin6_addr, a);
if (ifa && ipa_has_link_scope(a))
sa->sin6_scope_id = ifa->index;
} }
static inline void static void
fill_in_sockifa(sockaddr *sa, struct iface *ifa) get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
{
sa->sin6_scope_id = ifa ? ifa->index : 0;
}
void
get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, unsigned *port, int check)
{ {
if (check && sa->sin6_family != AF_INET6) if (check && sa->sin6_family != AF_INET6)
bug("get_sockaddr called for wrong address family (%d)", sa->sin6_family); bug("get_sockaddr called for wrong address family (%d)", sa->sin6_family);
@ -637,12 +634,15 @@ get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, unsigned *port, int check)
*port = ntohs(sa->sin6_port); *port = ntohs(sa->sin6_port);
memcpy(a, &sa->sin6_addr, sizeof(*a)); memcpy(a, &sa->sin6_addr, sizeof(*a));
ipa_ntoh(*a); ipa_ntoh(*a);
if (ifa && ipa_has_link_scope(*a))
*ifa = if_find_by_index(sa->sin6_scope_id);
} }
#else #else
void static void
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port) fill_in_sockaddr(sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port)
{ {
memset (sa, 0, sizeof (struct sockaddr_in)); memset (sa, 0, sizeof (struct sockaddr_in));
sa->sin_family = AF_INET; sa->sin_family = AF_INET;
@ -653,13 +653,8 @@ fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
set_inaddr(&sa->sin_addr, a); set_inaddr(&sa->sin_addr, a);
} }
static inline void static void
fill_in_sockifa(sockaddr *sa UNUSED, struct iface *ifa UNUSED) get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check)
{
}
void
get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
{ {
if (check && sa->sin_family != AF_INET) if (check && sa->sin_family != AF_INET)
bug("get_sockaddr called for wrong address family (%d)", sa->sin_family); bug("get_sockaddr called for wrong address family (%d)", sa->sin_family);
@ -855,6 +850,7 @@ sk_set_min_ttl(sock *s, int ttl)
* sk_set_md5_auth - add / remove MD5 security association for given socket. * sk_set_md5_auth - add / remove MD5 security association for given socket.
* @s: socket * @s: socket
* @a: IP address of the other side * @a: IP address of the other side
* @ifa: Interface for link-local IP address
* @passwd: password used for MD5 authentication * @passwd: password used for MD5 authentication
* *
* In TCP MD5 handling code in kernel, there is a set of pairs * In TCP MD5 handling code in kernel, there is a set of pairs
@ -870,10 +866,10 @@ sk_set_min_ttl(sock *s, int ttl)
*/ */
int int
sk_set_md5_auth(sock *s, ip_addr a, char *passwd) sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd)
{ {
sockaddr sa; sockaddr sa;
fill_in_sockaddr(&sa, a, 0); fill_in_sockaddr(&sa, a, ifa, 0);
return sk_set_md5_auth_int(s, &sa, passwd); return sk_set_md5_auth_int(s, &sa, passwd);
} }
@ -1049,7 +1045,7 @@ sk_tcp_connected(sock *s)
sockaddr lsa; sockaddr lsa;
int lsa_len = sizeof(lsa); int lsa_len = sizeof(lsa);
if (getsockname(s->fd, (struct sockaddr *) &lsa, &lsa_len) == 0) if (getsockname(s->fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
get_sockaddr(&lsa, &s->saddr, &s->sport, 1); get_sockaddr(&lsa, &s->saddr, &s->iface, &s->sport, 1);
s->type = SK_TCP; s->type = SK_TCP;
sk_alloc_bufs(s); sk_alloc_bufs(s);
@ -1075,9 +1071,9 @@ sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
sockaddr lsa; sockaddr lsa;
int lsa_len = sizeof(lsa); int lsa_len = sizeof(lsa);
if (getsockname(fd, (struct sockaddr *) &lsa, &lsa_len) == 0) if (getsockname(fd, (struct sockaddr *) &lsa, &lsa_len) == 0)
get_sockaddr(&lsa, &t->saddr, &t->sport, 1); get_sockaddr(&lsa, &t->saddr, &t->iface, &t->sport, 1);
get_sockaddr((sockaddr *) sa, &t->daddr, &t->dport, 1); get_sockaddr((sockaddr *) sa, &t->daddr, &t->iface, &t->dport, 1);
} }
sk_insert(t); sk_insert(t);
if (err = sk_setup(t)) if (err = sk_setup(t))
@ -1156,12 +1152,11 @@ sk_open(sock *s)
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
ERR("SO_REUSEADDR"); ERR("SO_REUSEADDR");
} }
fill_in_sockaddr(&sa, s->saddr, port); fill_in_sockaddr(&sa, s->saddr, s->iface, port);
fill_in_sockifa(&sa, s->iface);
if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
ERR("bind"); ERR("bind");
} }
fill_in_sockaddr(&sa, s->daddr, s->dport); fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
if (s->password) if (s->password)
{ {
@ -1284,8 +1279,7 @@ sk_maybe_write(sock *s)
return 1; return 1;
sockaddr sa; sockaddr sa;
fill_in_sockaddr(&sa, s->daddr, s->dport); fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
fill_in_sockifa(&sa, s->iface);
struct iovec iov = {s->tbuf, s->tpos - s->tbuf}; struct iovec iov = {s->tbuf, s->tpos - s->tbuf};
// byte cmsg_buf[CMSG_TX_SPACE]; // byte cmsg_buf[CMSG_TX_SPACE];
@ -1463,7 +1457,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, 1); get_sockaddr(&sa, &s->faddr, NULL, &s->fport, 1);
sysio_process_rx_cmsgs(s, &msg); sysio_process_rx_cmsgs(s, &msg);
s->rx_hook(s, e); s->rx_hook(s, e);
@ -1480,7 +1474,7 @@ sk_write(sock *s)
case SK_TCP_ACTIVE: case SK_TCP_ACTIVE:
{ {
sockaddr sa; sockaddr sa;
fill_in_sockaddr(&sa, s->daddr, s->dport); fill_in_sockaddr(&sa, s->daddr, s->iface, s->dport);
if (connect(s->fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0 || errno == EISCONN) if (connect(s->fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0 || errno == EISCONN)
sk_tcp_connected(s); sk_tcp_connected(s);
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS) else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)

View File

@ -48,8 +48,8 @@ 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, struct iface *ifa, unsigned port);
void get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port, int check); // void get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check);
void sk_open_unix(struct birdsock *s, char *name); void 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);