| /* SPDX-License-Identifier: BSD-3-Clause */ |
| /* |
| * Copyright (c) 2013 |
| * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne. |
| */ |
| |
| #include "slirp.h" |
| #include "ip6_icmp.h" |
| |
| /* |
| * IP initialization: fill in IP protocol switch table. |
| * All protocols not implemented in kernel go to raw IP protocol handler. |
| */ |
| void ip6_post_init(Slirp *slirp) |
| { |
| icmp6_post_init(slirp); |
| } |
| |
| void ip6_cleanup(Slirp *slirp) |
| { |
| icmp6_cleanup(slirp); |
| } |
| |
| void ip6_input(struct mbuf *m) |
| { |
| Slirp *slirp = m->slirp; |
| /* NDP reads the ethernet header for gratuitous NDP */ |
| M_DUP_DEBUG(slirp, m, 1, TCPIPHDR_DELTA + 2 + ETH_HLEN); |
| |
| struct ip6 *ip6; |
| |
| if (!slirp->in6_enabled) { |
| goto bad; |
| } |
| |
| DEBUG_CALL("ip6_input"); |
| DEBUG_ARG("m = %p", m); |
| DEBUG_ARG("m_len = %d", m->m_len); |
| |
| if (m->m_len < sizeof(struct ip6)) { |
| goto bad; |
| } |
| |
| ip6 = mtod(m, struct ip6 *); |
| |
| if (ip6->ip_v != IP6VERSION) { |
| goto bad; |
| } |
| |
| if (ntohs(ip6->ip_pl) + sizeof(struct ip6) > slirp->if_mtu) { |
| icmp6_send_error(m, ICMP6_TOOBIG, 0); |
| goto bad; |
| } |
| |
| // Check if the message size is big enough to hold what's |
| // set in the payload length header. If not this is an invalid |
| // packet |
| if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) { |
| goto bad; |
| } |
| |
| /* check ip_ttl for a correct ICMP reply */ |
| if (ip6->ip_hl == 0) { |
| icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS); |
| goto bad; |
| } |
| |
| /* |
| * Switch out to protocol's input routine. |
| */ |
| switch (ip6->ip_nh) { |
| case IPPROTO_TCP: |
| NTOHS(ip6->ip_pl); |
| tcp_input(m, sizeof(struct ip6), (struct socket *)NULL, AF_INET6); |
| break; |
| case IPPROTO_UDP: |
| udp6_input(m); |
| break; |
| case IPPROTO_ICMPV6: |
| icmp6_input(m); |
| break; |
| default: |
| m_free(m); |
| } |
| return; |
| bad: |
| m_free(m); |
| } |