Lines 238-251
Link Here
|
238 |
anonport = inp->inp_lport == 0 && (nam == NULL || |
238 |
anonport = inp->inp_lport == 0 && (nam == NULL || |
239 |
((struct sockaddr_in *)nam)->sin_port == 0); |
239 |
((struct sockaddr_in *)nam)->sin_port == 0); |
240 |
error = in_pcbbind_setup(inp, nam, &inp->inp_laddr.s_addr, |
240 |
error = in_pcbbind_setup(inp, nam, &inp->inp_laddr.s_addr, |
241 |
&inp->inp_lport, cred); |
241 |
&inp->inp_lport, &inp->inp_locia, cred); |
242 |
if (error) |
242 |
if (error) |
243 |
return (error); |
243 |
return (error); |
244 |
if (in_pcbinshash(inp) != 0) { |
244 |
if (in_pcbinshash(inp) != 0) { |
245 |
inp->inp_laddr.s_addr = INADDR_ANY; |
245 |
inp->inp_laddr.s_addr = INADDR_ANY; |
246 |
inp->inp_lport = 0; |
246 |
inp->inp_lport = 0; |
|
|
247 |
inp->inp_locia = NULL; |
247 |
return (EAGAIN); |
248 |
return (EAGAIN); |
248 |
} |
249 |
} |
|
|
250 |
if (inp->inp_locia != NULL) |
251 |
IFAREF(&inp->inp_locia->ia_ifa); |
249 |
if (anonport) |
252 |
if (anonport) |
250 |
inp->inp_flags |= INP_ANONPORT; |
253 |
inp->inp_flags |= INP_ANONPORT; |
251 |
return (0); |
254 |
return (0); |
Lines 262-273
Link Here
|
262 |
*/ |
265 |
*/ |
263 |
int |
266 |
int |
264 |
in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, |
267 |
in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp, |
265 |
u_short *lportp, struct ucred *cred) |
268 |
u_short *lportp, struct in_ifaddr **iap, struct ucred *cred) |
266 |
{ |
269 |
{ |
267 |
struct socket *so = inp->inp_socket; |
270 |
struct socket *so = inp->inp_socket; |
268 |
unsigned short *lastport; |
271 |
unsigned short *lastport; |
269 |
struct sockaddr_in *sin; |
272 |
struct sockaddr_in *sin; |
270 |
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; |
273 |
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; |
|
|
274 |
struct in_ifaddr *ia = NULL; |
271 |
struct in_addr laddr; |
275 |
struct in_addr laddr; |
272 |
u_short lport = 0; |
276 |
u_short lport = 0; |
273 |
int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); |
277 |
int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); |
Lines 319-325
Link Here
|
319 |
} else if (sin->sin_addr.s_addr != INADDR_ANY) { |
323 |
} else if (sin->sin_addr.s_addr != INADDR_ANY) { |
320 |
sin->sin_port = 0; /* yech... */ |
324 |
sin->sin_port = 0; /* yech... */ |
321 |
bzero(&sin->sin_zero, sizeof(sin->sin_zero)); |
325 |
bzero(&sin->sin_zero, sizeof(sin->sin_zero)); |
322 |
if (ifa_ifwithaddr((struct sockaddr *)sin) == 0) |
326 |
if ((ia = (struct in_ifaddr *)ifa_ifwithaddr( |
|
|
327 |
(struct sockaddr *)sin)) == 0) |
323 |
return (EADDRNOTAVAIL); |
328 |
return (EADDRNOTAVAIL); |
324 |
} |
329 |
} |
325 |
laddr = sin->sin_addr; |
330 |
laddr = sin->sin_addr; |
Lines 478-483
Link Here
|
478 |
return (EINVAL); |
483 |
return (EINVAL); |
479 |
*laddrp = laddr.s_addr; |
484 |
*laddrp = laddr.s_addr; |
480 |
*lportp = lport; |
485 |
*lportp = lport; |
|
|
486 |
if (iap != NULL) |
487 |
*iap = ia; |
481 |
return (0); |
488 |
return (0); |
482 |
} |
489 |
} |
483 |
|
490 |
|
Lines 490-495
Link Here
|
490 |
int |
497 |
int |
491 |
in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred) |
498 |
in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred) |
492 |
{ |
499 |
{ |
|
|
500 |
struct in_ifaddr *locia; |
493 |
u_short lport, fport; |
501 |
u_short lport, fport; |
494 |
in_addr_t laddr, faddr; |
502 |
in_addr_t laddr, faddr; |
495 |
int anonport, error; |
503 |
int anonport, error; |
Lines 501-507
Link Here
|
501 |
laddr = inp->inp_laddr.s_addr; |
509 |
laddr = inp->inp_laddr.s_addr; |
502 |
anonport = (lport == 0); |
510 |
anonport = (lport == 0); |
503 |
error = in_pcbconnect_setup(inp, nam, &laddr, &lport, &faddr, &fport, |
511 |
error = in_pcbconnect_setup(inp, nam, &laddr, &lport, &faddr, &fport, |
504 |
NULL, cred); |
512 |
NULL, &locia, cred); |
505 |
if (error) |
513 |
if (error) |
506 |
return (error); |
514 |
return (error); |
507 |
|
515 |
|
Lines 519-524
Link Here
|
519 |
/* Commit the remaining changes. */ |
527 |
/* Commit the remaining changes. */ |
520 |
inp->inp_lport = lport; |
528 |
inp->inp_lport = lport; |
521 |
inp->inp_laddr.s_addr = laddr; |
529 |
inp->inp_laddr.s_addr = laddr; |
|
|
530 |
inp->inp_locia = locia; |
531 |
if (inp->inp_locia != NULL) |
532 |
IFAREF(&inp->inp_locia->ia_ifa); |
522 |
inp->inp_faddr.s_addr = faddr; |
533 |
inp->inp_faddr.s_addr = faddr; |
523 |
inp->inp_fport = fport; |
534 |
inp->inp_fport = fport; |
524 |
in_pcbrehash(inp); |
535 |
in_pcbrehash(inp); |
Lines 536-542
Link Here
|
536 |
* On entry, *laddrp and *lportp should contain the current local |
547 |
* On entry, *laddrp and *lportp should contain the current local |
537 |
* address and port for the PCB; these are updated to the values |
548 |
* address and port for the PCB; these are updated to the values |
538 |
* that should be placed in inp_laddr and inp_lport to complete |
549 |
* that should be placed in inp_laddr and inp_lport to complete |
539 |
* the connect. |
550 |
* the connect. If iap is not NULL, *iap is set to the interface |
|
|
551 |
* address corresponding to *laddrp, if any, but no new reference |
552 |
* to it has been added. |
540 |
* |
553 |
* |
541 |
* On success, *faddrp and *fportp will be set to the remote address |
554 |
* On success, *faddrp and *fportp will be set to the remote address |
542 |
* and port. These are not updated in the error case. |
555 |
* and port. These are not updated in the error case. |
Lines 549-555
Link Here
|
549 |
int |
562 |
int |
550 |
in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, |
563 |
in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam, |
551 |
in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp, |
564 |
in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp, |
552 |
struct inpcb **oinpp, struct ucred *cred) |
565 |
struct inpcb **oinpp, struct in_ifaddr **iap, struct ucred *cred) |
553 |
{ |
566 |
{ |
554 |
struct sockaddr_in *sin = (struct sockaddr_in *)nam; |
567 |
struct sockaddr_in *sin = (struct sockaddr_in *)nam; |
555 |
struct in_ifaddr *ia; |
568 |
struct in_ifaddr *ia; |
Lines 560-565
Link Here
|
560 |
u_short lport, fport; |
573 |
u_short lport, fport; |
561 |
int error; |
574 |
int error; |
562 |
|
575 |
|
|
|
576 |
ia = NULL; |
563 |
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo); |
577 |
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo); |
564 |
INP_LOCK_ASSERT(inp); |
578 |
INP_LOCK_ASSERT(inp); |
565 |
|
579 |
|
Lines 582-588
Link Here
|
582 |
sa.sin_len = sizeof(sa); |
596 |
sa.sin_len = sizeof(sa); |
583 |
sa.sin_family = AF_INET; |
597 |
sa.sin_family = AF_INET; |
584 |
error = in_pcbbind_setup(inp, (struct sockaddr *)&sa, |
598 |
error = in_pcbbind_setup(inp, (struct sockaddr *)&sa, |
585 |
&laddr.s_addr, &lport, cred); |
599 |
&laddr.s_addr, &lport, &ia, cred); |
586 |
if (error) |
600 |
if (error) |
587 |
return (error); |
601 |
return (error); |
588 |
} |
602 |
} |
Lines 664-670
Link Here
|
664 |
} |
678 |
} |
665 |
if (lport == 0) { |
679 |
if (lport == 0) { |
666 |
error = in_pcbbind_setup(inp, NULL, &laddr.s_addr, &lport, |
680 |
error = in_pcbbind_setup(inp, NULL, &laddr.s_addr, &lport, |
667 |
cred); |
681 |
&ia, cred); |
668 |
if (error) |
682 |
if (error) |
669 |
return (error); |
683 |
return (error); |
670 |
} |
684 |
} |
Lines 672-677
Link Here
|
672 |
*lportp = lport; |
686 |
*lportp = lport; |
673 |
*faddrp = faddr.s_addr; |
687 |
*faddrp = faddr.s_addr; |
674 |
*fportp = fport; |
688 |
*fportp = fport; |
|
|
689 |
if (iap != NULL) |
690 |
*iap = ia; |
675 |
return (0); |
691 |
return (0); |
676 |
} |
692 |
} |
677 |
|
693 |
|
Lines 720-725
Link Here
|
720 |
#endif /*IPSEC*/ |
736 |
#endif /*IPSEC*/ |
721 |
inp->inp_gencnt = ++ipi->ipi_gencnt; |
737 |
inp->inp_gencnt = ++ipi->ipi_gencnt; |
722 |
in_pcbremlists(inp); |
738 |
in_pcbremlists(inp); |
|
|
739 |
if (inp->inp_locia != NULL) |
740 |
IFAFREE(&inp->inp_locia->ia_ifa); |
723 |
if (inp->inp_options) |
741 |
if (inp->inp_options) |
724 |
(void)m_free(inp->inp_options); |
742 |
(void)m_free(inp->inp_options); |
725 |
ip_freemoptions(inp->inp_moptions); |
743 |
ip_freemoptions(inp->inp_moptions); |