mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-17 08:38:42 +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:
parent
ef4a50be10
commit
70e212f913
@ -89,6 +89,7 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul
|
|||||||
#define SKF_V6ONLY 1 /* Use IPV6_V6ONLY socket option */
|
#define SKF_V6ONLY 1 /* Use IPV6_V6ONLY socket option */
|
||||||
#define SKF_LADDR_RX 2 /* Report local address for RX packets */
|
#define SKF_LADDR_RX 2 /* Report local address for RX packets */
|
||||||
#define SKF_LADDR_TX 4 /* Allow to specify local address for TX packets */
|
#define SKF_LADDR_TX 4 /* Allow to specify local address for TX packets */
|
||||||
|
#define SKF_TTL_RX 8 /* Report TTL / Hop Limit for RX packets */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -127,8 +127,8 @@ CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF_ROUTER_ID)
|
|||||||
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, COST2, RETRANSMIT)
|
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, COST2, RETRANSMIT)
|
||||||
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
|
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
|
||||||
CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
|
CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
|
||||||
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
|
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC, TTL, SECURITY)
|
||||||
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
|
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK, ONLY)
|
||||||
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
|
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
|
||||||
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
|
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
|
||||||
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY)
|
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY)
|
||||||
@ -307,6 +307,8 @@ ospf_iface_item:
|
|||||||
| RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if (($3 < OSPF_RXBUF_MINSIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
|
| RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if (($3 < OSPF_RXBUF_MINSIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
|
||||||
| TX tos { OSPF_PATT->tx_tos = $2; }
|
| TX tos { OSPF_PATT->tx_tos = $2; }
|
||||||
| TX PRIORITY expr { OSPF_PATT->tx_priority = $3; }
|
| TX PRIORITY expr { OSPF_PATT->tx_priority = $3; }
|
||||||
|
| TTL SECURITY bool { OSPF_PATT->ttl_security = $3; }
|
||||||
|
| TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; }
|
||||||
| password_list
|
| password_list
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ ospf_sk_open(struct ospf_iface *ifa)
|
|||||||
sk->rbsize = rxbufsize(ifa);
|
sk->rbsize = rxbufsize(ifa);
|
||||||
sk->tbsize = rxbufsize(ifa);
|
sk->tbsize = rxbufsize(ifa);
|
||||||
sk->data = (void *) ifa;
|
sk->data = (void *) ifa;
|
||||||
sk->flags = SKF_LADDR_RX;
|
sk->flags = SKF_LADDR_RX | (ifa->check_ttl ? SKF_TTL_RX : 0);
|
||||||
|
|
||||||
if (sk_open(sk) != 0)
|
if (sk_open(sk) != 0)
|
||||||
goto err;
|
goto err;
|
||||||
@ -131,7 +131,7 @@ ospf_sk_open(struct ospf_iface *ifa)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ifa->all_routers = AllSPFRouters;
|
ifa->all_routers = AllSPFRouters;
|
||||||
sk->ttl = 1; /* Hack, this will affect just multicast packets */
|
sk->ttl = ifa->cf->ttl_security ? 255 : 1;
|
||||||
|
|
||||||
if (sk_setup_multicast(sk) < 0)
|
if (sk_setup_multicast(sk) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@ -534,6 +534,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
|||||||
ifa->rxbuf = ip->rxbuf;
|
ifa->rxbuf = ip->rxbuf;
|
||||||
ifa->check_link = ip->check_link;
|
ifa->check_link = ip->check_link;
|
||||||
ifa->ecmp_weight = ip->ecmp_weight;
|
ifa->ecmp_weight = ip->ecmp_weight;
|
||||||
|
ifa->check_ttl = (ip->ttl_security == 1);
|
||||||
|
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
ifa->autype = ip->autype;
|
ifa->autype = ip->autype;
|
||||||
|
@ -275,6 +275,7 @@ struct ospf_iface
|
|||||||
u8 check_link; /* Whether iface link change is used */
|
u8 check_link; /* Whether iface link change is used */
|
||||||
u8 ecmp_weight; /* Weight used for ECMP */
|
u8 ecmp_weight; /* Weight used for ECMP */
|
||||||
u8 ptp_netmask; /* Send real netmask for P2P */
|
u8 ptp_netmask; /* Send real netmask for P2P */
|
||||||
|
u8 check_ttl; /* Check incoming packets for TTL 255 */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ospf_md5
|
struct ospf_md5
|
||||||
@ -815,7 +816,8 @@ struct ospf_iface_patt
|
|||||||
u8 check_link;
|
u8 check_link;
|
||||||
u8 ecmp_weight;
|
u8 ecmp_weight;
|
||||||
u8 real_bcast; /* Not really used in OSPFv3 */
|
u8 real_bcast; /* Not really used in OSPFv3 */
|
||||||
u8 ptp_netmask; /* bool but 2 for unspecified */
|
u8 ptp_netmask; /* bool + 2 for unspecified */
|
||||||
|
u8 ttl_security; /* bool + 2 for TX only */
|
||||||
|
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
list *passwords;
|
list *passwords;
|
||||||
|
@ -309,6 +309,12 @@ ospf_rx_hook(sock *sk, int size)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ifa->check_ttl && (sk->ttl < 255))
|
||||||
|
{
|
||||||
|
log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->ttl);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((unsigned) size < sizeof(struct ospf_packet))
|
if ((unsigned) size < sizeof(struct ospf_packet))
|
||||||
{
|
{
|
||||||
log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
|
log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
|
||||||
|
@ -22,12 +22,18 @@ CF_DEFINES
|
|||||||
#define RIP_CFG ((struct rip_proto_config *) this_proto)
|
#define RIP_CFG ((struct rip_proto_config *) this_proto)
|
||||||
#define RIP_IPATT ((struct rip_patt *) this_ipatt)
|
#define RIP_IPATT ((struct rip_patt *) this_ipatt)
|
||||||
|
|
||||||
|
#ifdef IPV6
|
||||||
|
#define RIP_DEFAULT_TTL_SECURITY 2
|
||||||
|
#else
|
||||||
|
#define RIP_DEFAULT_TTL_SECURITY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT,
|
CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT,
|
||||||
MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1,
|
MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1,
|
||||||
AUTHENTICATION, NONE, PLAINTEXT, MD5,
|
AUTHENTICATION, NONE, PLAINTEXT, MD5, TTL, SECURITY,
|
||||||
HONOR, NEVER, NEIGHBOR, ALWAYS, TX, PRIORITY,
|
HONOR, NEVER, NEIGHBOR, ALWAYS, TX, PRIORITY, ONLY,
|
||||||
RIP_METRIC, RIP_TAG)
|
RIP_METRIC, RIP_TAG)
|
||||||
|
|
||||||
%type <i> rip_mode rip_auth
|
%type <i> rip_mode rip_auth
|
||||||
@ -78,6 +84,8 @@ rip_iface_item:
|
|||||||
| MODE rip_mode { RIP_IPATT->mode |= $2; }
|
| MODE rip_mode { RIP_IPATT->mode |= $2; }
|
||||||
| TX tos { RIP_IPATT->tx_tos = $2; }
|
| TX tos { RIP_IPATT->tx_tos = $2; }
|
||||||
| TX PRIORITY expr { RIP_IPATT->tx_priority = $3; }
|
| TX PRIORITY expr { RIP_IPATT->tx_priority = $3; }
|
||||||
|
| TTL SECURITY bool { RIP_IPATT->ttl_security = $3; }
|
||||||
|
| TTL SECURITY TX ONLY { RIP_IPATT->ttl_security = 2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
rip_iface_opts:
|
rip_iface_opts:
|
||||||
@ -98,6 +106,7 @@ rip_iface_init:
|
|||||||
RIP_IPATT->metric = 1;
|
RIP_IPATT->metric = 1;
|
||||||
RIP_IPATT->tx_tos = IP_PREC_INTERNET_CONTROL;
|
RIP_IPATT->tx_tos = IP_PREC_INTERNET_CONTROL;
|
||||||
RIP_IPATT->tx_priority = sk_priority_control;
|
RIP_IPATT->tx_priority = sk_priority_control;
|
||||||
|
RIP_IPATT->ttl_security = RIP_DEFAULT_TTL_SECURITY;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -480,6 +480,14 @@ rip_rx(sock *s, int size)
|
|||||||
iface = i->iface;
|
iface = i->iface;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (i->check_ttl && (s->ttl < 255))
|
||||||
|
{
|
||||||
|
log( L_REMOTE "%s: Discarding packet with TTL %d (< 255) from %I on %s",
|
||||||
|
p->name, s->ttl, s->faddr, i->iface->name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CHK_MAGIC;
|
CHK_MAGIC;
|
||||||
DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, i->iface ? i->iface->name : "(dummy)" );
|
DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, i->iface ? i->iface->name : "(dummy)" );
|
||||||
size -= sizeof( struct rip_packet_heading );
|
size -= sizeof( struct rip_packet_heading );
|
||||||
@ -686,6 +694,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
|||||||
rif->mode = PATT->mode;
|
rif->mode = PATT->mode;
|
||||||
rif->metric = PATT->metric;
|
rif->metric = PATT->metric;
|
||||||
rif->multicast = (!(PATT->mode & IM_BROADCAST)) && (flags & IF_MULTICAST);
|
rif->multicast = (!(PATT->mode & IM_BROADCAST)) && (flags & IF_MULTICAST);
|
||||||
|
rif->check_ttl = (PATT->ttl_security == 1);
|
||||||
}
|
}
|
||||||
/* lookup multicasts over unnumbered links - no: rip is not defined over unnumbered links */
|
/* lookup multicasts over unnumbered links - no: rip is not defined over unnumbered links */
|
||||||
|
|
||||||
@ -706,10 +715,10 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
|||||||
rif->sock->dport = P_CF->port;
|
rif->sock->dport = P_CF->port;
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
rif->sock->ttl = 1;
|
|
||||||
rif->sock->tos = PATT->tx_tos;
|
rif->sock->tos = PATT->tx_tos;
|
||||||
rif->sock->priority = PATT->tx_priority;
|
rif->sock->priority = PATT->tx_priority;
|
||||||
rif->sock->flags = SKF_LADDR_RX;
|
rif->sock->ttl = PATT->ttl_security ? 255 : 1;
|
||||||
|
rif->sock->flags = SKF_LADDR_RX | (rif->check_ttl ? SKF_TTL_RX : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new) {
|
if (new) {
|
||||||
|
@ -114,6 +114,7 @@ struct rip_interface {
|
|||||||
struct rip_connection *busy;
|
struct rip_connection *busy;
|
||||||
int metric; /* You don't want to put struct rip_patt *patt here -- think about reconfigure */
|
int metric; /* You don't want to put struct rip_patt *patt here -- think about reconfigure */
|
||||||
int mode;
|
int mode;
|
||||||
|
int check_ttl; /* Check incoming packets for TTL 255 */
|
||||||
int triggered;
|
int triggered;
|
||||||
struct object_lock *lock;
|
struct object_lock *lock;
|
||||||
int multicast;
|
int multicast;
|
||||||
@ -130,6 +131,7 @@ struct rip_patt {
|
|||||||
#define IM_VERSION1 16
|
#define IM_VERSION1 16
|
||||||
int tx_tos;
|
int tx_tos;
|
||||||
int tx_priority;
|
int tx_priority;
|
||||||
|
int ttl_security; /* bool + 2 for TX only (send, but do not check on RX) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rip_proto_config {
|
struct rip_proto_config {
|
||||||
|
@ -113,7 +113,9 @@ sysio_leave_group(sock *s, ip_addr maddr)
|
|||||||
/* BSD RX/TX packet info handling for IPv4 */
|
/* BSD RX/TX packet info handling for IPv4 */
|
||||||
/* it uses IP_RECVDSTADDR / IP_RECVIF socket options instead of IP_PKTINFO */
|
/* 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))
|
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@ -121,13 +123,18 @@ sysio_register_cmsgs(sock *s)
|
|||||||
{
|
{
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
if (s->flags & SKF_LADDR_RX)
|
if (s->flags & SKF_LADDR_RX)
|
||||||
{
|
{
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVDSTADDR, &ok, sizeof(ok)) < 0)
|
||||||
return "IP_RECVDSTADDR";
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -136,27 +143,35 @@ static void
|
|||||||
sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
||||||
{
|
{
|
||||||
struct cmsghdr *cm;
|
struct cmsghdr *cm;
|
||||||
|
struct in_addr *ra = NULL;
|
||||||
if (!(s->flags & SKF_LADDR_RX))
|
struct sockaddr_dl *ri = NULL;
|
||||||
return;
|
unsigned char *ttl = NULL;
|
||||||
|
|
||||||
s->laddr = IPA_NONE;
|
|
||||||
s->lifindex = 0;
|
|
||||||
|
|
||||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||||
{
|
{
|
||||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
|
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
|
||||||
{
|
ra = (struct in_addr *) CMSG_DATA(cm);
|
||||||
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_RECVIF)
|
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
|
||||||
{
|
ri = (struct sockaddr_dl *) CMSG_DATA(cm);
|
||||||
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_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);
|
// 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 */
|
/* RX/TX packet info handling for IPv4 */
|
||||||
/* Mostly similar to standardized IPv6 code */
|
/* 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))
|
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_pktinfo))
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
sysio_register_cmsgs(sock *s)
|
sysio_register_cmsgs(sock *s)
|
||||||
{
|
{
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
|
||||||
if ((s->flags & SKF_LADDR_RX) &&
|
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";
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,25 +218,34 @@ sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
|||||||
{
|
{
|
||||||
struct cmsghdr *cm;
|
struct cmsghdr *cm;
|
||||||
struct in_pktinfo *pi = NULL;
|
struct in_pktinfo *pi = NULL;
|
||||||
|
int *ttl = NULL;
|
||||||
if (!(s->flags & SKF_LADDR_RX))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||||
{
|
{
|
||||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO)
|
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO)
|
||||||
pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
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->laddr = IPA_NONE;
|
||||||
s->lifindex = 0;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +673,7 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, struct iface **ifa, unsigned *p
|
|||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
|
|
||||||
/* PKTINFO handling is also standardized in 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))
|
#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
|
#ifndef IPV6_RECVPKTINFO
|
||||||
#define IPV6_RECVPKTINFO IPV6_PKTINFO
|
#define IPV6_RECVPKTINFO IPV6_PKTINFO
|
||||||
#endif
|
#endif
|
||||||
|
/*
|
||||||
|
* Same goes for IPV6_HOPLIMIT -> IPV6_RECVHOPLIMIT.
|
||||||
|
*/
|
||||||
|
#ifndef IPV6_RECVHOPLIMIT
|
||||||
|
#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
|
||||||
|
#endif
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
sysio_register_cmsgs(sock *s)
|
sysio_register_cmsgs(sock *s)
|
||||||
{
|
{
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
|
|
||||||
if ((s->flags & SKF_LADDR_RX) &&
|
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";
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -702,25 +713,34 @@ sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
|||||||
{
|
{
|
||||||
struct cmsghdr *cm;
|
struct cmsghdr *cm;
|
||||||
struct in6_pktinfo *pi = NULL;
|
struct in6_pktinfo *pi = NULL;
|
||||||
|
int *hlim = NULL;
|
||||||
if (!(s->flags & SKF_LADDR_RX))
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||||
{
|
{
|
||||||
if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
|
if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
|
||||||
pi = (struct in6_pktinfo *) CMSG_DATA(cm);
|
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->laddr = IPA_NONE;
|
||||||
s->lifindex = 0;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user