summaryrefslogtreecommitdiff
path: root/usr.sbin/ldpd/packet.c
diff options
context:
space:
mode:
authorRenato Westphal <renato@cvs.openbsd.org>2016-05-23 16:08:19 +0000
committerRenato Westphal <renato@cvs.openbsd.org>2016-05-23 16:08:19 +0000
commit91ec63a6cc84ab519bdb3d5333da436b8b9a2647 (patch)
tree165323bcc28becfcbc217e6e1d05e9ec27de1cc9 /usr.sbin/ldpd/packet.c
parent960a41bce4d794d6d183c192d4ee2fd1f6021296 (diff)
Several improvements in the parsing of UDP/Hello packets.
* Fix check of the packet's size and the "PDU Length" field; * Add check for the "Message Length" field; * Check for invalid labelspace earlier. * Use if_lookup() on disc_recv_iface() to reduce one level of identation; Additionally, add the following safeguards: * Check for unicast link hellos; * Check for multicast targeted hellos; * Validate packet's source address; * Validate received transport-address. Put the ancillary function bad_ip_addr() into a new file, util.c, which will be used later for several other things.
Diffstat (limited to 'usr.sbin/ldpd/packet.c')
-rw-r--r--usr.sbin/ldpd/packet.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c
index 6ea5aafd4d8..b855b22ea98 100644
--- a/usr.sbin/ldpd/packet.c
+++ b/usr.sbin/ldpd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.48 2016/05/23 16:06:08 renato Exp $ */
+/* $OpenBSD: packet.c,v 1.49 2016/05/23 16:08:18 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -42,7 +42,7 @@
extern struct ldpd_conf *leconf;
extern struct ldpd_sysdep sysdep;
-struct iface *disc_find_iface(unsigned int, struct in_addr);
+struct iface *disc_find_iface(unsigned int, struct in_addr, int);
ssize_t session_get_pdu(struct ibuf_read *, char **);
static int msgcnt = 0;
@@ -142,6 +142,14 @@ disc_recv_packet(int fd, short event, void *bula)
strerror(errno));
return;
}
+
+ multicast = (msg.msg_flags & MSG_MCAST) ? 1 : 0;
+ if (bad_ip_addr(src.sin_addr)) {
+ log_debug("%s: invalid source address: %s", __func__,
+ inet_ntoa(src.sin_addr));
+ return;
+ }
+
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == IPPROTO_IP &&
@@ -203,27 +211,34 @@ disc_recv_packet(int fd, short event, void *bula)
}
struct iface *
-disc_find_iface(unsigned int ifindex, struct in_addr src)
+disc_find_iface(unsigned int ifindex, struct in_addr src,
+ int multicast)
{
struct iface *iface;
struct if_addr *if_addr;
- LIST_FOREACH(iface, &leconf->iface_list, entry)
- LIST_FOREACH(if_addr, &iface->addr_list, entry)
- switch (iface->type) {
- case IF_TYPE_POINTOPOINT:
- if (ifindex == iface->ifindex &&
- if_addr->dstbrd.s_addr == src.s_addr)
- return (iface);
- break;
- default:
- if (ifindex == iface->ifindex &&
- (if_addr->addr.s_addr &
- if_addr->mask.s_addr) ==
- (src.s_addr & if_addr->mask.s_addr))
- return (iface);
- break;
- }
+ iface = if_lookup(leconf, ifindex);
+ if (iface == NULL)
+ return (NULL);
+
+ if (!multicast)
+ return (iface);
+
+ LIST_FOREACH(if_addr, &iface->addr_list, entry) {
+ switch (iface->type) {
+ case IF_TYPE_POINTOPOINT:
+ if (ifindex == iface->ifindex &&
+ if_addr->dstbrd.s_addr == src.s_addr)
+ return (iface);
+ break;
+ default:
+ if (ifindex == iface->ifindex &&
+ (if_addr->addr.s_addr & if_addr->mask.s_addr) ==
+ (src.s_addr & if_addr->mask.s_addr))
+ return (iface);
+ break;
+ }
+ }
return (NULL);
}