mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-03-11 17:08:46 +00:00
Merge commit '6ac4f87a2d661c739e55a63577e7bccf696c7abd' into integrated
Conflicts: lib/socket.h proto/ospf/config.Y proto/ospf/iface.c proto/ospf/ospf.h proto/rip/rip.c sysdep/bsd/sysio.h sysdep/linux/sysio.h sysdep/unix/io.c
This commit is contained in:
commit
6abc22f4b0
@ -470,7 +470,7 @@ to zero to disable it. An empty <cf><m/switch/</cf> is equivalent to <cf/on/
|
||||
works in the direction from the routing table to the protocol.
|
||||
Default: <cf/none/.
|
||||
|
||||
<tag>import keep filtered <m/bool/</tag>
|
||||
<tag>import keep filtered <m/switch/</tag>
|
||||
Usually, if an import filter rejects a route, the route is
|
||||
forgotten. When this option is active, these routes are
|
||||
kept in the routing table, but they are hidden and not
|
||||
@ -1966,6 +1966,9 @@ protocol ospf <name> {
|
||||
ptp netmask <switch>;
|
||||
check link <switch>;
|
||||
ecmp weight <num>;
|
||||
ttl security [<switch>; | tx only]
|
||||
tx class|dscp <num>;
|
||||
tx priority <num>;
|
||||
authentication [none|simple|cryptographic];
|
||||
password "<text>";
|
||||
password "<text>" {
|
||||
@ -2236,6 +2239,20 @@ protocol ospf <name> {
|
||||
prefix) is propagated. It is possible that some hardware
|
||||
drivers or platforms do not implement this feature. Default value is no.
|
||||
|
||||
<tag>ttl security [<m/switch/ | tx only]</tag>
|
||||
TTL security is a feature that protects routing protocols
|
||||
from remote spoofed packets by using TTL 255 instead of TTL 1
|
||||
for protocol packets destined to neighbors. Because TTL is
|
||||
decremented when packets are forwarded, it is non-trivial to
|
||||
spoof packets with TTL 255 from remote locations. Note that
|
||||
this option would interfere with OSPF virtual links.
|
||||
|
||||
If this option is enabled, the router will send OSPF packets
|
||||
with TTL 255 and drop received packets with TTL less than
|
||||
255. If this option si set to <cf/tx only/, TTL 255 is used
|
||||
for sent packets, but is not checked for received
|
||||
packets. Default value is no.
|
||||
|
||||
<tag>tx class|dscp|priority <m/num/</tag>
|
||||
These options specify the ToS/DiffServ/Traffic class/Priority
|
||||
of the outgoing OSPF packets. See <ref id="dsc-prio" name="tx
|
||||
@ -2784,6 +2801,26 @@ makes it pretty much obsolete. (It is still usable on very small networks.)
|
||||
any periodic messages to this interface and <cf/nolisten/
|
||||
means that RIP will send to this interface butnot listen to it.
|
||||
|
||||
<tag>ttl security [<m/switch/ | tx only]</tag>
|
||||
TTL security is a feature that protects routing protocols
|
||||
from remote spoofed packets by using TTL 255 instead of TTL 1
|
||||
for protocol packets destined to neighbors. Because TTL is
|
||||
decremented when packets are forwarded, it is non-trivial to
|
||||
spoof packets with TTL 255 from remote locations.
|
||||
|
||||
If this option is enabled, the router will send RIP packets
|
||||
with TTL 255 and drop received packets with TTL less than
|
||||
255. If this option si set to <cf/tx only/, TTL 255 is used
|
||||
for sent packets, but is not checked for received
|
||||
packets. Such setting does not offer protection, but offers
|
||||
compatibility with neighbors regardless of whether they use
|
||||
ttl security.
|
||||
|
||||
Note that for RIPng, TTL security is a standard behavior
|
||||
(required by RFC 2080), but BIRD uses <cf/tx only/ by
|
||||
default, for compatibility with older versions. For IPv4 RIP,
|
||||
default value is no.
|
||||
|
||||
<tag>tx class|dscp|priority <m/num/</tag>
|
||||
These options specify the ToS/DiffServ/Traffic class/Priority
|
||||
of the outgoing RIP packets. See <ref id="dsc-prio" name="tx
|
||||
|
@ -89,10 +89,11 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul
|
||||
|
||||
/* Socket flags */
|
||||
|
||||
#define SKF_V4ONLY 1 /* Use IPv4 for IP sockets */
|
||||
#define SKF_V6ONLY 2 /* Use IPV6_V6ONLY socket option */
|
||||
#define SKF_LADDR_RX 4 /* Report local address for RX packets */
|
||||
#define SKF_LADDR_TX 6 /* Allow to specify local address for TX packets */
|
||||
#define SKF_V4ONLY 0x01 /* Use IPv4 for IP sockets */
|
||||
#define SKF_V6ONLY 0x02 /* Use IPV6_V6ONLY socket option */
|
||||
#define SKF_LADDR_RX 0x04 /* Report local address for RX packets */
|
||||
#define SKF_LADDR_TX 0x08 /* Allow to specify local address for TX packets */
|
||||
#define SKF_TTL_RX 0x10 /* Report TTL / Hop Limit for RX packets */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -112,8 +112,8 @@ CF_KEYWORDS(OSPF, OSPF2, OSPF3, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG, OSPF
|
||||
CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, COST2, RETRANSMIT)
|
||||
CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, TYPE, BROADCAST, BCAST)
|
||||
CF_KEYWORDS(NONBROADCAST, NBMA, POINTOPOINT, PTP, POINTOMULTIPOINT, PTMP)
|
||||
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC)
|
||||
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK)
|
||||
CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC, TTL, SECURITY)
|
||||
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK, ONLY)
|
||||
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
|
||||
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
|
||||
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY)
|
||||
@ -297,6 +297,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"); }
|
||||
| TX tos { OSPF_PATT->tx_tos = $2; }
|
||||
| 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 { ospf_check_auth(); }
|
||||
;
|
||||
|
||||
|
@ -88,7 +88,7 @@ ospf_sk_open(struct ospf_iface *ifa)
|
||||
sk->rbsize = rxbufsize(ifa);
|
||||
sk->tbsize = rxbufsize(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)
|
||||
goto err;
|
||||
@ -134,7 +134,7 @@ ospf_sk_open(struct ospf_iface *ifa)
|
||||
{
|
||||
ifa->all_routers = ospf_is_v2(po) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
|
||||
ifa->des_routers = ospf_is_v2(po) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
|
||||
sk->ttl = 1; /* Hack, this will affect just the multicast packets */
|
||||
sk->ttl = ifa->cf->ttl_security ? 255 : 1;
|
||||
|
||||
if (sk_setup_multicast(sk) < 0)
|
||||
goto err;
|
||||
@ -535,6 +535,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
ifa->rxbuf = ip->rxbuf;
|
||||
ifa->check_link = ip->check_link;
|
||||
ifa->ecmp_weight = ip->ecmp_weight;
|
||||
ifa->check_ttl = (ip->ttl_security == 1);
|
||||
ifa->autype = ip->autype;
|
||||
ifa->passwords = ip->passwords;
|
||||
ifa->instance_id = ip->instance_id;
|
||||
|
@ -248,6 +248,7 @@ struct ospf_iface
|
||||
u8 check_link; /* Whether iface link change is used */
|
||||
u8 ecmp_weight; /* Weight used for ECMP */
|
||||
u8 ptp_netmask; /* Send real netmask for P2P */
|
||||
u8 check_ttl; /* Check incoming packets for TTL 255 */
|
||||
};
|
||||
|
||||
struct ospf_md5
|
||||
@ -754,7 +755,8 @@ struct ospf_iface_patt
|
||||
u8 check_link;
|
||||
u8 ecmp_weight;
|
||||
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 */
|
||||
u8 instance_id;
|
||||
list *passwords;
|
||||
};
|
||||
|
@ -311,6 +311,12 @@ ospf_rx_hook(sock *sk, int size)
|
||||
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))
|
||||
{
|
||||
log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
|
||||
|
@ -22,12 +22,15 @@ CF_DEFINES
|
||||
#define RIP_CFG ((struct rip_proto_config *) this_proto)
|
||||
#define RIP_IPATT ((struct rip_patt *) this_ipatt)
|
||||
|
||||
static inline int rip_cfg_is_old(void) { return RIP_CFG->c.protocol == &proto_rip; }
|
||||
static inline int rip_cfg_is_ng(void) { return RIP_CFG->c.protocol == &proto_ripng; }
|
||||
|
||||
CF_DECLS
|
||||
|
||||
CF_KEYWORDS(RIP, RIPNG, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT,
|
||||
MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1,
|
||||
AUTHENTICATION, NONE, PLAINTEXT, MD5,
|
||||
HONOR, NEVER, NEIGHBOR, ALWAYS, TX, PRIORITY,
|
||||
AUTHENTICATION, NONE, PLAINTEXT, MD5, TTL, SECURITY,
|
||||
HONOR, NEVER, NEIGHBOR, ALWAYS, TX, PRIORITY, ONLY,
|
||||
RIP_METRIC, RIP_TAG)
|
||||
|
||||
%type <i> rip_mode rip_auth
|
||||
@ -87,6 +90,8 @@ rip_iface_item:
|
||||
| MODE rip_mode { RIP_IPATT->mode |= $2; }
|
||||
| TX tos { RIP_IPATT->tx_tos = $2; }
|
||||
| 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:
|
||||
@ -107,6 +112,7 @@ rip_iface_init:
|
||||
RIP_IPATT->metric = 1;
|
||||
RIP_IPATT->tx_tos = IP_PREC_INTERNET_CONTROL;
|
||||
RIP_IPATT->tx_priority = sk_priority_control;
|
||||
RIP_IPATT->ttl_security = rip_cfg_is_ng() ? 1 : 0;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -481,6 +481,14 @@ rip_rx(sock *s, int size)
|
||||
iface = i->iface;
|
||||
|
||||
|
||||
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;
|
||||
DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, iface ? iface->name : "(dummy)" );
|
||||
size -= sizeof( struct rip_packet_heading );
|
||||
@ -687,6 +695,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
||||
rif->mode = PATT->mode;
|
||||
rif->metric = PATT->metric;
|
||||
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 */
|
||||
|
||||
@ -708,10 +717,10 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
||||
rif->sock->flags = rip_is_old(p) ? SKF_V4ONLY : SKF_V6ONLY;
|
||||
if (new)
|
||||
{
|
||||
rif->sock->ttl = 1;
|
||||
rif->sock->tos = PATT->tx_tos;
|
||||
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) {
|
||||
|
@ -109,6 +109,7 @@ struct rip_interface {
|
||||
struct rip_connection *busy;
|
||||
int metric; /* You don't want to put struct rip_patt *patt here -- think about reconfigure */
|
||||
int mode;
|
||||
int check_ttl; /* Check incoming packets for TTL 255 */
|
||||
int triggered;
|
||||
struct object_lock *lock;
|
||||
int multicast;
|
||||
@ -125,6 +126,7 @@ struct rip_patt {
|
||||
#define IM_VERSION1 16
|
||||
int tx_tos;
|
||||
int tx_priority;
|
||||
int ttl_security; /* bool + 2 for TX only (send, but do not check on RX) */
|
||||
};
|
||||
|
||||
struct rip_proto_config {
|
||||
|
@ -81,43 +81,57 @@ sk_leave_group4(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_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
|
||||
#define CMSG_SPACE_PKTINFO4 (CMSG_SPACE(sizeof(struct in_addr)) + \
|
||||
CMSG_SPACE(sizeof(struct sockaddr_dl)))
|
||||
#define CMSG_SPACE_PKTINFO6 CMSG_SPACE(sizeof(struct in6_pktinfo))
|
||||
|
||||
static char *
|
||||
sk_request_pktinfo4(sock *s)
|
||||
#define CMSG_RX_SPACE (MAX(CMSG_SPACE_PKTINFO4,CMSG_SPACE_PKTINFO6) + CMSG_SPACE(sizeof(int)))
|
||||
#define CMSG_TX_SPACE MAX(CMSG_SPACE_PKTINFO4,CMSG_SPACE_PKTINFO6)
|
||||
|
||||
|
||||
static inline char *
|
||||
sk_request_cmsg4_pktinfo(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_RECVIF, &ok, sizeof(ok)) < 0)
|
||||
return "IP_RECVIF";
|
||||
}
|
||||
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";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
sk_process_rx_cmsg4(sock *s, struct cmsghdr *cm)
|
||||
static inline void
|
||||
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
|
||||
{
|
||||
struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm);
|
||||
s->laddr = ipa_get_in4(ra);
|
||||
}
|
||||
if ((cm->cmsg_type == IP_RECVDSTADDR) && (s->flags & SKF_LADDR_RX))
|
||||
s->laddr = ipa_get_in4((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;
|
||||
}
|
||||
|
||||
// log(L_WARN "RX %I %d", s->laddr, s->lifindex);
|
||||
if ((cm->cmsg_type == IP_RECVIF) && (s->flags & SKF_LADDR_RX))
|
||||
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
|
||||
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
||||
{
|
||||
if ((cm->cmsg_type == IP_RECVTTL) && (s->flags & SKF_TTL_RX))
|
||||
s->ttl = * (unsigned char *) CMSG_DATA(cm);
|
||||
}
|
||||
|
||||
|
||||
/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
|
||||
/*
|
||||
static void
|
||||
|
@ -157,34 +157,52 @@ sk_set_md5_auth_int(sock *s, struct sockaddr *sa, int sa_len, char *passwd)
|
||||
/* RX/TX packet info handling for IPv4 */
|
||||
/* Mostly similar to standardized IPv6 code */
|
||||
|
||||
#define CMSG_SPACE_PKTINFO4 CMSG_SPACE(sizeof(struct in_pktinfo))
|
||||
#define CMSG_SPACE_PKTINFO6 CMSG_SPACE(sizeof(struct in6_pktinfo))
|
||||
|
||||
#define CMSG_RX_SPACE MAX(CMSG_SPACE_PKTINFO4,CMSG_SPACE_PKTINFO6)
|
||||
#define CMSG_TX_SPACE MAX(CMSG_SPACE_PKTINFO4,CMSG_SPACE_PKTINFO6)
|
||||
#define CMSG4_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in_pktinfo))
|
||||
|
||||
static inline char *
|
||||
sk_request_pktinfo4(sock *s)
|
||||
sk_request_cmsg4_pktinfo(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0)
|
||||
return "IP_PKTINFO";
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0)
|
||||
return "IP_PKTINFO";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
sk_process_rx_cmsg4(sock *s, struct cmsghdr *cm)
|
||||
sk_process_cmsg4_pktinfo(sock *s, struct cmsghdr *cm)
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_PKTINFO)
|
||||
{
|
||||
struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||
s->laddr = ipa_get_in4(&pi->ipi_addr);
|
||||
s->lifindex = pi->ipi_ifindex;
|
||||
}
|
||||
if ((cm->cmsg_type == IP_PKTINFO) && (s->flags & SKF_LADDR_RX))
|
||||
{
|
||||
struct in_pktinfo *pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||
s->laddr = ipa_get_in4(&pi->ipi_addr);
|
||||
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, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0)
|
||||
return "IP_RECVTTL";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
||||
{
|
||||
if ((cm->cmsg_type == IP_TTL) && (s->flags & SKF_TTL_RX))
|
||||
s->ttl = * (int *) CMSG_DATA(cm);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static void
|
||||
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
|
119
sysdep/unix/io.c
119
sysdep/unix/io.c
@ -700,42 +700,96 @@ sk_insert(sock *s)
|
||||
#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
|
||||
|
||||
|
||||
#define CMSG6_SPACE_PKTINFO CMSG_SPACE(sizeof(struct in6_pktinfo))
|
||||
|
||||
static inline char *
|
||||
sk_request_pktinfo6(sock *s)
|
||||
sk_request_cmsg6_pktinfo(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0)
|
||||
return "IPV6_RECVPKTINFO";
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0)
|
||||
return "IPV6_RECVPKTINFO";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
sk_process_cmsg6_pktinfo(sock *s, struct cmsghdr *cm)
|
||||
{
|
||||
if ((cm->cmsg_type == IPV6_PKTINFO) && (s->flags & SKF_LADDR_RX))
|
||||
{
|
||||
struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cm);
|
||||
s->laddr = ipa_get_in6(&pi->ipi6_addr);
|
||||
s->lifindex = pi->ipi6_ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define CMSG6_SPACE_TTL CMSG_SPACE(sizeof(int))
|
||||
|
||||
static inline char *
|
||||
sk_request_cmsg6_ttl(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0)
|
||||
return "IPV6_RECVHOPLIMIT";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
sk_process_cmsg6_ttl(sock *s, struct cmsghdr *cm)
|
||||
{
|
||||
if ((cm->cmsg_type == IPV6_HOPLIMIT) && (s->flags & SKF_TTL_RX))
|
||||
s->ttl = * (int *) CMSG_DATA(cm);
|
||||
}
|
||||
|
||||
|
||||
#define CMSG_RX_SPACE MAX(CMSG4_SPACE_PKTINFO+CMSG4_SPACE_TTL, \
|
||||
CMSG6_SPACE_PKTINFO+CMSG6_SPACE_TTL)
|
||||
#define CMSG_TX_SPACE MAX(CMSG4_SPACE_PKTINFO,CMSG6_SPACE_PKTINFO)
|
||||
|
||||
|
||||
static void
|
||||
sk_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
||||
sk_process_cmsgs(sock *s, struct msghdr *msg)
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
|
||||
if (!(s->flags & SKF_LADDR_RX))
|
||||
return;
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
{
|
||||
s->laddr = IPA_NONE;
|
||||
s->lifindex = 0;
|
||||
}
|
||||
|
||||
s->laddr = IPA_NONE;
|
||||
s->lifindex = 0;
|
||||
if (s->flags & SKF_TTL_RX)
|
||||
s->ttl = -1;
|
||||
|
||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||
{
|
||||
if ((cm->cmsg_level == IPPROTO_IP) && sk_is_ipv4(s))
|
||||
{
|
||||
if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO)
|
||||
{
|
||||
struct in6_pktinfo *pi = (struct in6_pktinfo *) CMSG_DATA(cm);
|
||||
s->laddr = ipa_get_in6(&pi->ipi6_addr);
|
||||
s->lifindex = pi->ipi6_ifindex;
|
||||
}
|
||||
|
||||
sk_process_rx_cmsg4(s, cm);
|
||||
sk_process_cmsg4_pktinfo(s, cm);
|
||||
sk_process_cmsg4_ttl(s, cm);
|
||||
}
|
||||
|
||||
if ((cm->cmsg_level == IPPROTO_IPV6) && sk_is_ipv6(s))
|
||||
{
|
||||
sk_process_cmsg6_pktinfo(s, cm);
|
||||
sk_process_cmsg6_ttl(s, cm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static void
|
||||
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
@ -794,14 +848,33 @@ sk_setup(sock *s)
|
||||
if (s->priority >= 0)
|
||||
sk_set_priority(s, s->priority);
|
||||
|
||||
// XXXX better error handling
|
||||
if (s->ttl >= 0)
|
||||
sk_set_ttl(s, s->ttl);
|
||||
if (sk_set_ttl(s, s->ttl) < 0)
|
||||
ERR("sk_set_ttl");
|
||||
|
||||
if (sk_is_ipv4(s))
|
||||
err = sk_request_pktinfo4(s);
|
||||
else
|
||||
err = sk_request_pktinfo6(s);
|
||||
{
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
if (err = sk_request_cmsg4_pktinfo(s))
|
||||
goto bad;
|
||||
|
||||
if (s->flags & SKF_TTL_RX)
|
||||
if (err = sk_request_cmsg4_ttl(s))
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (sk_is_ipv6(s))
|
||||
{
|
||||
if (s->flags & SKF_LADDR_RX)
|
||||
if (err = sk_request_cmsg6_pktinfo(s))
|
||||
goto bad;
|
||||
|
||||
if (s->flags & SKF_TTL_RX)
|
||||
if (err = sk_request_cmsg6_ttl(s));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
bad:
|
||||
return err;
|
||||
}
|
||||
@ -1493,7 +1566,7 @@ sk_read(sock *s)
|
||||
}
|
||||
s->rpos = s->rbuf + e;
|
||||
sockaddr_read(sa, &s->faddr, NULL, &s->fport, 1);
|
||||
sk_process_rx_cmsgs(s, &msg);
|
||||
sk_process_cmsgs(s, &msg);
|
||||
|
||||
s->rx_hook(s, e);
|
||||
return 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user