Date: Mon, 5 Dec 2005 19:12:18 GMT From: John <omen-pub@omenlabs.com> To: freebsd-gnats-submit@FreeBSD.org Subject: bin/89988: [PATCH] bootparamd null host support and whoami fix Message-ID: <200512051912.jB5JCI4V052317@www.freebsd.org> Resent-Message-ID: <200512051920.jB5JK2Vw007366@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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@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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200512051912.jB5JCI4V052317>