diff --git a/dhcp6.c b/dhcp6.c index cb145eb..4454f4e 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -29,7 +29,7 @@ static struct dhcp6_in_option list_option; static int dhcpv6_format_dns_search_name(const char *strdns, uint8_t *buffer); -static void dhcp6_send_reply(sessionidt s, tunnelidt t, struct in6_addr *ip6_src) +static void dhcp6_send_reply(sessionidt s, tunnelidt t, const struct in6_addr *ip6_src) { struct ip6_hdr *p_ip6_hdr; struct udphdr *p_udp; @@ -309,26 +309,22 @@ static char * get_msg_type(uint8_t type) } } -void dhcpv6_process(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) +void dhcpv6_process(sessionidt s, tunnelidt t, const struct in6_addr *addr, uint8_t *p, uint16_t l) { - struct ip6_hdr *p_ip6_hdr_in; - struct dhcp6_mess_hdr *p_mess_hdr; + struct dhcp6_mess_hdr *p_mess_hdr = (struct dhcp6_mess_hdr *) p; struct dhcp6_opt_h *p_opt; uint8_t *p_end; uint16_t len; CSTAT(dhcpv6_process); - p_ip6_hdr_in = (struct ip6_hdr *) p; - p_mess_hdr = (struct dhcp6_mess_hdr *) (p + 48); - LOG(3, s, t, "Got DHCPv6 message Type: %s(%d)\n", get_msg_type(p_mess_hdr->type), p_mess_hdr->type); if (!session[s].route6[0].ipv6route.s6_addr[0] || !session[s].route6[0].ipv6prefixlen) return; p_opt = (struct dhcp6_opt_h *) &p_mess_hdr[1]; - p_end = ((uint8_t *)p_ip6_hdr_in) + ntohs(p_ip6_hdr_in->ip6_plen) + sizeof(*p_ip6_hdr_in); + p_end = p + l; memset(&list_option, 0, sizeof(list_option)); list_option.p_mess_hdr = p_mess_hdr; while (((uint8_t *)p_opt) < p_end) @@ -413,7 +409,7 @@ void dhcpv6_process(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) return; } - dhcp6_send_reply(s, t, &p_ip6_hdr_in->ip6_src); + dhcp6_send_reply(s, t, addr); } break; @@ -458,8 +454,8 @@ void dhcpv6_process(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) return; } - dhcp6_send_reply(s, t, &p_ip6_hdr_in->ip6_src); - send_ipv6_ra(s, t, &p_ip6_hdr_in->ip6_src); // send a RA + dhcp6_send_reply(s, t, addr); + send_ipv6_ra(s, t, addr); // send a RA } break; @@ -489,7 +485,7 @@ void dhcpv6_process(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) return; } - dhcp6_send_reply(s, t, &p_ip6_hdr_in->ip6_src); + dhcp6_send_reply(s, t, addr); } break; @@ -501,7 +497,7 @@ void dhcpv6_process(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) return; } - dhcp6_send_reply(s, t, &p_ip6_hdr_in->ip6_src); + dhcp6_send_reply(s, t, addr); } break; @@ -527,6 +523,37 @@ void dhcpv6_process(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) return; } +void dhcpv6_process_from_ipv6(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) +{ + struct ip6_hdr *p_ip6_hdr_in = (struct ip6_hdr *) p; + struct in6_addr *addr = &p_ip6_hdr_in->ip6_src; + uint16_t ipv6_len = ntohs(p_ip6_hdr_in->ip6_plen); + + l -= sizeof(*p_ip6_hdr_in); + p += sizeof(*p_ip6_hdr_in); + + if (ipv6_len > l) + { + LOG(5, 0, 0, "bogus IPv6 packet size??\n"); + return; + } + + if (p_ip6_hdr_in->ip6_nxt != 17) + { + LOG(5, 0, 0, "not UDP DHCP packet??\n"); + return; + } + if (ipv6_len < sizeof(struct udphdr)) + { + LOG(5, 0, 0, "bogus IPv6 packet size for UDP??\n"); + return; + } + ipv6_len -= sizeof(struct udphdr); + p += sizeof(struct udphdr); + + dhcpv6_process(s, t, addr, p, ipv6_len); +} + static int dhcpv6_format_dns_search_name(const char *strdns, uint8_t *buffer) { int n = strlen(strdns); diff --git a/dhcp6.h b/dhcp6.h index 4b0eb19..54cd76d 100644 --- a/dhcp6.h +++ b/dhcp6.h @@ -212,7 +212,7 @@ struct dhcp6_opt_ia_prefix { } __attribute__((packed)); // dhcp6.c -void dhcpv6_process(uint16_t s, uint16_t t, uint8_t *p, uint16_t l); +void dhcpv6_process_from_ipv6(uint16_t s, uint16_t t, uint8_t *p, uint16_t l); void dhcpv6_init(void); #endif /* __DHCP6_H__ */ diff --git a/icmp.c b/icmp.c index 54690eb..168eb5f 100644 --- a/icmp.c +++ b/icmp.c @@ -96,7 +96,7 @@ struct nd_opt_rdnss_info_l2tpns struct in6_addr nd_opt_rdnssi[0]; }; -void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip) +void send_ipv6_ra(sessionidt s, tunnelidt t, const struct in6_addr *ip) { struct nd_opt_prefix_info *pinfo; struct ip6_hdr *p_ip6_hdr; diff --git a/l2tpns.h b/l2tpns.h index 9220b9e..80cccf5 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -960,7 +960,7 @@ int rad_tunnel_pwdecode(uint8_t *pl2tpsecret, size_t *pl2tpsecretlen, const char // l2tpns.c clockt backoff(uint8_t try); -void send_ipv6_ra(sessionidt s, tunnelidt t, struct in6_addr *ip); +void send_ipv6_ra(sessionidt s, tunnelidt t, const struct in6_addr *ip); void route6set(sessionidt s, struct in6_addr ip, int prefixlen, int add); void routes6set(sessionidt s, sessiont *sp, int add); sessionidt sessionbyip(in_addr_t ip); diff --git a/ppp.c b/ppp.c index 43c4213..1f5791f 100644 --- a/ppp.c +++ b/ppp.c @@ -2286,7 +2286,7 @@ void processipv6in(sessionidt s, tunnelidt t, uint8_t *p, uint16_t l) *(uint16_t *)(p + 34) == 0 && *(p + 36) == 0 && *(p + 37) == 1 && *(p + 38) == 0 && *(p + 39) == 2 && *(p + 40) == 2 && *(p + 41) == 0x22 && *(p + 42) == 2 && *(p + 43) == 0x23) { - dhcpv6_process(s, t, p, l); + dhcpv6_process_from_ipv6(s, t, p, l); return; }