summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldra.c59
1 files changed, 52 insertions, 7 deletions
diff --git a/ldra.c b/ldra.c
index 20dcbc4..30954e2 100644
--- a/ldra.c
+++ b/ldra.c
@@ -270,11 +270,10 @@ int sendit(int s, char *txbuf, int len, int ifidx)
}
int main(int argc, char *argv[]) {
- int domain, s, i;
- char str[INET6_ADDRSTRLEN];
+ int s;
struct sockaddr_ll ll;
char *buf, *txbuf;
- int fromlen, len = 0;
+ int len = 0;
int on = 1;
int vlan;
int size;
@@ -302,6 +301,12 @@ int main(int argc, char *argv[]) {
int idx_up, idx_down;
+ struct in6_addr all_dhcp_servers_and_relays;
+
+
+ /* prepare for comparing later on */
+ inet_pton(AF_INET6, "ff02::1:2", &all_dhcp_servers_and_relays);
+
/* FIXME: When using VLANs, we receive the *same* packet on both
main interface and VLAN interface, with no difference except
for the ifindex */
@@ -453,6 +458,9 @@ Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
}
/* do some common checks before knowing whether this packet goes up or down */
+
+ /* we need this for checking the source port */
+ udp = (struct udphdr *)(buf + sizeof(struct ethhdr) + sizeof(struct ip6_hdr));
/* NOTE: Not necessarily a relay message, but we only look at msg_type until we know for sure */
dhcpv6 = (struct dhcpv6_relay_msg *)(buf + sizeof(struct ethhdr) + sizeof(struct ip6_hdr) + sizeof(struct udphdr));
@@ -469,11 +477,17 @@ Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
continue;
}
- /* FIMXE:
+ /*
verify that destination and source address is link local
verify that source port is 547
*/
+ /* verify that source port is correct */
+ if (udp->source != htons(547)) {
+ fprintf(stderr, "invalid source port: %d\n", ntohs(udp->source));
+ continue;
+ }
+
/* parse DHCP RELAY message */
opt = (struct dhcpv6_option *)&dhcpv6->options;
txintf = parse_relay_packet(&opt, buf + len - (char *)&dhcpv6->options);
@@ -485,16 +499,28 @@ Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
fprintf(stderr, "received %d bytes from %s on interface %d (vlan=%d) with DHCPv6 type=%hhd\n",
len, macstr((char *)ll.sll_addr), ll.sll_ifindex, vlan, dhcpv6->msg_type);
-
/* create tx packet header */
size = copyheader(txbuf, buf, txintf & 0xfff);
- /* we change most of the UDP header, so create a new instead of copying */
+ /* setup pointer to IPv6 header */
ip6 = (struct ip6_hdr *)(txbuf + size - sizeof(struct ip6_hdr));
+
+ /* verify that both source and dest are link local */
+ if (!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
+ fprintf(stderr, "invalid source address: %s\n", ip6str(&ip6->ip6_src));
+ continue;
+ }
+ if (!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
+ fprintf(stderr, "invalid destination address: %s\n", ip6str(&ip6->ip6_dst));
+ continue;
+ }
+
+ /* we change most of the UDP header, so create a new instead of copying */
udp = setlen(ip6, ntohs(opt->len));
udp->dest = htons(546);
udp->source = htons(547);
size += sizeof(struct udphdr);
+
/* copy in the DHCP message */
memcpy(txbuf + size, &opt->data, ntohs(opt->len));
@@ -544,7 +570,7 @@ Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
hopcount = dhcpv6->hop_count + 1; /* propagate */
}
- /* FIMXE:
+ /*
verify that destination address is ff02::1:2
verify that source address is link local
verify that source port is 546 (unless hopcount > 0)
@@ -552,6 +578,12 @@ Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
*/
+ /* verify that source port is correct */
+ if ((hopcount && udp->source != htons(547)) || (!hopcount && udp->source != htons(546))) {
+ fprintf(stderr, "invalid source port: %d\n", ntohs(udp->source));
+ continue;
+ }
+
fprintf(stderr, "received %d bytes from %s on interface %d (vlan=%d) with DHCPv6 type=%hhd\n",
len, macstr((char *)ll.sll_addr), ll.sll_ifindex, vlan, dhcpv6->msg_type);
@@ -561,6 +593,19 @@ Steven McCanne and Van Jacobson of Lawrence Berkeley Laboratory.
/* save a pointer to the IPv6 header */
ip6 = (struct ip6_hdr *)(txbuf + size - sizeof(struct ip6_hdr));
+
+ /* verify that source address is link local */
+ if (!IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
+ fprintf(stderr, "invalid source address: %s\n", ip6str(&ip6->ip6_src));
+ continue;
+ }
+
+ /* verify that destination is ff02::1:2 */
+ if (memcmp(&all_dhcp_servers_and_relays, &ip6->ip6_dst, sizeof(&ip6->ip6_dst))) {
+ fprintf(stderr, "invalid destination address: %s\n", ip6str(&ip6->ip6_dst));
+ continue;
+ }
+
/* abusing the fact that we haven't updated this field yet */
datalen = ntohs(ip6->ip6_plen) - sizeof(struct udphdr);