VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/udp.c@ 103068

Last change on this file since 103068 was 98103, checked in by vboxsync, 21 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.3 KB
RevLine 
[28449]1/* $Id: udp.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * NAT - UDP protocol.
4 */
5
[1]6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[28449]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[28449]26 */
27
28/*
29 * This code is based on:
30 *
[1]31 * Copyright (c) 1982, 1986, 1988, 1990, 1993
[14470]32 * The Regents of the University of California. All rights reserved.
[1]33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
[95573]42 * 3. Neither the name of the University nor the names of its contributors
[1]43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
[14470]58 * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
[1]59 * udp_usrreq.c,v 1.4 1994/10/02 17:48:45 phk Exp
60 */
61
62/*
63 * Changes and additions relating to SLiRP
64 * Copyright (c) 1995 Danny Gasparovski.
[1010]65 *
66 * Please read the file COPYRIGHT for the
[1]67 * terms and conditions of the copyright.
68 */
69
70#include <slirp.h>
71#include "ip_icmp.h"
72
73
74/*
75 * UDP protocol implementation.
76 * Per RFC 768, August, 1980.
77 */
[1033]78#define udpcksum 1
[1]79
80void
[1033]81udp_init(PNATState pData)
[1]82{
[15293]83 udp_last_so = &udb;
84 udb.so_next = udb.so_prev = &udb;
[1]85}
[1076]86
[1010]87/* m->m_data points at ip packet header
88 * m->m_len length ip packet
[1]89 * ip->ip_len length data (IPDU)
90 */
91void
[1033]92udp_input(PNATState pData, register struct mbuf *m, int iphlen)
[1]93{
[15293]94 register struct ip *ip;
95 register struct udphdr *uh;
96 int len;
97 struct ip save_ip;
98 struct socket *so;
[15443]99 int ret;
[52256]100 int ttl, tos;
[1010]101
[37936]102 LogFlowFunc(("ENTER: m = %p, iphlen = %d\n", m, iphlen));
[20164]103 ip = mtod(m, struct ip *);
[37746]104 Log2(("%RTnaipv4 iphlen = %d\n", ip->ip_dst, iphlen));
[1010]105
[15293]106 udpstat.udps_ipackets++;
[1]107
[15293]108 /*
109 * Strip IP options, if any; should skip this,
110 * make available to user, and use on returned packets,
111 * but we don't yet have a way to check the checksum
112 * with options still present.
113 */
114 if (iphlen > sizeof(struct ip))
115 {
116 ip_stripoptions(m, (struct mbuf *)0);
117 iphlen = sizeof(struct ip);
118 }
[1]119
[15293]120 /*
121 * Get IP and UDP header together in first mbuf.
122 */
123 ip = mtod(m, struct ip *);
124 uh = (struct udphdr *)((caddr_t)ip + iphlen);
[1]125
[15293]126 /*
127 * Make mbuf data length reflect UDP length.
128 * If not enough data to reflect UDP length, drop.
129 */
[25822]130 len = RT_N2H_U16((u_int16_t)uh->uh_ulen);
[63016]131 Assert(ip->ip_len + iphlen == (ssize_t)m_length(m, NULL));
[1]132
[15293]133 if (ip->ip_len != len)
134 {
135 if (len > ip->ip_len)
136 {
137 udpstat.udps_badlen++;
[22976]138 Log3(("NAT: IP(id: %hd) has bad size\n", ip->ip_id));
[46608]139 goto bad_free_mbuf;
[14470]140 }
[15293]141 m_adj(m, len - ip->ip_len);
142 ip->ip_len = len;
143 }
[1010]144
[15293]145 /*
146 * Save a copy of the IP header in case we want restore it
147 * for sending an ICMP error message in response.
148 */
149 save_ip = *ip;
150 save_ip.ip_len+= iphlen; /* tcp_input subtracts this */
[1]151
[15293]152 /*
153 * Checksum extended UDP header and data.
154 */
155 if (udpcksum && uh->uh_sum)
156 {
157 memset(((struct ipovly *)ip)->ih_x1, 0, 9);
158 ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
159#if 0
160 /* keep uh_sum for ICMP reply */
161 uh->uh_sum = cksum(m, len + sizeof (struct ip));
162 if (uh->uh_sum)
163 {
[15355]164
[15293]165#endif
[30352]166 if (cksum(m, len + iphlen))
[15293]167 {
168 udpstat.udps_badsum++;
[22976]169 Log3(("NAT: IP(id: %hd) has bad (udp) cksum\n", ip->ip_id));
[30352]170 goto bad_free_mbuf;
[15293]171 }
[14470]172 }
[15293]173#if 0
174 }
175#endif
[1]176
[15293]177 /*
178 * handle DHCP/BOOTP
179 */
[25822]180 if (uh->uh_dport == RT_H2N_U16_C(BOOTP_SERVER))
[15293]181 {
182 bootp_input(pData, m);
[30352]183 goto done_free_mbuf;
[15293]184 }
185
[59034]186 LogFunc(("uh src: %RTnaipv4:%d, dst: %RTnaipv4:%d\n",
187 ip->ip_src.s_addr, RT_N2H_U16(uh->uh_sport),
188 ip->ip_dst.s_addr, RT_N2H_U16(uh->uh_dport)));
189
[59063]190 /*
191 * handle DNS host resolver without creating a socket
192 */
[28365]193 if ( pData->fUseHostResolver
[25822]194 && uh->uh_dport == RT_H2N_U16_C(53)
[40283]195 && CTL_CHECK(ip->ip_dst.s_addr, CTL_DNS))
[22843]196 {
197 struct sockaddr_in dst, src;
[59063]198
[22843]199 src.sin_addr.s_addr = ip->ip_dst.s_addr;
200 src.sin_port = uh->uh_dport;
201 dst.sin_addr.s_addr = ip->ip_src.s_addr;
202 dst.sin_port = uh->uh_sport;
[23369]203
[59063]204 m_adj(m, sizeof(struct udpiphdr));
205
[60142]206 m = hostresolver(pData, m, ip->ip_src.s_addr, uh->uh_sport);
[59143]207 if (m == NULL)
[59063]208 goto done_free_mbuf;
209
[36901]210 slirpMbufTagService(pData, m, CTL_DNS);
[59063]211
[22843]212 udp_output2(pData, NULL, m, &src, &dst, IPTOS_LOWDELAY);
[37936]213 LogFlowFuncLeave();
[30350]214 return;
[22843]215 }
[59034]216
[15293]217 /*
218 * handle TFTP
219 */
[25822]220 if ( uh->uh_dport == RT_H2N_U16_C(TFTP_SERVER)
[40283]221 && CTL_CHECK(ip->ip_dst.s_addr, CTL_TFTP))
[15293]222 {
[41987]223 if (pData->pvTftpSessions)
224 slirpTftpInput(pData, m);
[30352]225 goto done_free_mbuf;
[15293]226 }
227
228 /*
[55003]229 * XXX: DNS proxy currently relies on the fact that each socket
230 * only serves one request.
231 */
232 if ( pData->fUseDnsProxy
233 && CTL_CHECK(ip->ip_dst.s_addr, CTL_DNS)
234 && (uh->uh_dport == RT_H2N_U16_C(53)))
235 {
236 so = NULL;
237 goto new_socket;
238 }
239
240 /*
[92093]241 * Drop UDP packets destind for CTL_ALIAS (i.e. the hosts loopback interface)
242 * if it is disabled.
243 */
244 if ( CTL_CHECK(ip->ip_dst.s_addr, CTL_ALIAS)
245 && !pData->fLocalhostReachable)
246 goto done_free_mbuf;
247
248 /*
[15293]249 * Locate pcb for datagram.
250 */
251 so = udp_last_so;
252 if ( so->so_lport != uh->uh_sport
253 || so->so_laddr.s_addr != ip->ip_src.s_addr)
254 {
255 struct socket *tmp;
256
257 for (tmp = udb.so_next; tmp != &udb; tmp = tmp->so_next)
258 {
259 if ( tmp->so_lport == uh->uh_sport
260 && tmp->so_laddr.s_addr == ip->ip_src.s_addr)
261 {
262 so = tmp;
263 break;
264 }
[1]265 }
[15293]266 if (tmp == &udb)
267 so = NULL;
268 else
269 {
270 udpstat.udpps_pcbcachemiss++;
271 udp_last_so = so;
272 }
273 }
[1]274
[55003]275 new_socket:
[15293]276 if (so == NULL)
277 {
[1]278 /*
[15293]279 * If there's no socket for this packet,
280 * create one
[1]281 */
[15293]282 if ((so = socreate()) == NULL)
[22976]283 {
[28522]284 Log2(("NAT: IP(id: %hd) failed to create socket\n", ip->ip_id));
[30352]285 goto bad_free_mbuf;
[22976]286 }
[71982]287
288 /*
289 * Setup fields
290 */
291 so->so_laddr = ip->ip_src;
292 so->so_lport = uh->uh_sport;
293 so->so_iptos = ip->ip_tos;
294
[39894]295 if (udp_attach(pData, so) <= 0)
[15293]296 {
[34103]297 Log2(("NAT: IP(id: %hd) udp_attach errno = %d (%s)\n",
[22976]298 ip->ip_id, errno, strerror(errno)));
[1033]299 sofree(pData, so);
[30352]300 goto bad_free_mbuf;
[15293]301 }
[1010]302
[15293]303 /* udp_last_so = so; */
[14470]304 /*
[15293]305 * XXXXX Here, check if it's in udpexec_list,
306 * and if it is, do the fork_exec() etc.
[14470]307 */
[15293]308 }
[1]309
[15293]310 so->so_faddr = ip->ip_dst; /* XXX */
311 so->so_fport = uh->uh_dport; /* XXX */
[40583]312 Assert(so->so_type == IPPROTO_UDP);
[1]313
[20959]314 /*
315 * DNS proxy
316 */
[28365]317 if ( pData->fUseDnsProxy
[45322]318 && CTL_CHECK(ip->ip_dst.s_addr, CTL_DNS)
[25822]319 && (uh->uh_dport == RT_H2N_U16_C(53)))
[17302]320 {
321 dnsproxy_query(pData, so, m, iphlen);
[30352]322 goto done_free_mbuf;
[17302]323 }
324
[15293]325 iphlen += sizeof(struct udphdr);
326 m->m_len -= iphlen;
327 m->m_data += iphlen;
[1]328
[15443]329 ttl = ip->ip_ttl = save_ip.ip_ttl;
[52256]330 if (ttl != so->so_sottl) {
331 ret = setsockopt(so->s, IPPROTO_IP, IP_TTL,
332 (char *)&ttl, sizeof(ttl));
333 if (RT_LIKELY(ret == 0))
334 so->so_sottl = ttl;
335 }
[15636]336
[52256]337 tos = save_ip.ip_tos;
338 if (tos != so->so_sotos) {
339 ret = setsockopt(so->s, IPPROTO_IP, IP_TOS,
340 (char *)&tos, sizeof(tos));
341 if (RT_LIKELY(ret == 0))
342 so->so_sotos = tos;
343 }
344
345 {
346 /*
347 * Different OSes have different socket options for DF. We
348 * can't use IP_HDRINCL here as it's only valid for SOCK_RAW.
349 */
[63013]350# define USE_DF_OPTION(_Optname) \
351 const int dfopt = _Optname
[52256]352#if defined(IP_MTU_DISCOVER)
353 USE_DF_OPTION(IP_MTU_DISCOVER);
354#elif defined(IP_DONTFRAG) /* Solaris 11+, FreeBSD */
355 USE_DF_OPTION(IP_DONTFRAG);
356#elif defined(IP_DONTFRAGMENT) /* Windows */
357 USE_DF_OPTION(IP_DONTFRAGMENT);
358#else
359 USE_DF_OPTION(0);
360#endif
361 if (dfopt) {
362 int df = (save_ip.ip_off & IP_DF) != 0;
363#if defined(IP_MTU_DISCOVER)
364 df = df ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
365#endif
366 if (df != so->so_sodf) {
367 ret = setsockopt(so->s, IPPROTO_IP, dfopt,
368 (char *)&df, sizeof(df));
369 if (RT_LIKELY(ret == 0))
370 so->so_sodf = df;
371 }
372 }
373 }
374
[41817]375 if ( sosendto(pData, so, m) == -1
[41856]376 && ( !soIgnorableErrorCode(errno)
[41817]377 && errno != ENOTCONN))
[15293]378 {
[14470]379 m->m_len += iphlen;
380 m->m_data -= iphlen;
[15293]381 *ip = save_ip;
[37746]382 Log2(("NAT: UDP tx errno = %d (%s) on sent to %RTnaipv4\n",
383 errno, strerror(errno), ip->ip_dst));
[69426]384 icmp_error(pData, m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
[23369]385 so->so_m = NULL;
[37936]386 LogFlowFuncLeave();
[35859]387 return;
[15293]388 }
[1]389
[23154]390 if (so->so_m)
[28443]391 m_freem(pData, so->so_m); /* used for ICMP if error on sorecvfrom */
[15293]392
393 /* restore the orig mbuf packet */
394 m->m_len += iphlen;
395 m->m_data -= iphlen;
396 *ip = save_ip;
397 so->so_m = m; /* ICMP backup */
[37936]398 LogFlowFuncLeave();
[15293]399 return;
400
[30352]401bad_free_mbuf:
[37746]402 Log2(("NAT: UDP(id: %hd) datagram to %RTnaipv4 with size(%d) claimed as bad\n",
[22974]403 ip->ip_id, &ip->ip_dst, ip->ip_len));
[30352]404
405done_free_mbuf:
[22971]406 /* some services like bootp(built-in), dns(buildt-in) and dhcp don't need sockets
[23369]407 * and create new m'buffers to send them to guest, so we'll free their incomming
408 * buffers here.
[22971]409 */
[59143]410 if (m != NULL)
411 m_freem(pData, m);
[37936]412 LogFlowFuncLeave();
[15293]413 return;
[1]414}
415
[30352]416/**
[30363]417 * Output a UDP packet.
418 *
419 * @note This function will finally free m!
[30352]420 */
[1033]421int udp_output2(PNATState pData, struct socket *so, struct mbuf *m,
422 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
423 int iptos)
[1]424{
[15293]425 register struct udpiphdr *ui;
[30363]426 int error;
[34034]427 int mlen = 0;
[1]428
[39174]429 LogFlowFunc(("ENTER: so = %R[natsock], m = %p, saddr = %RTnaipv4, daddr = %RTnaipv4\n",
430 so, m, saddr->sin_addr.s_addr, daddr->sin_addr.s_addr));
[1]431
[40583]432 /* in case of built-in service so might be NULL */
433 if (so) Assert(so->so_type == IPPROTO_UDP);
434
[15293]435 /*
436 * Adjust for header
437 */
438 m->m_data -= sizeof(struct udpiphdr);
439 m->m_len += sizeof(struct udpiphdr);
[34034]440 mlen = m_length(m, NULL);
[1010]441
[15293]442 /*
443 * Fill in mbuf with extended UDP header
444 * and addresses and length put into network format.
445 */
446 ui = mtod(m, struct udpiphdr *);
447 memset(ui->ui_x1, 0, 9);
448 ui->ui_pr = IPPROTO_UDP;
[63013]449 ui->ui_len = RT_H2N_U16((uint16_t)(mlen - sizeof(struct ip)));
[15293]450 /* XXXXX Check for from-one-location sockets, or from-any-location sockets */
451 ui->ui_src = saddr->sin_addr;
452 ui->ui_dst = daddr->sin_addr;
453 ui->ui_sport = saddr->sin_port;
454 ui->ui_dport = daddr->sin_port;
455 ui->ui_ulen = ui->ui_len;
[1]456
[15293]457 /*
458 * Stuff checksum and output datagram.
459 */
460 ui->ui_sum = 0;
461 if (udpcksum)
462 {
[34034]463 if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ mlen)) == 0)
[15293]464 ui->ui_sum = 0xffff;
465 }
[34034]466 ((struct ip *)ui)->ip_len = mlen;
[15293]467 ((struct ip *)ui)->ip_ttl = ip_defttl;
468 ((struct ip *)ui)->ip_tos = iptos;
[1]469
[15293]470 udpstat.udps_opackets++;
[1010]471
[15293]472 error = ip_output(pData, so, m);
[1010]473
[15293]474 return error;
[1]475}
476
[30363]477/**
478 * @note This function will free m!
479 */
[1033]480int udp_output(PNATState pData, struct socket *so, struct mbuf *m,
481 struct sockaddr_in *addr)
[1]482{
483 struct sockaddr_in saddr, daddr;
[71945]484
[40583]485 Assert(so->so_type == IPPROTO_UDP);
[63016]486 LogFlowFunc(("ENTER: so = %R[natsock], m = %p, saddr = %RTnaipv4\n", so, m, addr->sin_addr.s_addr));
[1]487
[57784]488 if (so->so_laddr.s_addr == INADDR_ANY)
489 {
490 if (pData->guest_addr_guess.s_addr != INADDR_ANY)
491 {
492 LogRel2(("NAT: port-forward: using %RTnaipv4 for %R[natsock]\n",
493 pData->guest_addr_guess.s_addr, so));
494 so->so_laddr = pData->guest_addr_guess;
495 }
496 else
497 {
498 LogRel2(("NAT: port-forward: guest address unknown for %R[natsock]\n", so));
499 m_freem(pData, m);
500 return 0;
501 }
502 }
503
[1]504 saddr = *addr;
[25822]505 if ((so->so_faddr.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr)
[15293]506 {
[1]507 saddr.sin_addr.s_addr = so->so_faddr.s_addr;
[39287]508 if (slirpIsWideCasting(pData, so->so_faddr.s_addr))
[39174]509 {
[39259]510 /**
511 * We haven't got real firewall but have got its submodule libalias.
512 */
513 m->m_flags |= M_SKIP_FIREWALL;
514 /**
[40283]515 * udp/137 port is Name Service in NetBIOS protocol. for some reasons Windows guest rejects
[39259]516 * accept data from non-aliased server.
517 */
518 if ( (so->so_fport == so->so_lport)
519 && (so->so_fport == RT_H2N_U16(137)))
520 saddr.sin_addr.s_addr = alias_addr.s_addr;
521 else
522 saddr.sin_addr.s_addr = addr->sin_addr.s_addr;
[39174]523 so->so_faddr.s_addr = addr->sin_addr.s_addr;
524 }
[1]525 }
[15293]526
[5723]527 /* Any UDP packet to the loopback address must be translated to be from
528 * the forwarding address, i.e. 10.0.2.2. */
[25822]529 if ( (saddr.sin_addr.s_addr & RT_H2N_U32_C(IN_CLASSA_NET))
530 == RT_H2N_U32_C(INADDR_LOOPBACK & IN_CLASSA_NET))
[5723]531 saddr.sin_addr.s_addr = alias_addr.s_addr;
532
[1]533 daddr.sin_addr = so->so_laddr;
534 daddr.sin_port = so->so_lport;
[1010]535
[13984]536 return udp_output2(pData, so, m, &saddr, &daddr, so->so_iptos);
[1]537}
538
539int
[39894]540udp_attach(PNATState pData, struct socket *so)
[1]541{
[15355]542 struct sockaddr sa_addr;
543 socklen_t socklen = sizeof(struct sockaddr);
544 int status;
[21663]545 int opt = 1;
[1010]546
[72274]547 AssertReturn(so->so_type == 0, -1);
548 so->so_type = IPPROTO_UDP;
549
[72276]550 so->s = socket(AF_INET, SOCK_DGRAM, 0);
551 if (so->s == -1)
[21663]552 goto error;
[72276]553 fd_nonblock(so->s);
554
[52256]555 so->so_sottl = 0;
556 so->so_sotos = 0;
557 so->so_sodf = -1;
[71982]558
559 status = sobind(pData, so);
560 if (status != 0)
561 return status;
562
[21663]563 /* success, insert in queue */
564 so->so_expire = curtime + SO_EXPIRE;
[72276]565
[21663]566 /* enable broadcast for later use */
567 setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
[72276]568
[21663]569 status = getsockname(so->s, &sa_addr, &socklen);
[72278]570 if (status == 0)
571 {
572 Assert(sa_addr.sa_family == AF_INET);
573 so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
574 so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
575 }
[39299]576
[21663]577 SOCKET_LOCK_CREATE(so);
578 QSOCKET_LOCK(udb);
579 insque(pData, so, &udb);
580 NSOCK_INC();
581 QSOCKET_UNLOCK(udb);
[15293]582 return so->s;
[21663]583error:
[72276]584 Log2(("NAT: can't create datagram socket\n"));
[21663]585 return -1;
[1]586}
587
588void
[1033]589udp_detach(PNATState pData, struct socket *so)
[1]590{
[15293]591 if (so != &pData->icmp_socket)
592 {
[40583]593 Assert(so->so_type == IPPROTO_UDP);
[16448]594 QSOCKET_LOCK(udb);
595 SOCKET_LOCK(so);
596 QSOCKET_UNLOCK(udb);
[15191]597 closesocket(so->s);
598 sofree(pData, so);
[16449]599 SOCKET_UNLOCK(so);
[15293]600 }
[1]601}
602
603struct socket *
[21004]604udp_listen(PNATState pData, u_int32_t bind_addr, u_int port, u_int32_t laddr, u_int lport, int flags)
[1]605{
[15293]606 struct sockaddr_in addr;
607 struct socket *so;
608 socklen_t addrlen = sizeof(struct sockaddr_in);
609 int opt = 1;
[38345]610 LogFlowFunc(("ENTER: bind_addr:%RTnaipv4, port:%d, laddr:%RTnaipv4, lport:%d, flags:%x\n",
611 bind_addr, RT_N2H_U16(port), laddr, RT_N2H_U16(lport), flags));
[1010]612
[15293]613 if ((so = socreate()) == NULL)
[38345]614 {
615 LogFlowFunc(("LEAVE: NULL\n"));
[15293]616 return NULL;
[38345]617 }
[15450]618
[17191]619 so->s = socket(AF_INET, SOCK_DGRAM, 0);
[16946]620 if (so->s == -1)
[16938]621 {
[16946]622 LogRel(("NAT: can't create datagram socket\n"));
[16938]623 RTMemFree(so);
[38345]624 LogFlowFunc(("LEAVE: NULL\n"));
[16938]625 return NULL;
626 }
[15293]627 so->so_expire = curtime + SO_EXPIRE;
[40583]628 so->so_type = IPPROTO_UDP;
[16938]629 fd_nonblock(so->s);
[52256]630 so->so_sottl = 0;
631 so->so_sotos = 0;
632 so->so_sodf = -1;
[16443]633 SOCKET_LOCK_CREATE(so);
634 QSOCKET_LOCK(udb);
[25747]635 insque(pData, so, &udb);
[16562]636 NSOCK_INC();
[16443]637 QSOCKET_UNLOCK(udb);
[1]638
[21049]639 memset(&addr, 0, sizeof(addr));
640#ifdef RT_OS_DARWIN
641 addr.sin_len = sizeof(addr);
642#endif
[15293]643 addr.sin_family = AF_INET;
[21004]644 addr.sin_addr.s_addr = bind_addr;
[15293]645 addr.sin_port = port;
[1]646
[15293]647 if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0)
648 {
[57738]649 LogRel(("NAT: udp bind to %RTnaipv4:%d failed, error %d\n",
650 addr.sin_addr, RT_N2H_U16(port), errno));
[15293]651 udp_detach(pData, so);
[38345]652 LogFlowFunc(("LEAVE: NULL\n"));
[15293]653 return NULL;
654 }
[17191]655 setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR,(char *)&opt, sizeof(int));
656/* setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE,(char *)&opt, sizeof(int)); */
[1010]657
[15293]658 getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
[57449]659 so->so_hladdr = addr.sin_addr;
660 so->so_hlport = addr.sin_port;
661
662 /* XXX: wtf are we setting so_faddr/so_fport here? */
[15293]663 so->so_fport = addr.sin_port;
[61805]664#if 0
[15293]665 /* The original check was completely broken, as the commented out
666 * if statement was always true (INADDR_ANY=0). */
[63562]667 /** @todo vvl - alias_addr should be set (if required)
[40583]668 * later by liabalias module.
669 */
[61805]670 if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
[15293]671 so->so_faddr = alias_addr;
672 else
[61805]673#endif
[15293]674 so->so_faddr = addr.sin_addr;
[1010]675
[15293]676 so->so_lport = lport;
677 so->so_laddr.s_addr = laddr;
678 if (flags != SS_FACCEPTONCE)
679 so->so_expire = 0;
[1010]680
[15293]681 so->so_state = SS_ISFCONNECTED;
[13984]682
[38345]683 LogFlowFunc(("LEAVE: %R[natsock]\n", so));
[15293]684 return so;
[1]685}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette