diff options
author | Renato Westphal <renato@cvs.openbsd.org> | 2016-05-23 16:08:19 +0000 |
---|---|---|
committer | Renato Westphal <renato@cvs.openbsd.org> | 2016-05-23 16:08:19 +0000 |
commit | 91ec63a6cc84ab519bdb3d5333da436b8b9a2647 (patch) | |
tree | 165323bcc28becfcbc217e6e1d05e9ec27de1cc9 /usr.sbin/ldpd/packet.c | |
parent | 960a41bce4d794d6d183c192d4ee2fd1f6021296 (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.c | 53 |
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); } |