Subject: Early working version of bootpc for NetBSD (using bpf ...NOT!)
To: John C. Hayward <johnh@david.wheaton.edu>
From: Gordon W. Ross <gwr@mc.com>
List: current-users
Date: 08/18/1995 11:56:00
> Date: Thu, 17 Aug 1995 17:13:50 -0500 (CDT)
> From: "John C. Hayward" <johnh@david.wheaton.edu>
> Subject: Early working version of bootpc for NetBSD using bpf

> Dear NetBSDers,
>    On the issue of getting NetBSD version of bootpc up several people 
> mentioned that "bpf" could be used to grab packets before the IP number
> of an interface was known.
>    Using this I have a working version of bootpc.  It is a bit of a hack in
> that you have to know the network number your computer is on.  I first
> configure the network interface to use the network address (with a host 
> of 0) of that network then bootpc sends out a bootp request (using 
> sendto).  It then waits for packets which are filtered by bpf.  Bootpc
> then outputs the various parameters it picks up from the server.

Here is an easier way to do this:  (No BPF required)

# ifconfig ie0 inet 255.255.255.255
# ifconfig ie0
ie0: flags=8863<UP,BROADCAST,NOTRAILERS,RUNNING,SIMPLEX,MULTICAST>
        inet 255.255.255.255 netmask 0xffffff00 broadcast 255.255.255.255
# ./bootptest -i ie0 -h
bootptest: version 2.4.1
Sending to 255.255.255.255 (request) xid:131 vend-rfc1395
Recvd from 192.233.17.32 (reply) xid:131 Y:192.233.17.119 S:192.233.17.32 \
 sname:"merlin" vend-rfc1395 SM:255.255.255.0 GW:192.233.17.32 TZ:18000 \
 DNS:192.233.16.15,192.233.16.4 DNAM:"mc.com" HN:"venus"
#

All the info you need is in the bootp reply printed by bootptest.
I had to hack on bootptest slightly to get it to do the above;
attached are my changes against src/usr.sbin/bootpd/bootptest.c
(note that you build this program in src/usr.sbin/bootptest).

Have fun!
Gordon Ross


*** bootptest.c.~1~	Sat May 20 06:13:54 1995
--- bootptest.c	Fri Aug 18 11:41:48 1995
***************
*** 125,130 ****
--- 125,131 ----
  	char *servername = NULL;
  	char *vendor_file = NULL;
  	char *bp_file = NULL;
+ 	char *ifname = NULL;
  	int s;				/* Socket file descriptor */
  	int n, tolen, fromlen, recvcnt;
  	int use_hwa = 0;
***************
*** 175,180 ****
--- 176,188 ----
  			use_hwa = 1;
  			break;
  
+ 		case 'i':				/* interface name */
+ 			if (argc < 2)
+ 				goto error;
+ 			argc--; argv++;
+ 			ifname = *argv;
+ 			break;
+ 
  		case 'm':				/* Magic number value. */
  			if (argc < 2)
  				goto error;
***************
*** 204,214 ****
--- 212,227 ----
  		argc--;
  		argv++;
  	}
+ 
+ #if 0
+ 	/* if not specified, assume 255.255.255.255 */
  	if (!servername) {
  		printf("missing server name.\n");
  		puts(usage);
  		exit(1);
  	}
+ #endif
+ 
  	/*
  	 * Create a socket.
  	 */
***************
*** 242,250 ****
  			    sizeof(sin_server.sin_addr));
  		}
  	} else {
! 		/* Get broadcast address */
! 		/* XXX - not yet */
! 		sin_server.sin_addr.s_addr = INADDR_ANY;
  	}
  	sin_server.sin_family = AF_INET;
  	sin_server.sin_port = htons(bootps_port);
--- 255,268 ----
  			    sizeof(sin_server.sin_addr));
  		}
  	} else {
! 		/* XXX - Get broadcast address? */
! 		int on = 1;
! 		servername = "255.255.255.255";
! 		sin_server.sin_addr.s_addr = INADDR_BROADCAST;
! 		if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))) {
! 			perror("setsockopt broadcast");
! 			exit(1);
! 		}
  	}
  	sin_server.sin_family = AF_INET;
  	sin_server.sin_port = htons(bootps_port);
***************
*** 294,305 ****
  	if (use_hwa) {
  		struct ifreq *ifr;
  
! 		ifr = getif(s, &sin_server.sin_addr);
! 		if (!ifr) {
! 			printf("No interface for %s\n", servername);
! 			exit(1);
  		}
! 		if (getether(ifr->ifr_name, eaddr)) {
  			printf("Can not get ether addr for %s\n", ifr->ifr_name);
  			exit(1);
  		}
--- 312,326 ----
  	if (use_hwa) {
  		struct ifreq *ifr;
  
! 		if (!ifname) {
! 			ifr = getif(s, &sin_server.sin_addr);
! 			if (!ifr) {
! 				printf("No interface for %s\n", servername);
! 				exit(1);
! 			}
! 			ifname = ifr->ifr_name;
  		}
! 		if (getether(ifname, eaddr)) {
  			printf("Can not get ether addr for %s\n", ifr->ifr_name);
  			exit(1);
  		}