FreeBSD/usr.sbin/traceroute/findsaddr-udp.c
/*
 * Return the source address for the given destination address.
 *
 * This makes use of proper source address selection in the FreeBSD kernel
 * even taking jails into account (sys/netinet/in_pcb.c:in_pcbladdr()).
 * We open a UDP socket, and connect to the destination, letting the kernel
 * do the bind and then read the source IPv4 address using getsockname(2).
 * This has multiple advantages: no need to do PF_ROUTE operations possibly
 * needing special privileges, jails properly taken into account and most
 * important - getting the result the kernel would give us rather than
 * best-guessing ourselves.
 */
Return the source address for the given destination address.
This makes use of proper source address selection in the FreeBSD kernel
even taking jails into account (sys/netinet/in_pcb.c:in_pcbladdr()).
We open a UDP socket, and connect to the destination, letting the kernel
do the bind and then read the source IPv4 address using getsockname(2).
This has multiple advantages: no need to do PF_ROUTE operations possibly
needing special privileges, jails properly taken into account and most
important - getting the result the kernel would give us rather than
best-guessing ourselves.
Return the source address for the given destination address . This makes use of proper source address selection in the FreeBSD kernel even taking jails into account ( sys / netinet / in_pcb . c : in_pcbladdr () ) . We open a UDP socket and connect to the destination letting the kernel do the bind and then read the source IPv4 address using getsockname ( 2 ) . This has multiple advantages : no need to do PF_ROUTE operations possibly needing special privileges jails properly taken into account and most important - getting the result the kernel would give us rather than best - guessing ourselves .
const char *
findsaddr(register const struct sockaddr_in *to,
    register struct sockaddr_in *from)
{
	const char *errstr;
	struct sockaddr_in cto, cfrom;
	int s;
	socklen_t len;
	s = socket(AF_INET, SOCK_DGRAM, 0);
	if (s == -1)
		return ("failed to open DGRAM socket for src addr selection.");
	errstr = NULL;
	len = sizeof(struct sockaddr_in);
	memcpy(&cto, to, len);
	cto.sin_port = htons(65535);	
	if (connect(s, (struct sockaddr *)&cto, len) == -1) {
		errstr = "failed to connect to peer for src addr selection.";
		goto err;
	}
	if (getsockname(s, (struct sockaddr *)&cfrom, &len) == -1) {
		errstr = "failed to get socket name for src addr selection.";
		goto err;
	}
	if (len != sizeof(struct sockaddr_in) || cfrom.sin_family != AF_INET) {
		errstr = "unexpected address family in src addr selection.";
		goto err;
	}
	setsin(from, cfrom.sin_addr.s_addr);
err:
	(void) close(s);
	return (errstr);
}
const char * findsaddr ( register const struct sockaddr_in * to , register struct sockaddr_in * from ) { const char * errstr ; struct sockaddr_in cto , cfrom ; int s ; socklen_t len ; s = socket ( AF_INET , SOCK_DGRAM , 0 ) ; if ( s == -1 ) return ( " " ) ; errstr = NULL ; len = sizeof ( struct sockaddr_in ) ; memcpy ( & cto , to , len ) ; cto . sin_port = htons ( 65535 ) ; if ( connect ( s , ( struct sockaddr * ) & cto , len ) == -1 ) { errstr = " " ; goto err ; } if ( getsockname ( s , ( struct sockaddr * ) & cfrom , & len ) == -1 ) { errstr = " " ; goto err ; } if ( len != sizeof ( struct sockaddr_in ) || cfrom . sin_family != AF_INET ) { errstr = " " ; goto err ; } setsin ( from , cfrom . sin_addr . s_addr ) ; err : ( void ) close ( s ) ; return ( errstr ) ; }
Return the source address for the given destination address.
Return the source address for the given destination address .
/* Dummy port for connect(2). */ /* Update source address for traceroute. */ /* No error (string) to return. */