Re: your mail

Tony Sanders ([email protected])
Fri, 5 May 1995 19:32:32 +0500


> On Thu, 4 May 1995 [email protected] wrote:
> > I am new to this mailing list and am not sure if this
> > has been discussed. But here it goes.
> > Is it possible to have 2 different names resolve to
> > the same server but point to two different home pages.
..
> > If yes, how do I do that. We use DNS and I can setup CNAME aliases
> > for my sun so that x.y.z and a.b.c both point to my sun platform.
Nope -- CNAME won't do it.

Rupesh Kapoor writes:
> That's not how it works. You have to run two different httpd's (with
> different root areas, of course). They would run on diff ports, say one
> on 80 (default) and the other on 2000. URL for the first is
..
> The port number has to be there. Am I missing a point?
Yes, and even worse, you commited the sin of misinformation.

<TITLE>multi-domain hosts (the shocking truth -- long)</TITLE>

<P>I assume what you really want are multiple,
parallel services that appear to be different machines
but are really one machine -- and since I believe
this is of general interest, here is that story.

<P>The most common request for this is from people
that want to setup parallel web servers (e.g.,
http://www.number1.com/ and http://www.number2.com/
on the same machine serving totally independant
information). This information is aimed mainly at
people using a un*x platform.

<P>First, you <B>must</B> be able to configure multiple
network interfaces on the machine with different IP
addresses. Some (un*x) machines can do this with
the <I><A HREF="http://www.bsdi.com/bsdi-man/?ifconfig(8)">ifconfig</A></I>
command using the alias option, for example:<PRE>
ifconfig XX# alias ##.##.##.##</PRE>

<P>On other machines you can use spare SLIP or PPP
interfaces as placeholders for the new IP address,
but one way or another you <B>must</B> have multiple IP
addresses on that machine or else you simply
<B>cannot</B> do it (you cannot do it simply by messing
with DNS). There is nothing special
you need to do with DNS either, you just assign the new IP
address to the name you want to use. The seperation
totally depends on the IP addresses, the names really
have nothing to do with (they are what the user sees
and nothing more -- the machines really don't care much about
them).

<P>Ok, now for some technical bits, (<I>please note
that some details will vary depending on the
implementation of TCP/IP</I>). When an application
<A HREF="http://www.bsdi.com/bsdi-man/?bind(2)">binds</A></I>
to a <B>TCP</B> port it must specify (amongst
other things) the <B>port</B> to which it will
bind (e.g., gopher, ftp, http, except it uses the
port number) and the address (which is often specified
as <B>INADDR_ANY</B> which means that it will
accept packets for all local destinations, that is,
IP addresses on this machine).

<P>This specification is done in a <B>struct sockaddr_in</B>
which looks like: <PRE>
struct sockaddr_in {
u_char sin_len;
u_char sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
}; </PRE>

<P>And the C code to setup the socket goes something like this
(this is just pseudo-code, error checking should be done, etc):<PRE>
int socket_fd;
int on = 1;
struct sockaddr_in sa_in;

socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
(void) setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof on);

/* ... */

/* fill in data for bind */
bzero((char *) &sa_in, sizeof sa_in);
sa_in.sin_family = AF_INET;
sa_in.sin_port = 80; /* shouldn't be hardcoded */
/* At this point, most applications have something like the following:
* sa_in.sin_addr.s_addr = INADDR_ANY;
* and you need to change it to something like: */
{
/* should use gethostbyname() in real code and get
* the argument from the command line */
long int hostaddr1 = inet_addr("1.2.3.4");
sa_in.sin_addr.s_addr = hostaddr1; /* change binding here */
}
bind(socket_fd, (struct sockaddr *)&sa_in, sizeof sa_in);
</PRE>
<P>The reason I've given you the technical details
above is that most existing internet applications
do not provide any way to specify the host to use
in the <B>s_addr</B> field, they just hardcode the
<B>INADDR_ANY</B>
and that does what most people want. So in most
case you will have to go in and modify the code
(in the best possible case you would add an option
that allows you to specify the binding on the command
line or in a configuration file, if not, I think
many people could hardcode in a new binding given the
information above). If that fails, call your local
system admin (but please don't call me).

<P>One really neat thing you can do with this is,
once you get it all working you can run a "default"
server bound to <B>INADDR_ANY</B> (remember, that is the
default address and will accept packets for any
address not bound to some other server) and have it
return a "sorry, temporarily out of service" message
to the client <B>and</B> email the local webmaster
that something has gone wrong! (<I>help me</I>)

<P>Since I am, among other things, the author of
the <A HREF="http://www.bsdi.com/server/doc/plexus.html">Plexus</A>
HTTP server (it's public domain code so don't worry,
this isn't a plug for money) I now must give a
shameless little plug for my server, which supports
this feature of binding to specific addresses in
the standard distribution. And all you have to do
(after you get it installed of course) is to use
the <TT>-h</TT> flag to specify which address to
bind to:<PRE>
plexus -h austin.bsdi.com</PRE>

<P>That's it! Now you have a server bound to the
IP address for austin.bsdi.com on port 80.
You could then run another "default"
server (as mentioned above) just by running <I>plexus</I>
without the <TT>-h</TT> flag, and it will bind to
<B>INADDR_ANY</B> (tada).

In addition to the above quick hack, you could make the server a little
bit smarter and a single server could service multiple IP addrs
-- I leave this as an exercise for the reader.

If you have further questions please contact your local guru and not me.