Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/udp6.c
2 views
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
* Copyright (c) 2013
4
* Guillaume Subiron
5
*/
6
7
#include "slirp.h"
8
#include "udp.h"
9
#include "dhcpv6.h"
10
11
void udp6_input(struct mbuf *m)
12
{
13
Slirp *slirp = m->slirp;
14
M_DUP_DEBUG(slirp, m, 0, 0);
15
16
struct ip6 *ip, save_ip;
17
struct udphdr *uh;
18
int iphlen = sizeof(struct ip6);
19
int len;
20
struct socket *so;
21
struct sockaddr_in6 lhost;
22
int hop_limit;
23
24
DEBUG_CALL("udp6_input");
25
DEBUG_ARG("m = %p", m);
26
27
if (slirp->restricted) {
28
goto bad;
29
}
30
31
ip = mtod(m, struct ip6 *);
32
m->m_len -= iphlen;
33
m->m_data += iphlen;
34
uh = mtod_check(m, sizeof(struct udphdr));
35
if (uh == NULL) {
36
goto bad;
37
}
38
m->m_len += iphlen;
39
m->m_data -= iphlen;
40
41
if (ip6_cksum(m)) {
42
goto bad;
43
}
44
45
len = ntohs((uint16_t)uh->uh_ulen);
46
47
/*
48
* Make mbuf data length reflect UDP length.
49
* If not enough data to reflect UDP length, drop.
50
*/
51
if (ntohs(ip->ip_pl) != len) {
52
if (len > ntohs(ip->ip_pl)) {
53
goto bad;
54
}
55
m_adj(m, len - ntohs(ip->ip_pl));
56
ip->ip_pl = htons(len);
57
}
58
59
/*
60
* Save a copy of the IP header in case we want restore it
61
* for sending an ICMP error message in response.
62
*/
63
save_ip = *ip;
64
65
/* Locate pcb for datagram. */
66
lhost.sin6_family = AF_INET6;
67
lhost.sin6_addr = ip->ip_src;
68
lhost.sin6_port = uh->uh_sport;
69
70
/* handle DHCPv6 */
71
if (ntohs(uh->uh_dport) == DHCPV6_SERVER_PORT &&
72
(in6_equal(&ip->ip_dst, &slirp->vhost_addr6) ||
73
in6_dhcp_multicast(&ip->ip_dst))) {
74
m->m_data += iphlen;
75
m->m_len -= iphlen;
76
dhcpv6_input(&lhost, m);
77
m->m_data -= iphlen;
78
m->m_len += iphlen;
79
goto bad;
80
}
81
82
/* handle TFTP */
83
if (ntohs(uh->uh_dport) == TFTP_SERVER &&
84
!memcmp(ip->ip_dst.s6_addr, slirp->vhost_addr6.s6_addr, 16)) {
85
m->m_data += iphlen;
86
m->m_len -= iphlen;
87
tftp_input((struct sockaddr_storage *)&lhost, m);
88
m->m_data -= iphlen;
89
m->m_len += iphlen;
90
goto bad;
91
}
92
93
so = solookup(&slirp->udp_last_so, &slirp->udb,
94
(struct sockaddr_storage *)&lhost, NULL);
95
96
if (so == NULL) {
97
/* If there's no socket for this packet, create one. */
98
so = socreate(slirp, IPPROTO_UDP);
99
if (udp_attach(so, AF_INET6) == -1) {
100
DEBUG_MISC(" udp6_attach errno = %d-%s", errno, strerror(errno));
101
sofree(so);
102
goto bad;
103
}
104
105
/* Setup fields */
106
so->so_lfamily = AF_INET6;
107
so->so_laddr6 = ip->ip_src;
108
so->so_lport6 = uh->uh_sport;
109
}
110
111
so->so_ffamily = AF_INET6;
112
so->so_faddr6 = ip->ip_dst; /* XXX */
113
so->so_fport6 = uh->uh_dport; /* XXX */
114
115
iphlen += sizeof(struct udphdr);
116
m->m_len -= iphlen;
117
m->m_data += iphlen;
118
119
/*
120
* Check for TTL
121
*/
122
hop_limit = save_ip.ip_hl-1;
123
if (hop_limit <= 0) {
124
m->m_len += iphlen;
125
m->m_data -= iphlen;
126
*ip = save_ip;
127
DEBUG_MISC("udp ttl exceeded");
128
icmp6_send_error(m, ICMP6_TIMXCEED, ICMP6_TIMXCEED_INTRANS);
129
goto bad;
130
}
131
setsockopt(so->s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hop_limit, sizeof(hop_limit));
132
133
/*
134
* Now we sendto() the packet.
135
*/
136
if (sosendto(so, m) == -1) {
137
m->m_len += iphlen;
138
m->m_data -= iphlen;
139
*ip = save_ip;
140
DEBUG_MISC("udp tx errno = %d-%s", errno, strerror(errno));
141
icmp6_send_error(m, ICMP6_UNREACH, ICMP6_UNREACH_NO_ROUTE);
142
goto bad;
143
}
144
145
m_free(so->so_m); /* used for ICMP if error on sorecvfrom */
146
147
/* restore the orig mbuf packet */
148
m->m_len += iphlen;
149
m->m_data -= iphlen;
150
*ip = save_ip;
151
so->so_m = m;
152
153
return;
154
bad:
155
m_free(m);
156
}
157
158
int udp6_output(struct socket *so, struct mbuf *m, struct sockaddr_in6 *saddr,
159
struct sockaddr_in6 *daddr)
160
{
161
Slirp *slirp = m->slirp;
162
M_DUP_DEBUG(slirp, m, 0, sizeof(struct ip6) + sizeof(struct udphdr));
163
164
struct ip6 *ip;
165
struct udphdr *uh;
166
167
DEBUG_CALL("udp6_output");
168
DEBUG_ARG("so = %p", so);
169
DEBUG_ARG("m = %p", m);
170
171
/* adjust for header */
172
m->m_data -= sizeof(struct udphdr);
173
m->m_len += sizeof(struct udphdr);
174
uh = mtod(m, struct udphdr *);
175
m->m_data -= sizeof(struct ip6);
176
m->m_len += sizeof(struct ip6);
177
ip = mtod(m, struct ip6 *);
178
179
/* Build IP header */
180
ip->ip_pl = htons(m->m_len - sizeof(struct ip6));
181
ip->ip_nh = IPPROTO_UDP;
182
ip->ip_src = saddr->sin6_addr;
183
ip->ip_dst = daddr->sin6_addr;
184
185
/* Build UDP header */
186
uh->uh_sport = saddr->sin6_port;
187
uh->uh_dport = daddr->sin6_port;
188
uh->uh_ulen = ip->ip_pl;
189
uh->uh_sum = 0;
190
uh->uh_sum = ip6_cksum(m);
191
if (uh->uh_sum == 0) {
192
uh->uh_sum = 0xffff;
193
}
194
195
return ip6_output(so, m, 0);
196
}
197
198