mirror of
https://gitlab.labs.nic.cz/labs/bird.git
synced 2024-05-11 16:54:54 +00:00
Implements TTL security for OSPF and RIP.
Interfaces for OSPF and RIP could be configured to use (and request) TTL 255 for traffic to direct neighbors. Thanks to Simon Dickhoven for the original patch for RIPng.
This commit is contained in:
@@ -113,7 +113,9 @@ sysio_leave_group(sock *s, ip_addr maddr)
|
||||
/* BSD RX/TX packet info handling for IPv4 */
|
||||
/* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
|
||||
|
||||
#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + CMSG_SPACE(sizeof(struct sockaddr_dl)))
|
||||
#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_addr)) + \
|
||||
CMSG_SPACE(sizeof(struct sockaddr_dl)) + \
|
||||
CMSG_SPACE(sizeof(char)))
|
||||
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
|
||||
|
||||
static char *
|
||||
@@ -121,13 +123,18 @@ sysio_register_cmsgs(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
{
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
|
||||
return "IP_RECVDSTADDR";
|
||||
{
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
|
||||
return "IP_RECVDSTADDR";
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0)
|
||||
return "IP_RECVIF";
|
||||
}
|
||||
|
||||
if ((s->flags & SKF_TTL_RX) &&
|
||||
(setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0))
|
||||
return "IP_RECVTTL";
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVIF, &ok, sizeof(ok)) < 0)
|
||||
return "IP_RECVIF";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -136,27 +143,35 @@ static void
|
||||
sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
|
||||
if (!(s->flags & SKF_LADDR_RX))
|
||||
return;
|
||||
|
||||
s->laddr = IPA_NONE;
|
||||
s->lifindex = 0;
|
||||
struct in_addr *ra = NULL;
|
||||
struct sockaddr_dl *ri = NULL;
|
||||
unsigned char *ttl = NULL;
|
||||
|
||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
|
||||
{
|
||||
struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm);
|
||||
get_inaddr(&s->laddr, ra);
|
||||
}
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
|
||||
ra = (struct in_addr *) CMSG_DATA(cm);
|
||||
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
|
||||
{
|
||||
struct sockaddr_dl *ri = (struct sockaddr_dl *) CMSG_DATA(cm);
|
||||
s->lifindex = ri->sdl_index;
|
||||
}
|
||||
}
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
|
||||
ri = (struct sockaddr_dl *) CMSG_DATA(cm);
|
||||
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVTTL)
|
||||
ttl = (unsigned char *) CMSG_DATA(cm);
|
||||
}
|
||||
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
{
|
||||
s->laddr = IPA_NONE;
|
||||
s->lifindex = 0;
|
||||
|
||||
if (ra)
|
||||
get_inaddr(&s->laddr, ra);
|
||||
if (ri)
|
||||
s->lifindex = ri->sdl_index;
|
||||
}
|
||||
|
||||
if (s->flags & SKF_TTL_RX)
|
||||
s->ttl = ttl ? *ttl : -1;
|
||||
|
||||
// log(L_WARN "RX %I %d", s->laddr, s->lifindex);
|
||||
}
|
||||
|
||||
@@ -194,17 +194,22 @@ sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
|
||||
/* RX/TX packet info handling for IPv4 */
|
||||
/* Mostly similar to standardized IPv6 code */
|
||||
|
||||
#define CMSG_RX_SPACE CMSG_SPACE(sizeof(struct in_pktinfo))
|
||||
#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in_pktinfo)) + CMSG_SPACE(sizeof(int)))
|
||||
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_pktinfo))
|
||||
|
||||
static char *
|
||||
sysio_register_cmsgs(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if ((s->flags & SKF_LADDR_RX) &&
|
||||
setsockopt(s->fd, IPPROTO_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0)
|
||||
(setsockopt(s->fd, IPPROTO_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0))
|
||||
return "IP_PKTINFO";
|
||||
|
||||
if ((s->flags & SKF_TTL_RX) &&
|
||||
(setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0))
|
||||
return "IP_RECVTTL";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -213,25 +218,34 @@ sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
struct in_pktinfo *pi = NULL;
|
||||
|
||||
if (!(s->flags & SKF_LADDR_RX))
|
||||
return;
|
||||
int *ttl = NULL;
|
||||
|
||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO)
|
||||
pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||
}
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO)
|
||||
pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||
|
||||
if (!pi)
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_TTL)
|
||||
ttl = (int *) CMSG_DATA(cm);
|
||||
}
|
||||
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
{
|
||||
if (pi)
|
||||
{
|
||||
get_inaddr(&s->laddr, &pi->ipi_addr);
|
||||
s->lifindex = pi->ipi_ifindex;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->laddr = IPA_NONE;
|
||||
s->lifindex = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->flags & SKF_TTL_RX)
|
||||
s->ttl = ttl ? *ttl : -1;
|
||||
|
||||
get_inaddr(&s->laddr, &pi->ipi_addr);
|
||||
s->lifindex = pi->ipi_ifindex;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -673,7 +673,7 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *p
|
||||
#ifdef IPV6
|
||||
|
||||
/* PKTINFO handling is also standardized in IPv6 */
|
||||
#define CMSG_RX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
|
||||
#define CMSG_RX_SPACE (CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int)))
|
||||
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
|
||||
|
||||
/*
|
||||
@@ -685,15 +685,26 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *p
|
||||
#ifndef IPV6_RECVPKTINFO
|
||||
#define IPV6_RECVPKTINFO IPV6_PKTINFO
|
||||
#endif
|
||||
/*
|
||||
* Same goes for IPV6_HOPLIMIT -> IPV6_RECVHOPLIMIT.
|
||||
*/
|
||||
#ifndef IPV6_RECVHOPLIMIT
|
||||
#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
|
||||
#endif
|
||||
|
||||
static char *
|
||||
sysio_register_cmsgs(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if ((s->flags & SKF_LADDR_RX) &&
|
||||
setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0)
|
||||
(setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0))
|
||||
return "IPV6_RECVPKTINFO";
|
||||
|
||||
if ((s->flags & SKF_TTL_RX) &&
|
||||
(setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0))
|
||||
return "IPV6_RECVHOPLIMIT";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -702,25 +713,34 @@ sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo *pi = NULL;
|
||||
|
||||
if (!(s->flags & SKF_LADDR_RX))
|
||||
return;
|
||||
int *hlim = NULL;
|
||||
|
||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
|
||||
pi = (struct in6_pktinfo *) CMSG_DATA(cm);
|
||||
}
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
|
||||
pi = (struct in6_pktinfo *) CMSG_DATA(cm);
|
||||
|
||||
if (!pi)
|
||||
if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_HOPLIMIT)
|
||||
hlim = (int *) CMSG_DATA(cm);
|
||||
}
|
||||
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
{
|
||||
if (pi)
|
||||
{
|
||||
get_inaddr(&s->laddr, &pi->ipi6_addr);
|
||||
s->lifindex = pi->ipi6_ifindex;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->laddr = IPA_NONE;
|
||||
s->lifindex = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->flags & SKF_TTL_RX)
|
||||
s->ttl = hlim ? *hlim : -1;
|
||||
|
||||
get_inaddr(&s->laddr, &pi->ipi6_addr);
|
||||
s->lifindex = pi->ipi6_ifindex;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user