root/lib/libsa/bootp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bootp
  2. bootpsend
  3. bootprecv
  4. vend_cmu
  5. vend_rfc1048

    1 /*      $OpenBSD: bootp.c,v 1.12 2006/02/06 17:37:28 jmc Exp $  */
    2 /*      $NetBSD: bootp.c,v 1.10 1996/10/13 02:28:59 christos Exp $      */
    3 
    4 /*
    5  * Copyright (c) 1992 Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * This software was developed by the Computer Systems Engineering group
    9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
   10  * contributed to Berkeley.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the University of
   23  *      California, Lawrence Berkeley Laboratory and its contributors.
   24  * 4. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  * @(#) Header: bootp.c,v 1.4 93/09/11 03:13:51 leres Exp  (LBL)
   41  */
   42 
   43 #include <sys/types.h>
   44 #include <sys/socket.h>
   45 #include <netinet/in.h>
   46 #include <netinet/in_systm.h>
   47 
   48 #include "stand.h"
   49 #include "net.h"
   50 #include "netif.h"
   51 #include "bootp.h"
   52 
   53 static n_long   nmask, smask;
   54 
   55 static time_t   bot;
   56 
   57 static  char vm_rfc1048[4] = VM_RFC1048;
   58 static  char vm_cmu[4] = VM_CMU;
   59 
   60 /* Local forwards */
   61 static  ssize_t bootpsend(struct iodesc *, void *, size_t);
   62 static  ssize_t bootprecv(struct iodesc *, void *, size_t, time_t);
   63 static  void vend_cmu(u_char *);
   64 static  void vend_rfc1048(u_char *, u_int);
   65 
   66 /* Fetch required bootp information */
   67 void
   68 bootp(int sock)
   69 {
   70         struct iodesc *d;
   71         struct bootp *bp;
   72         struct {
   73                 u_char header[HEADER_SIZE];
   74                 struct bootp wbootp;
   75         } wbuf;
   76         struct {
   77                 u_char header[HEADER_SIZE];
   78                 struct bootp rbootp;
   79         } rbuf;
   80 
   81 #ifdef BOOTP_DEBUG
   82         if (debug)
   83                 printf("bootp: socket=%d\n", sock);
   84 #endif
   85         if (!bot)
   86                 bot = getsecs();
   87 
   88         if (!(d = socktodesc(sock))) {
   89                 printf("bootp: bad socket. %d\n", sock);
   90                 return;
   91         }
   92 #ifdef BOOTP_DEBUG
   93         if (debug)
   94                 printf("bootp: d=%x\n", (u_int)d);
   95 #endif
   96 
   97         bp = &wbuf.wbootp;
   98         bzero(bp, sizeof(*bp));
   99 
  100         bp->bp_op = BOOTREQUEST;
  101         bp->bp_htype = HTYPE_ETHERNET;  /* 10Mb Ethernet (48 bits) */
  102         bp->bp_hlen = 6;
  103         bp->bp_xid = htonl(d->xid);
  104         MACPY(d->myea, bp->bp_chaddr);
  105         bzero(bp->bp_file, sizeof(bp->bp_file));
  106         bcopy(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048));
  107 
  108         d->myip = myip;
  109         d->myport = htons(IPPORT_BOOTPC);
  110         d->destip.s_addr = INADDR_BROADCAST;
  111         d->destport = htons(IPPORT_BOOTPS);
  112 
  113         (void)sendrecv(d,
  114             bootpsend, bp, sizeof(*bp),
  115             bootprecv, &rbuf.rbootp, sizeof(rbuf.rbootp));
  116 
  117         /* Bump xid so next request will be unique. */
  118         ++d->xid;
  119 }
  120 
  121 /* Transmit a bootp request */
  122 static ssize_t
  123 bootpsend(struct iodesc *d, void *pkt, size_t len)
  124 {
  125         struct bootp *bp;
  126 
  127 #ifdef BOOTP_DEBUG
  128         if (debug)
  129                 printf("bootpsend: d=%x called.\n", (u_int)d);
  130 #endif
  131 
  132         bp = pkt;
  133         bp->bp_secs = htons((u_short)(getsecs() - bot));
  134 
  135 #ifdef BOOTP_DEBUG
  136         if (debug)
  137                 printf("bootpsend: calling sendudp\n");
  138 #endif
  139 
  140         return (sendudp(d, pkt, len));
  141 }
  142 
  143 /* Returns 0 if this is the packet we're waiting for else -1 (and errno == 0) */
  144 static ssize_t
  145 bootprecv(struct iodesc *d, void *pkt, size_t len, time_t tleft)
  146 {
  147         ssize_t n;
  148         struct bootp *bp;
  149 
  150 #ifdef BOOTP_DEBUG
  151         if (debug)
  152                 printf("bootprecv: called\n");
  153 #endif
  154 
  155         n = readudp(d, pkt, len, tleft);
  156         if (n < 0 || (size_t)n < sizeof(struct bootp))
  157                 goto bad;
  158 
  159         bp = (struct bootp *)pkt;
  160 
  161 #ifdef BOOTP_DEBUG
  162         if (debug)
  163                 printf("bootprecv: checked.  bp = 0x%x, n = %d\n",
  164                     (unsigned)bp, n);
  165 #endif
  166         if (bp->bp_xid != htonl(d->xid)) {
  167 #ifdef BOOTP_DEBUG
  168                 if (debug) {
  169                         printf("bootprecv: expected xid 0x%lx, got 0x%lx\n",
  170                             d->xid, ntohl(bp->bp_xid));
  171                 }
  172 #endif
  173                 goto bad;
  174         }
  175 
  176 #ifdef BOOTP_DEBUG
  177         if (debug)
  178                 printf("bootprecv: got one!\n");
  179 #endif
  180 
  181         /* Pick up our ip address (and natural netmask) */
  182         myip = d->myip = bp->bp_yiaddr;
  183 #ifdef BOOTP_DEBUG
  184         if (debug)
  185                 printf("our ip address is %s\n", inet_ntoa(d->myip));
  186 #endif
  187         if (IN_CLASSA(d->myip.s_addr))
  188                 nmask = IN_CLASSA_NET;
  189         else if (IN_CLASSB(d->myip.s_addr))
  190                 nmask = IN_CLASSB_NET;
  191         else
  192                 nmask = IN_CLASSC_NET;
  193 #ifdef BOOTP_DEBUG
  194         if (debug)
  195                 printf("'native netmask' is %s\n", intoa(nmask));
  196 #endif
  197 
  198         /* Pick up root or swap server address and file spec. */
  199         if (bp->bp_siaddr.s_addr != 0)
  200                 rootip = bp->bp_siaddr;
  201         if (bp->bp_file[0] != '\0') {
  202                 strncpy(bootfile, (char *)bp->bp_file, sizeof(bootfile));
  203                 bootfile[sizeof(bootfile) - 1] = '\0';
  204         }
  205 
  206         /* Suck out vendor info */
  207         if (bcmp(vm_cmu, bp->bp_vend, sizeof(vm_cmu)) == 0)
  208                 vend_cmu(bp->bp_vend);
  209         else if (bcmp(vm_rfc1048, bp->bp_vend, sizeof(vm_rfc1048)) == 0)
  210                 vend_rfc1048(bp->bp_vend, sizeof(bp->bp_vend));
  211         else
  212                 printf("bootprecv: unknown vendor 0x%lx\n", (long)bp->bp_vend);
  213 
  214         /* Check subnet mask against net mask; toss if bogus */
  215         if ((nmask & smask) != nmask) {
  216 #ifdef BOOTP_DEBUG
  217                 if (debug)
  218                         printf("subnet mask (%s) bad\n", intoa(smask));
  219 #endif
  220                 smask = 0;
  221         }
  222 
  223         /* Get subnet (or natural net) mask */
  224         netmask = nmask;
  225         if (smask)
  226                 netmask = smask;
  227 #ifdef BOOTP_DEBUG
  228         if (debug)
  229                 printf("mask: %s\n", intoa(netmask));
  230 #endif
  231 
  232         /* We need a gateway if root or swap is on a different net */
  233         if (!SAMENET(d->myip, rootip, netmask)) {
  234 #ifdef BOOTP_DEBUG
  235                 if (debug)
  236                         printf("need gateway for root ip\n");
  237 #endif
  238         }
  239 
  240         if (!SAMENET(d->myip, swapip, netmask)) {
  241 #ifdef BOOTP_DEBUG
  242                 if (debug)
  243                         printf("need gateway for swap ip\n");
  244 #endif
  245         }
  246 
  247         /* Toss gateway if on a different net */
  248         if (!SAMENET(d->myip, gateip, netmask)) {
  249 #ifdef BOOTP_DEBUG
  250                 if (debug)
  251                         printf("gateway ip (%s) bad\n", inet_ntoa(gateip));
  252 #endif
  253                 gateip.s_addr = 0;
  254         }
  255 
  256         return (n);
  257 
  258 bad:
  259         errno = 0;
  260         return (-1);
  261 }
  262 
  263 static void
  264 vend_cmu(u_char *cp)
  265 {
  266         struct cmu_vend *vp;
  267 
  268 #ifdef BOOTP_DEBUG
  269         if (debug)
  270                 printf("vend_cmu bootp info.\n");
  271 #endif
  272         vp = (struct cmu_vend *)cp;
  273 
  274         if (vp->v_smask.s_addr != 0)
  275                 smask = vp->v_smask.s_addr;
  276         if (vp->v_dgate.s_addr != 0)
  277                 gateip = vp->v_dgate;
  278 }
  279 
  280 static void
  281 vend_rfc1048(u_char *cp, u_int len)
  282 {
  283         u_char *ep;
  284         int size;
  285         u_char tag;
  286 
  287 #ifdef BOOTP_DEBUG
  288         if (debug)
  289                 printf("vend_rfc1048 bootp info. len=%d\n", len);
  290 #endif
  291         ep = cp + len;
  292 
  293         /* Step over magic cookie */
  294         cp += sizeof(int);
  295 
  296         while (cp < ep) {
  297                 tag = *cp++;
  298                 size = *cp++;
  299                 if (tag == TAG_END)
  300                         break;
  301 
  302                 if (tag == TAG_SUBNET_MASK)
  303                         bcopy(cp, &smask, sizeof(smask));
  304                 if (tag == TAG_GATEWAY)
  305                         bcopy(cp, &gateip.s_addr, sizeof(gateip.s_addr));
  306                 if (tag == TAG_SWAPSERVER)
  307                         bcopy(cp, &swapip.s_addr, sizeof(swapip.s_addr));
  308                 if (tag == TAG_DOMAIN_SERVER)
  309                         bcopy(cp, &nameip.s_addr, sizeof(nameip.s_addr));
  310                 if (tag == TAG_ROOTPATH) {
  311                         strncpy(rootpath, (char *)cp, sizeof(rootpath));
  312                         rootpath[size] = '\0';
  313                 }
  314                 if (tag == TAG_HOSTNAME) {
  315                         strncpy(hostname, (char *)cp, sizeof(hostname));
  316                         hostname[size] = '\0';
  317                 }
  318                 if (tag == TAG_DOMAINNAME) {
  319                         strncpy(domainname, (char *)cp, sizeof(domainname));
  320                         domainname[size] = '\0';
  321                 }
  322                 cp += size;
  323         }
  324 }

/* [<][>][^][v][top][bottom][index][help] */