root/arch/i386/stand/pxeboot/net.c

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

DEFINITIONS

This source file includes following definitions.
  1. sendudp
  2. readudp
  3. sendrecv
  4. inet_addr
  5. inet_ntoa
  6. intoa
  7. number
  8. ip_convertaddr

    1 /*      $OpenBSD: net.c,v 1.1 2004/03/19 13:48:19 tom Exp $     */
    2 /*      $NetBSD: net.c,v 1.14 1996/10/13 02:29:02 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: net.c,v 1.9 93/08/06 19:32:15 leres Exp  (LBL)
   41  */
   42 
   43 #include <sys/param.h>
   44 #include <sys/socket.h>
   45 
   46 #include <net/if.h>
   47 #include <netinet/in.h>
   48 
   49 #include <netinet/in.h>
   50 #include <netinet/if_ether.h>
   51 #include <netinet/in_systm.h>
   52 #include <netinet/ip.h>
   53 #include <netinet/ip_var.h>
   54 #include <netinet/udp.h>
   55 #include <netinet/udp_var.h>
   56 
   57 #include <lib/libsa/stand.h>
   58 #include <lib/libsa/net.h>
   59 
   60 #include <pxeboot.h>
   61 
   62 /* Caller must leave room for ethernet, ip and udp headers in front!! */
   63 ssize_t
   64 sendudp(struct iodesc *d, void *pkt, size_t len)
   65 {
   66         return pxesendudp(d, pkt, len);
   67 }
   68 
   69 /*
   70  * Receive a UDP packet and validate it is for us.
   71  * Caller leaves room for the headers (Ether, IP, UDP)
   72  */
   73 ssize_t
   74 readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
   75 {
   76         return pxereadudp(d, pkt, len, tleft);
   77 }
   78 
   79 /*
   80  * Send a packet and wait for a reply, with exponential backoff.
   81  *
   82  * The send routine must return the actual number of bytes written.
   83  *
   84  * The receive routine can indicate success by returning the number of
   85  * bytes read; it can return 0 to indicate EOF; it can return -1 with a
   86  * non-zero errno to indicate failure; finally, it can return -1 with a
   87  * zero errno to indicate it isn't done yet.
   88  */
   89 ssize_t
   90 sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t),
   91     void *sbuf, size_t ssize,
   92     ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t),
   93     void *rbuf, size_t rsize)
   94 {
   95         ssize_t cc;
   96         time_t t, tmo, tlast;
   97         long tleft;
   98 
   99 #ifdef NET_DEBUG
  100         if (debug)
  101                 printf("sendrecv: called\n");
  102 #endif
  103 
  104         tmo = MINTMO;
  105         tlast = tleft = 0;
  106         t = getsecs();
  107         for (;;) {
  108                 if (tleft <= 0) {
  109                         if (tmo >= MAXTMO) {
  110                                 errno = ETIMEDOUT;
  111                                 return -1;
  112                         }
  113                         cc = (*sproc)(d, sbuf, ssize);
  114                         if (cc < 0 || (size_t)cc < ssize)
  115                                 panic("sendrecv: short write! (%d < %d)",
  116                                     cc, ssize);
  117 
  118                         tleft = tmo;
  119                         tmo <<= 1;
  120                         if (tmo > MAXTMO)
  121                                 tmo = MAXTMO;
  122                         tlast = t;
  123                 }
  124 
  125                 /* Try to get a packet and process it. */
  126                 cc = (*rproc)(d, rbuf, rsize, tleft);
  127                 /* Return on data, EOF or real error. */
  128                 if (cc != -1 || errno != 0)
  129                         return (cc);
  130 
  131                 /* Timed out or didn't get the packet we're waiting for */
  132                 t = getsecs();
  133                 tleft -= t - tlast;
  134                 tlast = t;
  135         }
  136 }
  137 
  138 /*
  139  * Like inet_addr() in the C library, but we only accept base-10.
  140  * Return values are in network order.
  141  */
  142 n_long
  143 inet_addr(char *cp)
  144 {
  145         u_long val;
  146         int n;
  147         char c;
  148         u_int parts[4];
  149         u_int *pp = parts;
  150 
  151         for (;;) {
  152                 /*
  153                  * Collect number up to ``.''.
  154                  * Values are specified as for C:
  155                  * 0x=hex, 0=octal, other=decimal.
  156                  */
  157                 val = 0;
  158                 while ((c = *cp) != '\0') {
  159                         if (c >= '0' && c <= '9') {
  160                                 val = (val * 10) + (c - '0');
  161                                 cp++;
  162                                 continue;
  163                         }
  164                         break;
  165                 }
  166                 if (*cp == '.') {
  167                         /*
  168                          * Internet format:
  169                          *      a.b.c.d
  170                          *      a.b.c   (with c treated as 16-bits)
  171                          *      a.b     (with b treated as 24 bits)
  172                          */
  173                         if (pp >= parts + 3 || val > 0xff)
  174                                 goto bad;
  175                         *pp++ = val, cp++;
  176                 } else
  177                         break;
  178         }
  179         /*
  180          * Check for trailing characters.
  181          */
  182         if (*cp != '\0')
  183                 goto bad;
  184 
  185         /*
  186          * Concoct the address according to
  187          * the number of parts specified.
  188          */
  189         n = pp - parts + 1;
  190         switch (n) {
  191 
  192         case 1:                         /* a -- 32 bits */
  193                 break;
  194 
  195         case 2:                         /* a.b -- 8.24 bits */
  196                 if (val > 0xffffff)
  197                         goto bad;
  198                 val |= parts[0] << 24;
  199                 break;
  200 
  201         case 3:                         /* a.b.c -- 8.8.16 bits */
  202                 if (val > 0xffff)
  203                         goto bad;
  204                 val |= (parts[0] << 24) | (parts[1] << 16);
  205                 break;
  206 
  207         case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
  208                 if (val > 0xff)
  209                         goto bad;
  210                 val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
  211                 break;
  212         }
  213 
  214         return (htonl(val));
  215  bad:
  216         return (htonl(INADDR_NONE));
  217 }
  218 
  219 char *
  220 inet_ntoa(struct in_addr ia)
  221 {
  222         return (intoa(ia.s_addr));
  223 }
  224 
  225 /* Similar to inet_ntoa() */
  226 char *
  227 intoa(n_long addr)
  228 {
  229         char *cp;
  230         u_int byte;
  231         int n;
  232         static char buf[sizeof(".255.255.255.255")];
  233 
  234         NTOHL(addr);
  235         cp = &buf[sizeof buf];
  236         *--cp = '\0';
  237 
  238         n = 4;
  239         do {
  240                 byte = addr & 0xff;
  241                 *--cp = byte % 10 + '0';
  242                 byte /= 10;
  243                 if (byte > 0) {
  244                         *--cp = byte % 10 + '0';
  245                         byte /= 10;
  246                         if (byte > 0)
  247                                 *--cp = byte + '0';
  248                 }
  249                 *--cp = '.';
  250                 addr >>= 8;
  251         } while (--n > 0);
  252 
  253         return (cp+1);
  254 }
  255 
  256 static char *
  257 number(char *s, int *n)
  258 {
  259         for (*n = 0; isdigit(*s); s++)
  260                 *n = (*n * 10) + *s - '0';
  261         return s;
  262 }
  263 
  264 n_long
  265 ip_convertaddr(char *p)
  266 {
  267 #define IP_ANYADDR      0
  268         n_long addr = 0, n;
  269 
  270         if (p == (char *)0 || *p == '\0')
  271                 return IP_ANYADDR;
  272         p = number(p, &n);
  273         addr |= (n << 24) & 0xff000000;
  274         if (*p == '\0' || *p++ != '.')
  275                 return IP_ANYADDR;
  276         p = number(p, &n);
  277         addr |= (n << 16) & 0xff0000;
  278         if (*p == '\0' || *p++ != '.')
  279                 return IP_ANYADDR;
  280         p = number(p, &n);
  281         addr |= (n << 8) & 0xff00;
  282         if (*p == '\0' || *p++ != '.')
  283                 return IP_ANYADDR;
  284         p = number(p, &n);
  285         addr |= n & 0xff;
  286         if (*p != '\0')
  287                 return IP_ANYADDR;
  288 
  289         return htonl(addr);
  290 }

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