Newsgroups: comp.sources.unix From: gwr@mc.com (Gordon W. Ross) Subject: v27i076: bootp-2.2 - RFC 1048 "bootp" server (w/ vendor extensions), Patch01 Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: gwr@mc.com (Gordon W. Ross) Posting-Number: Volume 27, Issue 76 Archive-Name: bootp-2.2.B/patch01 I didn't have a Solaris machine to test on when I merge in the Solaris support changes and, well, I botched it. Sorry. (On Solaris, it dumps core while composing the first reply.) Here are changes to make bootp-2.2.B _really_ work on Solaris. Your copy becomes version 2.2.C after these chages. Gordon W. Ross Mercury Computer Systems gwr@mc.com 199 Riverneck Road 508-256-1300 Chelmsford, MA 01824-2820 diff -rcw bootp-2.2.B/Makefile bootp-2.2.C/Makefile *** bootp-2.2.B/Makefile Thu Oct 7 15:30:56 1993 --- bootp-2.2.C/Makefile Thu Oct 14 19:21:29 1993 *************** *** 20,26 **** # Uncomment these lines for SunOS 4.X SYSDEFS= -DSUNOS4 # Uncomment these lines for SVR4 (or Solaris 2.X) ! # SYSDEFS= -DSVR4 # -Dsparc -Dsun -Dunix ?XXX? # SYSLIBS= -lsocket -lnsl INSTALL=/usr/bin/install --- 20,26 ---- # Uncomment these lines for SunOS 4.X SYSDEFS= -DSUNOS4 # Uncomment these lines for SVR4 (or Solaris 2.X) ! # SYSDEFS= -DSVR4 # SYSLIBS= -lsocket -lnsl INSTALL=/usr/bin/install diff -rcw bootp-2.2.B/Version.c bootp-2.2.C/Version.c *** bootp-2.2.B/Version.c Thu Oct 7 16:11:18 1993 --- bootp-2.2.C/Version.c Thu Oct 14 19:40:01 1993 *************** *** 41,48 **** */ #ifndef lint ! char sccsid[] = "@(#)bootpd 2.2.B %VERSION% %WHOANDWHERE%\n"; ! char rcsid[] = "$Header: Version 2.2.B from gwr@mc.com $"; #endif /* not lint */ ! char Version[] = "bootpd 2.2.B %VERSION%\n\t%WHOANDWHERE%\n"; --- 41,48 ---- */ #ifndef lint ! char sccsid[] = "@(#)bootpd 2.2.C %VERSION% %WHOANDWHERE%\n"; ! char rcsid[] = "$Header: Version 2.2.C from gwr@mc.com $"; #endif /* not lint */ ! char Version[] = "bootpd 2.2.C %VERSION%\n\t%WHOANDWHERE%\n"; diff -rcw bootp-2.2.B/bootpd.c bootp-2.2.C/bootpd.c *** bootp-2.2.B/bootpd.c Fri Oct 8 11:34:30 1993 --- bootp-2.2.C/bootpd.c Thu Oct 14 19:27:24 1993 *************** *** 85,93 **** #include #include #ifdef SVR4 ! #include /* Why? */ #include - #include /* Why? */ #else #include #endif --- 85,93 ---- #include #include #ifdef SVR4 ! #include /* for O_RDONLY, etc */ ! #include /* for TIOCNOTTY */ #include #else #include #endif *************** *** 120,126 **** #define bcopy(a,b,c) memcpy(b,a,c) #define bzero(p,l) memset(p,0,l) #define bcmp(a,b,c) memcmp(a,b,c) ! #define index(a,b) strchr(a,b) #endif --- 120,126 ---- #define bcopy(a,b,c) memcpy(b,a,c) #define bzero(p,l) memset(p,0,l) #define bcmp(a,b,c) memcmp(a,b,c) ! #define index strchr #endif *************** *** 162,169 **** * Internet socket and interface config structures */ ! struct sockaddr server_addr; ! struct sockaddr client_addr; struct ifreq ifreq[10]; /* Holds interface configuration */ struct ifconf ifconf; /* Int. config ioctl block (pnts to ifreq) */ struct arpreq arpreq; /* Arp request ioctl block */ --- 162,169 ---- * Internet socket and interface config structures */ ! struct sockaddr_in server_addr; ! struct sockaddr_in client_addr; struct ifreq ifreq[10]; /* Holds interface configuration */ struct ifconf ifconf; /* Int. config ioctl block (pnts to ifreq) */ struct arpreq arpreq; /* Arp request ioctl block */ *************** *** 243,249 **** struct timeval actualtimeout, *timeout; struct bootp *bp; struct servent *servp; - struct sockaddr_in *s_sin; char *stmp; int n, sa_len, ca_len; int nfound, readfds; --- 243,248 ---- *************** *** 253,259 **** actualtimeout.tv_usec = 0L; actualtimeout.tv_sec = 60 * DEFAULT_TIMEOUT; timeout = &actualtimeout; - s_sin = (struct sockaddr_in *) &server_addr; /* Get space for receiving packets and composing replies. */ pktbuf = malloc(MAXPKT); --- 252,257 ---- *************** *** 271,284 **** bzero((char *) &server_addr, sa_len); errno = 0; standalone = TRUE; ! if (getsockname(s, &server_addr, &sa_len) == 0) { /* * Descriptor 0 is a socket. Assume we are a child of inetd. */ ! if (s_sin->sin_family == AF_INET) { standalone = FALSE; ! bootps_port = ntohs(s_sin->sin_port); } else { report(LOG_INFO, "getsockname: not an INET socket\n"); } } --- 269,283 ---- bzero((char *) &server_addr, sa_len); errno = 0; standalone = TRUE; ! if (getsockname(s, (struct sockaddr *) &server_addr, &sa_len) == 0) { /* * Descriptor 0 is a socket. Assume we are a child of inetd. */ ! if (server_addr.sin_family == AF_INET) { standalone = FALSE; ! bootps_port = ntohs(server_addr.sin_port); } else { + /* Some other type of socket? */ report(LOG_INFO, "getsockname: not an INET socket\n"); } } *************** *** 470,479 **** /* * Bind socket to BOOTPS port. */ ! s_sin->sin_family = AF_INET; ! s_sin->sin_addr.s_addr = INADDR_ANY; ! s_sin->sin_port = htons(bootps_port); ! if (bind(s, &server_addr, sizeof(*s_sin)) < 0) { report(LOG_ERR, "bind: %s\n", get_network_errmsg()); exit(1); } --- 469,480 ---- /* * Bind socket to BOOTPS port. */ ! server_addr.sin_family = AF_INET; ! server_addr.sin_addr.s_addr = INADDR_ANY; ! server_addr.sin_port = htons(bootps_port); ! if (bind(s, (struct sockaddr *) &server_addr, ! sizeof(server_addr)) < 0) ! { report(LOG_ERR, "bind: %s\n", get_network_errmsg()); exit(1); } *************** *** 538,544 **** exit(0); } ca_len = sizeof(client_addr); ! n = recvfrom(s, pktbuf, MAXPKT, 0, &client_addr, &ca_len); if (n <= 0) { continue; } --- 539,546 ---- exit(0); } ca_len = sizeof(client_addr); ! n = recvfrom(s, pktbuf, MAXPKT, 0, ! (struct sockaddr *) &client_addr, &ca_len); if (n <= 0) { continue; } *************** *** 860,871 **** int forward; { register struct bootp *bp = (struct bootp *) pktbuf; ! struct in_addr dst; /* XXX */ ! struct sockaddr_in *c_sin; ! c_sin = (struct sockaddr_in *) &client_addr; ! ! c_sin->sin_port = htons(bootpc_port); /* * If the client IP address is specified, use that * else if gateway IP address is specified, use that --- 862,870 ---- int forward; { register struct bootp *bp = (struct bootp *) pktbuf; ! struct in_addr dst; ! client_addr.sin_port = htons(bootpc_port); /* * If the client IP address is specified, use that * else if gateway IP address is specified, use that *************** *** 876,882 **** dst = bp->bp_ciaddr; } else if (bp->bp_giaddr.s_addr && forward == 0) { dst = bp->bp_giaddr; ! c_sin->sin_port = htons(bootps_port); } else { dst = bp->bp_yiaddr; setarp(&dst, bp->bp_chaddr, bp->bp_hlen); --- 875,881 ---- dst = bp->bp_ciaddr; } else if (bp->bp_giaddr.s_addr && forward == 0) { dst = bp->bp_giaddr; ! client_addr.sin_port = htons(bootps_port); } else { dst = bp->bp_yiaddr; setarp(&dst, bp->bp_chaddr, bp->bp_hlen); *************** *** 925,934 **** } } ! c_sin->sin_addr = dst; /* Send reply with same size packet as request used. */ if (sendto(s, pktbuf, pktlen, 0, ! &client_addr, sizeof(*c_sin)) < 0) { report(LOG_ERR, "sendto: %s\n", get_network_errmsg()); } } /* sendreply */ --- 924,935 ---- } } ! client_addr.sin_addr = dst; /* Send reply with same size packet as request used. */ if (sendto(s, pktbuf, pktlen, 0, ! (struct sockaddr *) &client_addr, ! sizeof(client_addr)) < 0) ! { report(LOG_ERR, "sendto: %s\n", get_network_errmsg()); } } /* sendreply */ *************** *** 965,980 **** { struct sockaddr_in *si; bzero((caddr_t)&arpreq, sizeof(arpreq)); arpreq.arp_pa.sa_family = AF_INET; si = (struct sockaddr_in *) &arpreq.arp_pa; si->sin_addr = *ia; ! arpreq.arp_flags = ATF_INUSE | ATF_COM; ! bcopy(ha, arpreq.arp_ha.sa_data, len); if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) { report(LOG_ERR, "ioctl(SIOCSARP): %s\n", get_network_errmsg()); } --- 966,987 ---- { struct sockaddr_in *si; + if (debug > 1) + report(LOG_INFO, "setarp %s %s (l=%d)\n", + inet_ntoa(*ia), haddrtoa(ha, 1), len); + bzero((caddr_t)&arpreq, sizeof(arpreq)); + arpreq.arp_flags = ATF_INUSE | ATF_COM; + /* Set up the protocol address. */ arpreq.arp_pa.sa_family = AF_INET; si = (struct sockaddr_in *) &arpreq.arp_pa; si->sin_addr = *ia; ! /* Set up the hardware address. */ bcopy(ha, arpreq.arp_ha.sa_data, len); + /* XXX - Why does this fail on Solaris 2.X ? (ENXIO) */ if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) { report(LOG_ERR, "ioctl(SIOCSARP): %s\n", get_network_errmsg()); } *************** *** 1308,1313 **** --- 1315,1325 ---- * One could append additional options when there is room after the * end record but this implementation does not do so. One would need * a way to know which options should be "forced" into the list. + * + * This function is now not really correct. The client only gets + * to set the magic number, not the data. Oddball clients can be + * supported using the "arbitrary vendor data" feature, so this + * code should be reverted back to the CMU version. */ void dovend_rfc1048(bp, hp, bootsize) register struct bootp *bp; *************** *** 1320,1325 **** --- 1332,1338 ---- char *tmpstr; unsigned long ul; unsigned short us; + extern char *index(); /* * Compute pointers to beginning and end of option area.