VirtualBox

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

Last change on this file since 104389 was 98103, checked in by vboxsync, 22 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
Line 
1/* $Id: udp.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * NAT - UDP protocol.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
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
26 */
27
28/*
29 * This code is based on:
30 *
31 * Copyright (c) 1982, 1986, 1988, 1990, 1993
32 * The Regents of the University of California. All rights reserved.
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.
42 * 3. Neither the name of the University nor the names of its contributors
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 *
58 * @(#)udp_usrreq.c 8.4 (Berkeley) 1/21/94
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.
65 *
66 * Please read the file COPYRIGHT for the
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 */
78#define udpcksum 1
79
80void
81udp_init(PNATState pData)
82{
83 udp_last_so = &udb;
84 udb.so_next = udb.so_prev = &udb;
85}
86
87/* m->m_data points at ip packet header
88 * m->m_len length ip packet
89 * ip->ip_len length data (IPDU)
90 */
91void
92udp_input(PNATState pData, register struct mbuf *m, int iphlen)
93{
94 register struct ip *ip;
95 register struct udphdr *uh;
96 int len;
97 struct ip save_ip;
98 struct socket *so;
99 int ret;
100 int ttl, tos;
101
102 LogFlowFunc(("ENTER: m = %p, iphlen = %d\n", m, iphlen));
103 ip = mtod(m, struct ip *);
104 Log2(("%RTnaipv4 iphlen = %d\n", ip->ip_dst, iphlen));
105
106 udpstat.udps_ipackets++;
107
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 }
119
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);
125
126 /*
127 * Make mbuf data length reflect UDP length.
128 * If not enough data to reflect UDP length, drop.
129 */
130 len = RT_N2H_U16((u_int16_t)uh->uh_ulen);
131 Assert(ip->ip_len + iphlen == (ssize_t)m_length(m, NULL));
132
133 if (ip->ip_len != len)
134 {
135 if (len > ip->ip_len)
136 {
137 udpstat.udps_badlen++;
138 Log3(("NAT: IP(id: %hd) has bad size\n", ip->ip_id));
139 goto bad_free_mbuf;
140 }
141 m_adj(m, len - ip->ip_len);
142 ip->ip_len = len;
143 }
144
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 */
151
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 {
164
165#endif
166 if (cksum(m, len + iphlen))
167 {
168 udpstat.udps_badsum++;
169 Log3(("NAT: IP(id: %hd) has bad (udp) cksum\n", ip->ip_id));
170 goto bad_free_mbuf;
171 }
172 }
173#if 0
174 }
175#endif
176
177 /*
178 * handle DHCP/BOOTP
179 */
180 if (uh->uh_dport == RT_H2N_U16_C(BOOTP_SERVER))
181 {
182 bootp_input(pData, m);
183 goto done_free_mbuf;
184 }
185
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
190 /*
191 * handle DNS host resolver without creating a socket
192 */
193 if ( pData->fUseHostResolver
194 && uh->uh_dport == RT_H2N_U16_C(53)
195 && CTL_CHECK(ip->ip_dst.s_addr, CTL_DNS))
196 {
197 struct sockaddr_in dst, src;
198
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;
203
204 m_adj(m, sizeof(struct udpiphdr));
205
206 m = hostresolver(pData, m, ip->ip_src.s_addr, uh->uh_sport);
207 if (m == NULL)
208 goto done_free_mbuf;
209
210 slirpMbufTagService(pData, m, CTL_DNS);
211
212 udp_output2(pData, NULL, m, &src, &dst, IPTOS_LOWDELAY);
213 LogFlowFuncLeave();
214 return;
215 }
216
217 /*
218 * handle TFTP
219 */
220 if ( uh->uh_dport == RT_H2N_U16_C(TFTP_SERVER)
221 && CTL_CHECK(ip->ip_dst.s_addr, CTL_TFTP))
222 {
223 if (pData->pvTftpSessions)
224 slirpTftpInput(pData, m);
225 goto done_free_mbuf;
226 }
227
228 /*
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 /*
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 /*
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 }
265 }
266 if (tmp == &udb)
267 so = NULL;
268 else
269 {
270 udpstat.udpps_pcbcachemiss++;
271 udp_last_so = so;
272 }
273 }
274
275 new_socket:
276 if (so == NULL)
277 {
278 /*
279 * If there's no socket for this packet,
280 * create one
281 */
282 if ((so = socreate()) == NULL)
283 {
284 Log2(("NAT: IP(id: %hd) failed to create socket\n", ip->ip_id));
285 goto bad_free_mbuf;
286 }
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
295 if (udp_attach(pData, so) <= 0)
296 {
297 Log2(("NAT: IP(id: %hd) udp_attach errno = %d (%s)\n",
298 ip->ip_id, errno, strerror(errno)));
299 sofree(pData, so);
300 goto bad_free_mbuf;
301 }
302
303 /* udp_last_so = so; */
304 /*
305 * XXXXX Here, check if it's in udpexec_list,
306 * and if it is, do the fork_exec() etc.
307 */
308 }
309
310 so->so_faddr = ip->ip_dst; /* XXX */
311 so->so_fport = uh->uh_dport; /* XXX */
312 Assert(so->so_type == IPPROTO_UDP);
313
314 /*
315 * DNS proxy
316 */
317 if ( pData->fUseDnsProxy
318 && CTL_CHECK(ip->ip_dst.s_addr, CTL_DNS)
319 && (uh->uh_dport == RT_H2N_U16_C(53)))
320 {
321 dnsproxy_query(pData, so, m, iphlen);
322 goto done_free_mbuf;
323 }
324
325 iphlen += sizeof(struct udphdr);
326 m->m_len -= iphlen;
327 m->m_data += iphlen;
328
329 ttl = ip->ip_ttl = save_ip.ip_ttl;
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 }
336
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 */
350# define USE_DF_OPTION(_Optname) \
351 const int dfopt = _Optname
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
375 if ( sosendto(pData, so, m) == -1
376 && ( !soIgnorableErrorCode(errno)
377 && errno != ENOTCONN))
378 {
379 m->m_len += iphlen;
380 m->m_data -= iphlen;
381 *ip = save_ip;
382 Log2(("NAT: UDP tx errno = %d (%s) on sent to %RTnaipv4\n",
383 errno, strerror(errno), ip->ip_dst));
384 icmp_error(pData, m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno));
385 so->so_m = NULL;
386 LogFlowFuncLeave();
387 return;
388 }
389
390 if (so->so_m)
391 m_freem(pData, so->so_m); /* used for ICMP if error on sorecvfrom */
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 */
398 LogFlowFuncLeave();
399 return;
400
401bad_free_mbuf:
402 Log2(("NAT: UDP(id: %hd) datagram to %RTnaipv4 with size(%d) claimed as bad\n",
403 ip->ip_id, &ip->ip_dst, ip->ip_len));
404
405done_free_mbuf:
406 /* some services like bootp(built-in), dns(buildt-in) and dhcp don't need sockets
407 * and create new m'buffers to send them to guest, so we'll free their incomming
408 * buffers here.
409 */
410 if (m != NULL)
411 m_freem(pData, m);
412 LogFlowFuncLeave();
413 return;
414}
415
416/**
417 * Output a UDP packet.
418 *
419 * @note This function will finally free m!
420 */
421int udp_output2(PNATState pData, struct socket *so, struct mbuf *m,
422 struct sockaddr_in *saddr, struct sockaddr_in *daddr,
423 int iptos)
424{
425 register struct udpiphdr *ui;
426 int error;
427 int mlen = 0;
428
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));
431
432 /* in case of built-in service so might be NULL */
433 if (so) Assert(so->so_type == IPPROTO_UDP);
434
435 /*
436 * Adjust for header
437 */
438 m->m_data -= sizeof(struct udpiphdr);
439 m->m_len += sizeof(struct udpiphdr);
440 mlen = m_length(m, NULL);
441
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;
449 ui->ui_len = RT_H2N_U16((uint16_t)(mlen - sizeof(struct ip)));
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;
456
457 /*
458 * Stuff checksum and output datagram.
459 */
460 ui->ui_sum = 0;
461 if (udpcksum)
462 {
463 if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ mlen)) == 0)
464 ui->ui_sum = 0xffff;
465 }
466 ((struct ip *)ui)->ip_len = mlen;
467 ((struct ip *)ui)->ip_ttl = ip_defttl;
468 ((struct ip *)ui)->ip_tos = iptos;
469
470 udpstat.udps_opackets++;
471
472 error = ip_output(pData, so, m);
473
474 return error;
475}
476
477/**
478 * @note This function will free m!
479 */
480int udp_output(PNATState pData, struct socket *so, struct mbuf *m,
481 struct sockaddr_in *addr)
482{
483 struct sockaddr_in saddr, daddr;
484
485 Assert(so->so_type == IPPROTO_UDP);
486 LogFlowFunc(("ENTER: so = %R[natsock], m = %p, saddr = %RTnaipv4\n", so, m, addr->sin_addr.s_addr));
487
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
504 saddr = *addr;
505 if ((so->so_faddr.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr)
506 {
507 saddr.sin_addr.s_addr = so->so_faddr.s_addr;
508 if (slirpIsWideCasting(pData, so->so_faddr.s_addr))
509 {
510 /**
511 * We haven't got real firewall but have got its submodule libalias.
512 */
513 m->m_flags |= M_SKIP_FIREWALL;
514 /**
515 * udp/137 port is Name Service in NetBIOS protocol. for some reasons Windows guest rejects
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;
523 so->so_faddr.s_addr = addr->sin_addr.s_addr;
524 }
525 }
526
527 /* Any UDP packet to the loopback address must be translated to be from
528 * the forwarding address, i.e. 10.0.2.2. */
529 if ( (saddr.sin_addr.s_addr & RT_H2N_U32_C(IN_CLASSA_NET))
530 == RT_H2N_U32_C(INADDR_LOOPBACK & IN_CLASSA_NET))
531 saddr.sin_addr.s_addr = alias_addr.s_addr;
532
533 daddr.sin_addr = so->so_laddr;
534 daddr.sin_port = so->so_lport;
535
536 return udp_output2(pData, so, m, &saddr, &daddr, so->so_iptos);
537}
538
539int
540udp_attach(PNATState pData, struct socket *so)
541{
542 struct sockaddr sa_addr;
543 socklen_t socklen = sizeof(struct sockaddr);
544 int status;
545 int opt = 1;
546
547 AssertReturn(so->so_type == 0, -1);
548 so->so_type = IPPROTO_UDP;
549
550 so->s = socket(AF_INET, SOCK_DGRAM, 0);
551 if (so->s == -1)
552 goto error;
553 fd_nonblock(so->s);
554
555 so->so_sottl = 0;
556 so->so_sotos = 0;
557 so->so_sodf = -1;
558
559 status = sobind(pData, so);
560 if (status != 0)
561 return status;
562
563 /* success, insert in queue */
564 so->so_expire = curtime + SO_EXPIRE;
565
566 /* enable broadcast for later use */
567 setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
568
569 status = getsockname(so->s, &sa_addr, &socklen);
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 }
576
577 SOCKET_LOCK_CREATE(so);
578 QSOCKET_LOCK(udb);
579 insque(pData, so, &udb);
580 NSOCK_INC();
581 QSOCKET_UNLOCK(udb);
582 return so->s;
583error:
584 Log2(("NAT: can't create datagram socket\n"));
585 return -1;
586}
587
588void
589udp_detach(PNATState pData, struct socket *so)
590{
591 if (so != &pData->icmp_socket)
592 {
593 Assert(so->so_type == IPPROTO_UDP);
594 QSOCKET_LOCK(udb);
595 SOCKET_LOCK(so);
596 QSOCKET_UNLOCK(udb);
597 closesocket(so->s);
598 sofree(pData, so);
599 SOCKET_UNLOCK(so);
600 }
601}
602
603struct socket *
604udp_listen(PNATState pData, u_int32_t bind_addr, u_int port, u_int32_t laddr, u_int lport, int flags)
605{
606 struct sockaddr_in addr;
607 struct socket *so;
608 socklen_t addrlen = sizeof(struct sockaddr_in);
609 int opt = 1;
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));
612
613 if ((so = socreate()) == NULL)
614 {
615 LogFlowFunc(("LEAVE: NULL\n"));
616 return NULL;
617 }
618
619 so->s = socket(AF_INET, SOCK_DGRAM, 0);
620 if (so->s == -1)
621 {
622 LogRel(("NAT: can't create datagram socket\n"));
623 RTMemFree(so);
624 LogFlowFunc(("LEAVE: NULL\n"));
625 return NULL;
626 }
627 so->so_expire = curtime + SO_EXPIRE;
628 so->so_type = IPPROTO_UDP;
629 fd_nonblock(so->s);
630 so->so_sottl = 0;
631 so->so_sotos = 0;
632 so->so_sodf = -1;
633 SOCKET_LOCK_CREATE(so);
634 QSOCKET_LOCK(udb);
635 insque(pData, so, &udb);
636 NSOCK_INC();
637 QSOCKET_UNLOCK(udb);
638
639 memset(&addr, 0, sizeof(addr));
640#ifdef RT_OS_DARWIN
641 addr.sin_len = sizeof(addr);
642#endif
643 addr.sin_family = AF_INET;
644 addr.sin_addr.s_addr = bind_addr;
645 addr.sin_port = port;
646
647 if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0)
648 {
649 LogRel(("NAT: udp bind to %RTnaipv4:%d failed, error %d\n",
650 addr.sin_addr, RT_N2H_U16(port), errno));
651 udp_detach(pData, so);
652 LogFlowFunc(("LEAVE: NULL\n"));
653 return NULL;
654 }
655 setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR,(char *)&opt, sizeof(int));
656/* setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE,(char *)&opt, sizeof(int)); */
657
658 getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
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? */
663 so->so_fport = addr.sin_port;
664#if 0
665 /* The original check was completely broken, as the commented out
666 * if statement was always true (INADDR_ANY=0). */
667 /** @todo vvl - alias_addr should be set (if required)
668 * later by liabalias module.
669 */
670 if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
671 so->so_faddr = alias_addr;
672 else
673#endif
674 so->so_faddr = addr.sin_addr;
675
676 so->so_lport = lport;
677 so->so_laddr.s_addr = laddr;
678 if (flags != SS_FACCEPTONCE)
679 so->so_expire = 0;
680
681 so->so_state = SS_ISFCONNECTED;
682
683 LogFlowFunc(("LEAVE: %R[natsock]\n", so));
684 return so;
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