bin/89988: [PATCH] bootparamd null host support and whoami fix

John omen-pub at omenlabs.com
Mon Dec 5 19:20:06 GMT 2005


>Number:         89988
>Category:       bin
>Synopsis:       [PATCH] bootparamd null host support and whoami fix
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Dec 05 19:20:02 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     John
>Release:        6.0 Release i386
>Organization:
>Environment:
FreeBSD scale 6.0-RELEASE FreeBSD 6.0-RELEASE #0: Thu Nov  3 09:36:13 UTC 2005     root at x64.samsco.home:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
There are two issues with bootparamd that I ran into trying to
get Solaris Jumpstart working nicely.  One was permitting null 
hostnames.  Certain options are passed to the jumpstart client
using /etc/bootparams file entries like "term=:vt100".  The current 
implementation only makes an exception for the file "dump=..." and 
will not return anything else if it can not be resolved.  I have 
added in a check to return an address of 0.0.0.0 if the length of 
the hostname is zero.

The second issue is a little more significant.  If a router
address is not supplied using the -r option, bootparamd uses the
function get_myaddress(3) to determine the address of the host.
The bootparamd(8) man page states:

     -r router   The default router (a machine or an IP-address).  This
                 defaults to the machine running the server.

The function get_myaddress always returns INADDR_LOOPBACK.  This
qualify as a bug.  Using -r solves this problem, unless you are
running on multiple networks.  The patch attempts to make rpc.bootparamd
more intelligent.  If -r is not supplied, the ip address of the
client is checked against all configured network interfaces on the
host in the function myaddr.  If the client is on a local subnet,
the ip address of the server on that network is returned (if not,
INADDR_LOOPBACK).  This allows for whoami on multiple networks.
>How-To-Repeat:
              
>Fix:
diff -urN bootparamd.orig/bootparamd.c bootparamd/bootparamd.c
--- bootparamd.orig/bootparamd.c	Thu Dec  1 16:06:21 2005
+++ bootparamd/bootparamd.c	Thu Dec  1 16:10:13 2005
@@ -27,7 +27,9 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-extern int debug, dolog;
+#include <netinet/in.h>
+#include <ifaddrs.h>
+extern int debug, dolog, route_set;
 extern unsigned long route_addr;
 extern char *bootpfile;
 
@@ -42,6 +44,7 @@
 
 int getthefile __P((char *, char *, char *, int));
 int checkhost __P((char *, char *, int));
+unsigned long myaddr __P((unsigned long));
 
 bp_whoami_res *
 bootparamproc_whoami_1_svc(whoami, req)
@@ -79,10 +82,15 @@
     getdomainname(domain_name, MAX_MACHINE_NAME);
     res.domain_name = domain_name;
 
-    if (  res.router_address.address_type != IP_ADDR_TYPE ) {
+    if (!route_set) {
+      route_addr = myaddr(haddr);
+    }
+
+    if (  (res.router_address.address_type != IP_ADDR_TYPE) && route_set ) {
       res.router_address.address_type = IP_ADDR_TYPE;
       bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, 4);
     }
+
     if (debug) fprintf(stderr,
 		       "Returning %s   %s    %d.%d.%d.%d\n",
 		       res.client_name,
@@ -139,8 +147,16 @@
       hostname[where - buffer] = '\0';
       where++;
       strcpy(path, where);
-      he = gethostbyname(hostname);
-      if ( !he ) goto failed;
+
+      /* support null hostnames which are useful for solaris jumpstart */
+      if (strlen(hostname)==0) {
+        bzero(&res.server_address.bp_address_u.ip_addr,4);
+      }
+      else {
+        he = gethostbyname(hostname);
+        if ( !he ) goto failed;
+      }
+
       bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
       res.server_name = hostname;
       res.server_path = path;
@@ -355,4 +371,37 @@
   }
   if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
   return(res);
+}
+
+/* Check the client address against the networks we are 
+listening on to have a more intelligent version of 
+get_myaddress(), which always returns localhost  */
+
+unsigned long
+myaddr(unsigned long clientip) {
+  struct ifaddrs *ifap, *ifaorig;
+  int i;
+  char* ifname = NULL;
+  unsigned long ifip, netmask;
+
+  getifaddrs(&ifaorig);
+  ifap = ifaorig;
+
+  while(ifap != NULL) {
+    if(ifap->ifa_addr->sa_family == AF_INET) {
+      bcopy(&ifap->ifa_addr->sa_data[2], &ifip, 4);
+      bcopy(&ifap->ifa_netmask->sa_data[2], &netmask, 4);
+
+      if((ifip & netmask) == (clientip & netmask))
+        goto done;
+    }
+
+    ifap = ifap->ifa_next;
+  }
+
+  ifip = INADDR_LOOPBACK;
+
+  done:
+   freeifaddrs(ifaorig);
+   return ifip;
 }
diff -urN bootparamd.orig/main.c bootparamd/main.c
--- bootparamd.orig/main.c	Thu Dec  1 16:06:21 2005
+++ bootparamd/main.c	Thu Dec  1 15:50:56 2005
@@ -9,7 +9,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-  "$FreeBSD: /repoman/r/ncvs/src/usr.sbin/bootparamd/bootparamd/main.c,v 1.10 2004/06/08 12:11:19 stefanf Exp $";
+  "$FreeBSD: src/usr.sbin/bootparamd/bootparamd/main.c,v 1.10 2004/06/08 12:11:19 stefanf Exp $";
 #endif /* not lint */
 
 #include <ctype.h>
@@ -32,6 +32,7 @@
 
 int debug = 0;
 int dolog = 0;
+int route_set = 0;
 unsigned long route_addr = -1;
 struct sockaddr_in my_addr;
 char *bootpfile = "/etc/bootparams";
@@ -55,6 +56,7 @@
 	    debug = 1;
 	    break;
 	  case 'r':
+              route_set = 1;
 	      if (isdigit((unsigned char)*optarg)) {
 		route_addr = inet_addr(optarg);
 		break;
@@ -85,11 +87,6 @@
 
 	if ( stat(bootpfile, &buf ) )
 	  err(1, "%s", bootpfile);
-
-	if (route_addr == -1) {
-	  get_myaddress(&my_addr);
-	  bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof (route_addr));
-	}
 
 	if (!debug) {
 	  if (daemon(0,0))


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list