[BACK]Return to net.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / stand / pxeboot

Annotation of sys/arch/i386/stand/pxeboot/net.c, Revision 1.1

1.1     ! nbrk        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: }

CVSweb