diff --git a/event/program-agent/program-agent.8 b/event/program-agent/program-agent.8
index d2a07348cc8f3f7b6b8147a2b64ae88313d57dda..a2e543487d484e6e100e585e4302455a76e1d6d1 100644
--- a/event/program-agent/program-agent.8
+++ b/event/program-agent/program-agent.8
@@ -1,6 +1,6 @@
 .\"
 .\" EMULAB-COPYRIGHT
-.\" Copyright (c) 2004, 2005 University of Utah and the Flux Group.
+.\" Copyright (c) 2004, 2005, 2006 University of Utah and the Flux Group.
 .\" All rights reserved.
 .\"
 .TH PROGRAM-AGENT 8 "November 6, 2004" "Emulab" "Emulab Commands Manual"
@@ -221,14 +221,29 @@ The project ID for the experiment this agent is running within.
 .B EID
 The experiment ID for the experiment this agent is running within.
 .TP
-.B NODE
-The name of the node this program agent is running on.  Note that this is the
-short name and
+.B NODECNET
+The fully-qualified name of the node this program agent is running on.
+This name resolves to the IP address of the control network interface
+of the node.
+.TP
+.B NODECNETIP
+The IP address of the control network interface.
+This address should
 .I not
-the fully qualified host name that would refer to the control interface.
+be advertised to, or used by, applications within an experiment as it will
+cause all traffic to flow over the control network rather than the experimental
+network.
+.TP
+.B NODE
+The unqualified name of the node this program agent is running on.
+For nodes with experimental interfaces,
+this name resolves to the IP address of an experimental interface on the node.
+For nodes with more than one experimental interface, there is no guarantee
+which one it will resolve to.
+For nodes with no experimental interfaces, the name will not resolve.
 .TP
 .B NODEIP
-The IP address of the experiment network interface that the node name maps to.
+The IP address of the experiment network interface that NODE resolves to.
 For nodes with no experimental interfaces, this variable will not be set.
 .TP
 set opt(\f(BIVAR\fR) \f(BIvalues\fR
diff --git a/event/program-agent/program-agent.c b/event/program-agent/program-agent.c
index 408c4d8045cd4ddc5ccac407e3d90970ce630ff0..fd3e0250f7ea7f50dfa2f147fbf1186bef9a58eb 100644
--- a/event/program-agent/program-agent.c
+++ b/event/program-agent/program-agent.c
@@ -128,6 +128,12 @@ static char		*pideid;
  */
 static char		*tokenfile;
 
+/**
+ * Non-zero if this is a plab node
+ * XXX hack to allow adjustment of NODE environment variable
+ */
+static int		isplab;
+
 /**
  * Elvin error object.
  */
@@ -433,7 +439,7 @@ main(int argc, char **argv)
 	progname = argv[0];
 	bzero(agentlist, sizeof(agentlist));
 	
-	while ((c = getopt(argc, argv, "hVdrs:p:l:u:i:e:c:k:f:o:v:t:")) != -1){
+	while ((c = getopt(argc, argv, "hVdrs:p:l:u:i:e:c:k:f:o:v:t:P")) != -1){
 		switch (c) {
 		case 'h':
 			usage(progname);
@@ -510,6 +516,9 @@ main(int argc, char **argv)
 			if (strcmp(vnode, "ops") == 0)
 				isops = 1;
 			break;
+		case 'P':
+			isplab = 1;
+			break;
 		default:
 			usage(progname);
 		}
@@ -659,34 +668,82 @@ main(int argc, char **argv)
 	setenv("HOME", pw->pw_dir, 1);
 	setenv("PID", pid, 1);
 	setenv("EID", eid, 1);
+
+	/*
+	 * Find the host's control net name/IP.  This will always be the
+	 * fully qualified name.  Note that if we cannot resolve the FQN
+	 * (which often happens on planetlab nodes) we dig the IP out of
+	 * the Emulab DB info.
+	 */
 	gethostname(buf, sizeof(buf));
-	if ((idx = strchr(buf, '.')) != NULL) {
-	    *idx = '\0';
-	}
-	setenv("NODE", buf, 1);
 	if ((he = gethostbyname(buf)) == NULL) {
 		/* XXX should not be hardwired */
 		char *ipfile = "/var/emulab/boot/myip";
 
-		warning("warning: cannot resolve hostname '%s' to obtain IP address,"
-			" reading IP from %s instead\n", buf, ipfile);
+		warning("WARNING: cannot resolve hostname '%s'"
+			" to obtain IP address, reading IP from %s instead\n",
+			buf, ipfile);
 		fp = fopen(ipfile, "r");
 		if (fp == NULL)
-		    warning("warning: cannot get IP address for hostname '%s',"
-			    " assuming no network links available\n", buf);
+			warning("WARNING: cannot get IP address for hostname '%s',"
+				" assuming no network links available\n", buf);
 		else {
-		    fgets(buf, sizeof(buf), fp);
-		    (void) fclose(fp);
-		    if ((idx = strchr(buf, '\n')) != NULL)
-			*idx = '\0';
-		    setenv("NODEIP", buf, 1);	    
+			char ipbuf[BUFSIZ];
+
+			fgets(ipbuf, sizeof(ipbuf), fp);
+			(void) fclose(fp);
+			if ((idx = strchr(ipbuf, '\n')) != NULL)
+				*idx = '\0';
+			setenv("NODECNETIP", ipbuf, 1);
 		}
 	}
 	else {
 	    struct in_addr ia;
 
 	    memcpy(&ia, he->h_addr, he->h_length);
-	    setenv("NODEIP", inet_ntoa(ia), 1);	    
+	    setenv("NODECNETIP", inet_ntoa(ia), 1);	    
+	}
+
+	/*
+	 * XXX for planetlab, hostname is the official hostname as opposed
+	 * to the per-experiment Emulab alias.  To be consistent, we want
+	 * NODECNET (and hence NODE) to reflect the Emulab name.
+	 */
+	if (isplab) {
+		/* XXX should not be hardwired */
+		char *alfile = "/var/emulab/boot/nickname";
+
+		fp = fopen(alfile, "r");
+		if (fp != NULL) {
+			fgets(buf, sizeof(buf), fp);
+			(void) fclose(fp);
+			if ((idx = strchr(buf, '\n')) != NULL) {
+				*idx++ = '.';
+				strncat(buf, OURDOMAIN,
+					sizeof(buf) - (idx - buf) - 1);
+			}
+			setenv("NODECNET", buf, 1);
+		}
+	} else
+		setenv("NODECNET", buf, 1);
+
+	/*
+	 * Now find "the default" experimental network interface by stripping
+	 * the domain qualifier and looking that up.  If the short name fails
+	 * to resolve, we assume there are no experimental interfaces.
+	 *
+	 * XXX for backwards compat, we always set NODE even if it does not
+	 * resolve.  It might still be useful as a tag.
+	 */
+	if ((idx = strchr(buf, '.')) != NULL) {
+	    *idx = '\0';
+	}
+	setenv("NODE", buf, 1);
+	if ((he = gethostbyname(buf)) != NULL) {
+		struct in_addr ia;
+
+		memcpy(&ia, he->h_addr, he->h_length);
+		setenv("NODEIP", inet_ntoa(ia), 1);	    
 	}
 
 	/* XXX Need to eval the ENV parts of the config file after we've
diff --git a/tmcd/common/config/rc.progagent b/tmcd/common/config/rc.progagent
index ada93d94801a97407955fc892deb08e46a3fba64..e3e189da486ce93bbf52e33fc7a009af556ea7ac 100755
--- a/tmcd/common/config/rc.progagent
+++ b/tmcd/common/config/rc.progagent
@@ -208,7 +208,7 @@ sub doboot()
 		# this failure should not happen
 		fatal("invalid format for plabconfig info");
 	    }
-	    system("$PAGENT -e $pid/$eid -s localhost -l $LOGFILE ".
+	    system("$PAGENT -P -e $pid/$eid -s localhost -l $LOGFILE ".
 		   "-d -i $PIDFILE -k " . TMEVENTKEY() . " -c $CONFIG ".
 		   "-v $vname -r -p $elvind_port -t $TOKEN");
 	}
diff --git a/tmcd/plab/rc.inplab b/tmcd/plab/rc.inplab
index 3b654f1e96b06302ebe1f74aaabaf007132e82b6..962511cb11e5223c44bc64bc61a82327d903c36c 100755
--- a/tmcd/plab/rc.inplab
+++ b/tmcd/plab/rc.inplab
@@ -7,6 +7,9 @@
 use English;
 use Getopt::Std;
 
+# XXX should not be hardwired
+my $ELABDOMAIN = "emulab.net";
+
 #
 # This script is the plab vserver equiv of ../common/rc.bootsetup. It runs
 # inside the vserver and does a limited set of bootstrapping tasks.
@@ -314,16 +317,20 @@ sub doplabconfig()
 	      "}\n\n");
 
 	# Make it look like it's in Emulab domain
-	# XXX This shouldn't be hardcoded
-	print RC "setconfigopt /etc/resolv.conf domain emulab.net\n";
-	print RC "setconfigopt /etc/resolv.conf search emulab.net\n\n";
+	print RC "setconfigopt /etc/resolv.conf domain $ELABDOMAIN\n";
+	print RC "setconfigopt /etc/resolv.conf search $ELABDOMAIN\n\n";
 
 	# XXX make sure we can resolve our own name
 	print RC "if ! ping -c 1 `hostname` >/dev/null 2>&1; then\n".
 	         "    myip=`cat /var/emulab/boot/myip`\n".
 	         "    myhn=`hostname`\n".
 	         "    if [ -n \"\$myip\" -a -n \"\$myhn\" ]; then\n".
-	         "        setconfigopt /etc/hosts \$myip \$myhn\n".
+		 "        myal=\"\"\n".
+	         "        mynn=`cat /var/emulab/boot/nickname`\n".
+	         "        if [ -n \"\$mynn\" ]; then\n".
+		 "            myal=\"\$mynn.$ELABDOMAIN\"\n".
+	         "        fi\n".
+	         "        setconfigopt /etc/hosts \$myip \"\$myhn \$myal\"\n".
 	         "    fi\n".
 		 "fi\n";
 
diff --git a/www/tutorial/eventsystem.html b/www/tutorial/eventsystem.html
index ff39504fceb9a58fb6f9357527ba9ddc54206d37..6c5e94b11efd29455a9b4c6ccae2d2078ba8eda6 100644
--- a/www/tutorial/eventsystem.html
+++ b/www/tutorial/eventsystem.html
@@ -398,18 +398,34 @@ directory containing Emulab specific binaries.</td>
 <td>The experiment ID for the experiment this agent is running within.</td>
 </tr>
 
+<tr>
+<td>NODECNET</td>
+<td>The fully-qualified name of the node this program agent is running on.
+This name resolves to the IP address of the control network interface
+of the node.</td>
+</tr>
+
+<tr>
+<td>NODECNETIP</td>
+<td>The IP address of the control network interface.
+This address should <i>not</i> be advertised to, or used by, applications
+within an experiment as it will cause all traffic to flow over the control
+network rather than the experimental network.
+
 <tr>
 <td>NODE</td>
-<td>The name of the node this program agent is running on.  Note that this is
-the short name and <i>not</i> the fully qualified host name that would refer to
-the control interface.</td>
+<td>The unqualified name of the node this program agent is running on.
+For nodes with experimental interfaces,
+this name resolves to the IP address of an experimental interface on the node.
+For nodes with more than one experimental interface, there is no guarantee
+which one it will resolve to.
+For nodes with no experimental interfaces, the name will not resolve.</td>
 </tr>
 
 <tr>
 <td>NODEIP</td>
-<td>The IP address of the experiment network interface that the node name maps
-to.  For nodes with no experimental interfaces, this variable will not be
-set.</td>
+<td>The IP address of the experiment network interface that NODE resolves to.
+For nodes with no experimental interfaces, this variable will not be set.</td>
 </tr>
 
 <tr>