Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/udp6.c
2 views
/* SPDX-License-Identifier: BSD-3-Clause */1/*2* Copyright (c) 20133* Guillaume Subiron4*/56#include "slirp.h"7#include "udp.h"8#include "dhcpv6.h"910void udp6_input(struct mbuf *m)11{12Slirp *slirp = m->slirp;13M_DUP_DEBUG(slirp, m, 0, 0);1415struct ip6 *ip, save_ip;16struct udphdr *uh;17int iphlen = sizeof(struct ip6);18int len;19struct socket *so;20struct sockaddr_in6 lhost;21int hop_limit;2223DEBUG_CALL("udp6_input");24DEBUG_ARG("m = %p", m);2526if (slirp->restricted) {27goto bad;28}2930ip = mtod(m, struct ip6 *);31m->m_len -= iphlen;32m->m_data += iphlen;33uh = mtod_check(m, sizeof(struct udphdr));34if (uh == NULL) {35goto bad;36}37m->m_len += iphlen;38m->m_data -= iphlen;3940if (ip6_cksum(m)) {41goto bad;42}4344len = ntohs((uint16_t)uh->uh_ulen);4546/*47* Make mbuf data length reflect UDP length.48* If not enough data to reflect UDP length, drop.49*/50if (ntohs(ip->ip_pl) != len) {51if (len > ntohs(ip->ip_pl)) {52goto bad;53}54m_adj(m, len - ntohs(ip->ip_pl));55ip->ip_pl = htons(len);56}5758/*59* Save a copy of the IP header in case we want restore it60* for sending an ICMP error message in response.61*/62save_ip = *ip;6364/* Locate pcb for datagram. */65lhost.sin6_family = AF_INET6;66lhost.sin6_addr = ip->ip_src;67lhost.sin6_port = uh->uh_sport;6869/* handle DHCPv6 */70if (ntohs(uh->uh_dport) == DHCPV6_SERVER_PORT &&71(in6_equal(&ip->ip_dst, &slirp->vhost_addr6) ||72in6_dhcp_multicast(&ip->ip_dst))) {73m->m_data += iphlen;74m->m_len -= iphlen;75dhcpv6_input(&lhost, m);76m->m_data -= iphlen;77m->m_len += iphlen;78goto bad;79}8081/* handle TFTP */82if (ntohs(uh->uh_dport) == TFTP_SERVER &&83!memcmp(ip->ip_dst.s6_addr, slirp->vhost_addr6.s6_addr, 16)) {84m->m_data += iphlen;85m->m_len -= iphlen;86tftp_input((struct sockaddr_storage *)&lhost, m);87m->m_data -= iphlen;88m->m_len += iphlen;89goto bad;90}9192so = solookup(&slirp->udp_last_so, &slirp->udb,93(struct sockaddr_storage *)&lhost, NULL);9495if (so == NULL) {96/* If there's no socket for this packet, create one. */97so = socreate(slirp, IPPROTO_UDP);98if (udp_attach(so, AF_INET6) == -1) {99DEBUG_MISC(" udp6_attach errno = %d-%s", errno, strerror(errno));100sofree(so);101goto bad;102}103104/* Setup fields */105so->so_lfamily = AF_INET6;106so->so_laddr6 = ip->ip_src;107so->so_lport6 = uh->uh_sport;108}109110so->so_ffamily = AF_INET6;111so->so_faddr6 = ip->ip_dst; /* XXX */112so->so_fport6 = uh->uh_dport; /* XXX */113114iphlen += sizeof(struct udphdr);115m->m_len -= iphlen;116m->m_data += iphlen;117118/*119* Check for TTL120*/121hop_limit = save_ip.ip_hl-1;122if (hop_limit <= 0) {123m->m_len += iphlen;124m->m_data -= iphlen;125*ip = save_ip;126DEBUG_MISC("udp ttl exceeded");127icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);128goto bad;129}130setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, sizeof(hop_limit));131132/*133* Now we sendto() the packet.134*/135if (sosendto(so, m) == -1) {136m->m_len += iphlen;137m->m_data -= iphlen;138*ip = save_ip;139DEBUG_MISC("udp tx errno = %d-%s", errno, strerror(errno));140icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);141goto bad;142}143144m_free(so->so_m); /* used for ICMP if error on sorecvfrom */145146/* restore the orig mbuf packet */147m->m_len += iphlen;148m->m_data -= iphlen;149*ip = save_ip;150so->so_m = m;151152return;153bad:154m_free(m);155}156157int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr,158struct sockaddr_in6 *daddr)159{160Slirp *slirp = m->slirp;161M_DUP_DEBUG(slirp, m, 0, sizeof(struct ip6) + sizeof(struct udphdr));162163struct ip6 *ip;164struct udphdr *uh;165166DEBUG_CALL("udp6_output");167DEBUG_ARG("so = %p", so);168DEBUG_ARG("m = %p", m);169170/* adjust for header */171m->m_data -= sizeof(struct udphdr);172m->m_len += sizeof(struct udphdr);173uh = mtod(m, struct udphdr *);174m->m_data -= sizeof(struct ip6);175m->m_len += sizeof(struct ip6);176ip = mtod(m, struct ip6 *);177178/* Build IP header */179ip->ip_pl = htons(m->m_len - sizeof(struct ip6));180ip->ip_nh = IPPROTO_UDP;181ip->ip_src = saddr->sin6_addr;182ip->ip_dst = daddr->sin6_addr;183184/* Build UDP header */185uh->uh_sport = saddr->sin6_port;186uh->uh_dport = daddr->sin6_port;187uh->uh_ulen = ip->ip_pl;188uh->uh_sum = 0;189uh->uh_sum = ip6_cksum(m);190if (uh->uh_sum == 0) {191uh->uh_sum = 0xffff;192}193194return ip6_output(so, m, 0);195}196197198