[150717] in North American Network Operators' Group
Re: dns and software, was Re: Reliable Cloud host ?
daemon@ATHENA.MIT.EDU (Owen DeLong)
Thu Mar 1 16:12:50 2012
From: Owen DeLong <owen@delong.com>
In-Reply-To: <201203011522.q21FM74H095011@aurora.sol.net>
Date: Thu, 1 Mar 2012 13:07:31 -0800
To: Joe Greco <jgreco@ns.sol.net>
Cc: Nanog <nanog@nanog.org>
Errors-To: nanog-bounces+nanog.discuss=bloom-picayune.mit.edu@nanog.org
>=20
> It's deeper than just that, though. The whole paradigm is messy, from
> the point of view of someone who just wants to get stuff done. The
> examples are (almost?) all fatally flawed. The code that actually =
gets
> at least some of it right ends up being too complex and too hard for
> people to understand why things are done the way they are.
>=20
> Even in the "old days", before IPv6, geez, look at this:
>=20
> bcopy(host->h_addr_list[n], (char *)&addr->sin_addr.s_addr, =
sizeof(addr->sin_addr.s_addr));
>=20
> That's real comprehensible - and it's essentially the data interface=20=
> between the resolver library and the system's addressing structures
> for syscalls.
>=20
> On one hand, it's "great" that they wanted to abstract the dirty =
details
> of DNS away from users, but I'd say they failed pretty much even at =
that.
>=20
> ... JG
> --=20
> Joe Greco - sol.net Network Services - Milwaukee, WI - =
http://www.sol.net
> "We call it the 'one bite at the apple' rule. Give me one chance [and] =
then I
> won't contact you again." - Direct Marketing Ass'n position on e-mail =
spam(CNN)
> With 24 million small businesses in the US alone, that's way too many =
apples.
I think that the modern set of getaddrinfo and connect is actually not =
that complicated:
/* Hints for getaddrinfo() (tell it what we want) */
memset(&addrinfo, 0, sizeof(addrinfo)); /* Zero out the buffer =
*/
addrinfo.ai_family=3DPF_UNSPEC; /* Any and all =
address families */
addrinfo.ai_socktype=3DSOCK_STREAM; /* Stream Socket */
addrinfo.ai_protocol=3DIPPROTO_TCP; /* TCP */
/* Ask the resolver library for the information. Exit on failure. */
/* argv[1] is the hostname passed in by the user. "demo" is the =
service name */
if (rval =3D getaddrinfo(argv[1], "demo", &addrinfo, &res) !=3D 0) {
fprintf(stderr, "%s: Failed to resolve address information.\n", =
argv[0]);
exit(2);
}
/* Iterate through the results */
for (r=3Dres; r; r =3D r->ai_next) {
/* Create a socket configured for the next candidate */
sockfd6 =3D socket(r->ai_family, r->ai_socktype, r->ai_protocol);
/* Try to connect */
if (connect(sockfd6, r->ai_addr, r->ai_addrlen) < 0)
{
/* Failed to connect */
e_save =3D errno;
/* Destroy socket */
(void) close(sockfd6);
/* Recover the error information */
errno =3D e_save;
/* Tell the user that this attempt failed */
fprintf(stderr, "%s: Failed attempt to %s.\n", argv[0],=20
get_ip_str((struct sockaddr *)r->ai_addr, buf, BUFLEN));
/* Give error details */
perror("Socket error");
} else { /* Success! */
/* Inform the user */
snprintf(s, BUFLEN, "%s: Succeeded to %s.", argv[0],
get_ip_str((struct sockaddr *)r->ai_addr, buf, BUFLEN));
debug(5, argv[0], s);
/* Flag our success */
success++;
/* Stop iterating */
break;
}
}
/* Out of the loop. Either we succeeded or ran out of possibilities */
if (success =3D=3D 0) /* If we ran out of possibilities... */
{
/* Inform the user, free up the resources, and exit */
fprintf(stderr, "%s: Failed to connect to %s.\n", argv[0], argv[1]);
freeaddrinfo(res);
exit(5);
}
/* Succeeded. Inform the user and continue with the application */
printf("%s: Successfully connected to %s at %s on FD %d.\n", argv[0], =
argv[1],
get_ip_str((struct sockaddr *)r->ai_addr, buf, BUFLEN),
sockfd6);
/* Free up the memory held by the resolver results */
freeaddrinfo(res);
It's really hard to make a case that this is all that complex.
I put a lot of extra comments in there to make it clear what's happening =
for people who may not be used to coding in C. It also contains a whole =
lot of extra user notification and debugging instrumentation because it =
is designed as an example people can use to learn with.=20
Yes, this was a lot messier and a lot stranger and harder to get right =
with get*by{name,addr}, but, those days are long gone and anyone still =
coding with those needs to move forward.
Owen