home *** CD-ROM | disk | FTP | other *** search
- /*
- * bootptest.c - Test out a bootp server.
- *
- *
- */
- char *usage = "bootptest server-name [vendor-data-template-file]";
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/file.h>
- #include <sys/time.h>
- #include <sys/stat.h>
- #include <net/if.h>
- #ifdef sun
- #include <sys/sockio.h>
- #include <net/if_arp.h>
- #endif
- #include <netinet/in.h>
- #include <netinet/if_ether.h>
- #include <signal.h>
- #include <stdio.h>
- #include <strings.h>
- #include <errno.h>
- #include <ctype.h>
- #include <netdb.h>
-
- extern int sys_nerr;
- extern char *sys_errlist[];
-
- #include "bootp.h"
- #include "interface.h"
-
- #define get_network_errmsg get_errmsg
- #define LOG_ERR 1
- #define BUFLEN 1024
-
- int vflag = 1;
- int tflag = 0;
- int thiszone;
- char *program_name;
- unsigned char *packetp;
- unsigned char *snapend;
- int snaplen;
-
-
- /*
- * IP port numbers for client and server obtained from /etc/services
- */
-
- u_short bootps_port, bootpc_port;
-
-
- /*
- * Internet socket and interface config structures
- */
-
- struct sockaddr_in sin_server;
- struct sockaddr_in sin_client;
- struct sockaddr_in sin_from; /* Packet source */
- struct ifreq ifreq[10]; /* Holds interface configuration */
- struct ifconf ifconf; /* Int. config ioctl block (pnts to ifreq) */
- struct arpreq arpreq; /* Arp request ioctl block */
- struct ether_addr eaddr;
-
- /*
- * General
- */
-
- int debug = 0; /* Debugging flag (level) */
- int s; /* Socket file descriptor */
- char hostname[64];
- unsigned char buf[BUFLEN]; /* Receive packet buffer */
- struct timezone tzp; /* Time zone offset for clients */
- struct timeval tp; /* Time (extra baggage) */
- long secondswest; /* Time zone offset in seconds */
-
- /*
- * Vendor magic cookies for CMU and RFC1048
- */
-
- unsigned char vm_cmu[4] = VM_CMU;
- unsigned char vm_rfc1048[4] = VM_RFC1048;
-
- void report();
- char * get_errmsg();
- extern void bootp_print();
- extern struct ether_addr *ether_hostton();
-
- /*
- * Initialization such as command-line processing is done, then
- * the receiver loop is started. Die when interrupted.
- */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- struct timeval timenow;
- struct bootp *bp = (struct bootp *) buf;
- struct servent *sep;
- struct hostent *hep;
-
- int n, tolen, fromlen;
- int nfound, readfds;
- char *servername = NULL;
- char *vendor_file = NULL;
- long server_addr = INADDR_ANY;
-
- program_name = argv[0];
-
- /* Get my Ethernet address for the query. */
- gethostname(hostname, sizeof(hostname));
- if (ether_hostton(hostname, &eaddr)) {
- printf("Can not get my ethernet address\n");
- exit(1);
- }
-
- /* If server name given, query there, otherwise use broadcast. */
- if (argc <= 1) {
- printf("missing server name.\n");
- puts(usage);
- exit(1);
- }
- servername = argv[1];
-
- /* vendor-data-template-file */
- if (argc > 2) vendor_file = argv[2];
-
- /*
- * Create a socket.
- */
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- report(LOG_ERR, "socket: %s\n", get_network_errmsg());
- exit(1);
- }
-
- /*
- * Determine network configuration.
- */
- ifconf.ifc_len = sizeof(ifreq);
- ifconf.ifc_req = ifreq;
- if ((ioctl(s, SIOCGIFCONF, (caddr_t) &ifconf) < 0) ||
- (ifconf.ifc_len <= 0)) {
- report(LOG_ERR, "ioctl: %s\n", get_network_errmsg());
- exit(1);
- }
- /* Find the appropriate interface to use? */
-
- /*
- * Get server's listening port number
- */
- sep = getservbyname("bootps", "udp");
- if (sep) {
- bootps_port = ntohs((u_short) sep->s_port);
- } else {
- report(LOG_ERR,
- "udp/bootps: unknown service -- assuming port %d\n",
- IPPORT_BOOTPS);
- bootps_port = (u_short) IPPORT_BOOTPS;
- }
-
- /*
- * Set up server socket address.
- */
- if (servername) {
- hep = gethostbyname(servername);
- if (!hep) {
- report(LOG_ERR, "gethostbyname(%s)", servername);
- exit(1);
- }
- bcopy(hep->h_addr, &sin_server.sin_addr, sizeof(struct in_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);
-
- /*
- * Get client's listening port number
- */
- sep = getservbyname("bootpc", "udp");
- if (sep) {
- bootpc_port = ntohs(sep->s_port);
- } else {
- report(LOG_ERR,
- "udp/bootpc: unknown service -- assuming port %d\n",
- IPPORT_BOOTPC);
- bootpc_port = (u_short) IPPORT_BOOTPC;
- }
-
- /*
- * Set up client socket address.
- */
- sin_client.sin_family = AF_INET;
- sin_client.sin_addr.s_addr = INADDR_ANY;
- sin_client.sin_port = htons(bootpc_port);
-
- /*
- * Bind client socket to BOOTPC port.
- */
- if (bind(s, &sin_client, sizeof(sin_client)) < 0) {
- perror("bind BOOTPC port");
- fprintf(stderr, "You need to run this as root\n");
- exit(1);
- }
-
- /*
- * Build a request.
- */
- bzero(bp, sizeof(*bp));
- bp->bp_op = BOOTREQUEST;
- bp->bp_htype = 1;
- bp->bp_hlen = 6;
- bp->bp_xid = 2; /* arbitrary */
- bp->bp_secs = 4;
-
- /*
- * Make the request look like a broadcast type.
- * (supply the hardware address, not the client IP address.)
- */
- bcopy(&eaddr, bp->bp_chaddr, sizeof(eaddr));
- bp->bp_siaddr.s_addr = -1; /* broadcast address */
-
- /*
- * Read in the "options" part of the request.
- * This also determines the size of the packet.
- */
- snaplen = sizeof(*bp);
- if (vendor_file) {
- int fd = open(vendor_file, 0);
- if (fd < 0) {
- perror(vendor_file);
- exit(1);
- }
- /* Compute actual space for options. */
- n = BUFLEN - sizeof(*bp) + BP_VEND_LEN;
- n = read(fd, bp->bp_vend, n);
- close(fd);
- if (n < 0) {
- perror(vendor_file);
- exit(1);
- }
- printf("read %d bytes of vendor template\n", n);
- if (n > BP_VEND_LEN) {
- printf("warning: extended options in use (len > %d)\n",
- BP_VEND_LEN);
- snaplen += (n - BP_VEND_LEN);
- }
- }
- /* Set the end pointer for bootp_print() */
- snapend = buf + snaplen;
-
- /* This is used by bootp_print() */
- packetp = (unsigned char*) &eaddr;
-
- /* Print the request packet. */
- printf("Request to %s", inet_ntoa(sin_server.sin_addr));
- printf(" (port:%d)", bootps_port);
- bootp_print(bp, snaplen, sin_from.sin_port, 0);
- putchar('\n');
-
- if (sendto(s, buf, snaplen, 0,
- &sin_server, sizeof(sin_server)) < 0)
- {
- perror("sendto server");
- exit(1);
- }
-
- printf("Receiving...\n");
- alarm(5); /* XXX - OK? */
-
- while (1) {
-
- fromlen = sizeof(sin_from);
- n = recvfrom(s, buf, sizeof(buf), 0, &sin_from, &fromlen);
- if (n <= 0) {
- continue;
- }
-
- if (n < sizeof(struct bootp)) {
- report(LOG_ERR, "received short packet\n");
- continue;
- }
-
- /* Print the received packet. */
- printf("Packet from %s", inet_ntoa(sin_from.sin_addr));
- printf(" (port:%d)", ntohs(sin_from.sin_port));
- snaplen = n;
- snapend = buf + snaplen;
- bootp_print(bp, n, sin_from.sin_port, 0);
- putchar('\n');
- }
- }
-
-
-
- /*
- * This routine reports errors and such via stderr and syslog() if
- * appopriate. It just helps avoid a lot of "#ifdef SYSLOG" constructs
- * from being scattered throughout the code.
- *
- * The syntax is identical to syslog(3), but %m is not considered special
- * for output to stderr (i.e. you'll see "%m" in the output. . .). Also,
- * control strings should normally end with \n since newlines aren't
- * automatically generated for stderr output (whereas syslog strips out all
- * newlines and adds its own at the end).
- */
-
- /*VARARGS2*/
- void report(priority, fmt, p0, p1, p2, p3, p4)
- int priority;
- char *fmt;
- {
- fprintf(stderr, "bootpd(pri=%d): ", priority);
- fprintf(stderr, fmt, p0, p1, p2, p3, p4);
- }
-
-
- /*
- * Return pointer to static string which gives full filesystem error message.
- */
-
- char *get_errmsg()
- {
- static char errmsg[80];
-
- if (errno < sys_nerr) {
- return sys_errlist[errno];
- } else {
- sprintf(errmsg, "Error %d", errno);
- return errmsg;
- }
- }
-
- #ifndef etheraddr_string
- char *etheraddr_string(p)
- char *p;
- {
- static char buf[32];
- sprintf(buf, "%x:%x:%x:%x:%x:%x",
- p[0],p[1],p[2],p[3],p[4],p[5]);
- return(buf);
- }
- #endif
-