[BACK]Return to net.c CVS log [TXT][DIR] Up to [local] / sys / lib / libsa

Annotation of sys/lib/libsa/net.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: net.c,v 1.13 2003/08/11 06:23:09 deraadt 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 "stand.h"
        !            58: #include "net.h"
        !            59:
        !            60: /* Caller must leave room for ethernet, ip and udp headers in front!! */
        !            61: ssize_t
        !            62: sendudp(struct iodesc *d, void *pkt, size_t len)
        !            63: {
        !            64:        ssize_t cc;
        !            65:        struct ip *ip;
        !            66:        struct udpiphdr *ui;
        !            67:        struct udphdr *uh;
        !            68:        u_char *ea;
        !            69:        struct ip tip;
        !            70:
        !            71: #ifdef NET_DEBUG
        !            72:        if (debug) {
        !            73:                printf("sendudp: d=%x called.\n", (u_int)d);
        !            74:                if (d) {
        !            75:                        printf("saddr: %s:%d",
        !            76:                            inet_ntoa(d->myip), ntohs(d->myport));
        !            77:                        printf(" daddr: %s:%d\n",
        !            78:                            inet_ntoa(d->destip), ntohs(d->destport));
        !            79:                }
        !            80:        }
        !            81: #endif
        !            82:
        !            83:        uh = (struct udphdr *)pkt - 1;
        !            84:        ip = (struct ip *)uh - 1;
        !            85:        len += sizeof(*ip) + sizeof(*uh);
        !            86:
        !            87:        bzero(ip, sizeof(*ip) + sizeof(*uh));
        !            88:
        !            89:        ip->ip_v = IPVERSION;                   /* half-char */
        !            90:        ip->ip_hl = sizeof(*ip) >> 2;           /* half-char */
        !            91:        ip->ip_len = htons(len);
        !            92:        ip->ip_p = IPPROTO_UDP;                 /* char */
        !            93:        ip->ip_ttl = IP_TTL;                    /* char */
        !            94:        ip->ip_src = d->myip;
        !            95:        ip->ip_dst = d->destip;
        !            96:        ip->ip_sum = in_cksum(ip, sizeof(*ip));  /* short, but special */
        !            97:
        !            98:        uh->uh_sport = d->myport;
        !            99:        uh->uh_dport = d->destport;
        !           100:        uh->uh_ulen = htons(len - sizeof(*ip));
        !           101:
        !           102:        /* Calculate checksum (must save and restore ip header) */
        !           103:        tip = *ip;
        !           104:        ui = (struct udpiphdr *)ip;
        !           105:        bzero(ui->ui_x1, sizeof(ui->ui_x1));
        !           106:        ui->ui_len = uh->uh_ulen;
        !           107:        uh->uh_sum = in_cksum(ui, len);
        !           108:        *ip = tip;
        !           109:
        !           110:        if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 ||
        !           111:            netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask))
        !           112:                ea = arpwhohas(d, ip->ip_dst);
        !           113:        else
        !           114:                ea = arpwhohas(d, gateip);
        !           115:
        !           116:        cc = sendether(d, ip, len, ea, ETHERTYPE_IP);
        !           117:        if (cc < 0)
        !           118:                return (-1);
        !           119:        if ((size_t)cc != len)
        !           120:                panic("sendudp: bad write (%d != %d)", cc, len);
        !           121:        return (cc - (sizeof(*ip) + sizeof(*uh)));
        !           122: }
        !           123:
        !           124: /*
        !           125:  * Receive a UDP packet and validate it is for us.
        !           126:  * Caller leaves room for the headers (Ether, IP, UDP)
        !           127:  */
        !           128: ssize_t
        !           129: readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft)
        !           130: {
        !           131:        ssize_t n;
        !           132:        size_t hlen;
        !           133:        struct ip *ip;
        !           134:        struct udphdr *uh;
        !           135:        struct udpiphdr *ui;
        !           136:        struct ip tip;
        !           137:        u_int16_t etype;        /* host order */
        !           138:
        !           139: #ifdef NET_DEBUG
        !           140:        if (debug)
        !           141:                printf("readudp: called\n");
        !           142: #endif
        !           143:
        !           144:        uh = (struct udphdr *)pkt - 1;
        !           145:        ip = (struct ip *)uh - 1;
        !           146:
        !           147:        n = readether(d, ip, len + sizeof(*ip) + sizeof(*uh), tleft, &etype);
        !           148:        if (n < 0 || (size_t)n < sizeof(*ip) + sizeof(*uh))
        !           149:                return -1;
        !           150:
        !           151:        /* Ethernet address checks now in readether() */
        !           152:
        !           153:        /* Need to respond to ARP requests. */
        !           154:        if (etype == ETHERTYPE_ARP) {
        !           155:                struct arphdr *ah = (void *)ip;
        !           156:                if (ah->ar_op == htons(ARPOP_REQUEST)) {
        !           157:                        /* Send ARP reply */
        !           158:                        arp_reply(d, ah);
        !           159:                }
        !           160:                return -1;
        !           161:        }
        !           162:
        !           163:        if (etype != ETHERTYPE_IP) {
        !           164: #ifdef NET_DEBUG
        !           165:                if (debug)
        !           166:                        printf("readudp: not IP. ether_type=%x\n", etype);
        !           167: #endif
        !           168:                return -1;
        !           169:        }
        !           170:
        !           171:        /* Check ip header */
        !           172:        if (ip->ip_v != IPVERSION ||
        !           173:            ip->ip_p != IPPROTO_UDP) {  /* half char */
        !           174: #ifdef NET_DEBUG
        !           175:                if (debug)
        !           176:                        printf("readudp: IP version or not UDP. ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p);
        !           177: #endif
        !           178:                return -1;
        !           179:        }
        !           180:
        !           181:        hlen = ip->ip_hl << 2;
        !           182:        if (hlen < sizeof(*ip) ||
        !           183:            in_cksum(ip, hlen) != 0) {
        !           184: #ifdef NET_DEBUG
        !           185:                if (debug)
        !           186:                        printf("readudp: short hdr or bad cksum.\n");
        !           187: #endif
        !           188:                return -1;
        !           189:        }
        !           190:        NTOHS(ip->ip_len);
        !           191:        if (n < ip->ip_len) {
        !           192: #ifdef NET_DEBUG
        !           193:                if (debug)
        !           194:                        printf("readudp: bad length %d < %d.\n", n, ip->ip_len);
        !           195: #endif
        !           196:                return -1;
        !           197:        }
        !           198:        if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) {
        !           199: #ifdef NET_DEBUG
        !           200:                if (debug) {
        !           201:                        printf("readudp: bad saddr %s != ", inet_ntoa(d->myip));
        !           202:                        printf("%s\n", inet_ntoa(ip->ip_dst));
        !           203:                }
        !           204: #endif
        !           205:                return -1;
        !           206:        }
        !           207:
        !           208:        /* If there were ip options, make them go away */
        !           209:        if (hlen != sizeof(*ip)) {
        !           210:                bcopy(((u_char *)ip) + hlen, uh, len - hlen);
        !           211:                ip->ip_len = sizeof(*ip);
        !           212:                n -= hlen - sizeof(*ip);
        !           213:        }
        !           214:        if (uh->uh_dport != d->myport) {
        !           215: #ifdef NET_DEBUG
        !           216:                if (debug)
        !           217:                        printf("readudp: bad dport %d != %d\n",
        !           218:                                d->myport, ntohs(uh->uh_dport));
        !           219: #endif
        !           220:                return -1;
        !           221:        }
        !           222:
        !           223:        if (uh->uh_sum) {
        !           224:                n = ntohs(uh->uh_ulen) + sizeof(*ip);
        !           225:                if (n > RECV_SIZE - ETHER_SIZE) {
        !           226:                        printf("readudp: huge packet, udp len %ld\n", (long)n);
        !           227:                        return -1;
        !           228:                }
        !           229:
        !           230:                /* Check checksum (must save and restore ip header) */
        !           231:                tip = *ip;
        !           232:                ui = (struct udpiphdr *)ip;
        !           233:                bzero(ui->ui_x1, sizeof(ui->ui_x1));
        !           234:                ui->ui_len = uh->uh_ulen;
        !           235:                if (in_cksum(ui, n) != 0) {
        !           236: #ifdef NET_DEBUG
        !           237:                        if (debug)
        !           238:                                printf("readudp: bad cksum\n");
        !           239: #endif
        !           240:                        *ip = tip;
        !           241:                        return -1;
        !           242:                }
        !           243:                *ip = tip;
        !           244:        }
        !           245:        NTOHS(uh->uh_dport);
        !           246:        NTOHS(uh->uh_sport);
        !           247:        NTOHS(uh->uh_ulen);
        !           248:        if (uh->uh_ulen < sizeof(*uh)) {
        !           249: #ifdef NET_DEBUG
        !           250:                if (debug)
        !           251:                        printf("readudp: bad udp len %d < %d\n",
        !           252:                                uh->uh_ulen, sizeof(*uh));
        !           253: #endif
        !           254:                return -1;
        !           255:        }
        !           256:
        !           257:        n -= sizeof(*ip) + sizeof(*uh);
        !           258:        return (n);
        !           259: }
        !           260:
        !           261: /*
        !           262:  * Send a packet and wait for a reply, with exponential backoff.
        !           263:  *
        !           264:  * The send routine must return the actual number of bytes written.
        !           265:  *
        !           266:  * The receive routine can indicate success by returning the number of
        !           267:  * bytes read; it can return 0 to indicate EOF; it can return -1 with a
        !           268:  * non-zero errno to indicate failure; finally, it can return -1 with a
        !           269:  * zero errno to indicate it isn't done yet.
        !           270:  */
        !           271: ssize_t
        !           272: sendrecv(struct iodesc *d, ssize_t (*sproc)(struct iodesc *, void *, size_t),
        !           273:     void *sbuf, size_t ssize,
        !           274:     ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t),
        !           275:     void *rbuf, size_t rsize)
        !           276: {
        !           277:        ssize_t cc;
        !           278:        time_t t, tmo, tlast;
        !           279:        long tleft;
        !           280:
        !           281: #ifdef NET_DEBUG
        !           282:        if (debug)
        !           283:                printf("sendrecv: called\n");
        !           284: #endif
        !           285:
        !           286:        tmo = MINTMO;
        !           287:        tlast = tleft = 0;
        !           288:        t = getsecs();
        !           289:        for (;;) {
        !           290:                if (tleft <= 0) {
        !           291:                        if (tmo >= MAXTMO) {
        !           292:                                errno = ETIMEDOUT;
        !           293:                                return -1;
        !           294:                        }
        !           295:                        cc = (*sproc)(d, sbuf, ssize);
        !           296:                        if (cc < 0 || (size_t)cc < ssize)
        !           297:                                panic("sendrecv: short write! (%d < %d)",
        !           298:                                    cc, ssize);
        !           299:
        !           300:                        tleft = tmo;
        !           301:                        tmo <<= 1;
        !           302:                        if (tmo > MAXTMO)
        !           303:                                tmo = MAXTMO;
        !           304:                        tlast = t;
        !           305:                }
        !           306:
        !           307:                /* Try to get a packet and process it. */
        !           308:                cc = (*rproc)(d, rbuf, rsize, tleft);
        !           309:                /* Return on data, EOF or real error. */
        !           310:                if (cc != -1 || errno != 0)
        !           311:                        return (cc);
        !           312:
        !           313:                /* Timed out or didn't get the packet we're waiting for */
        !           314:                t = getsecs();
        !           315:                tleft -= t - tlast;
        !           316:                tlast = t;
        !           317:        }
        !           318: }
        !           319:
        !           320: /*
        !           321:  * Like inet_addr() in the C library, but we only accept base-10.
        !           322:  * Return values are in network order.
        !           323:  */
        !           324: n_long
        !           325: inet_addr(char *cp)
        !           326: {
        !           327:        u_long val;
        !           328:        int n;
        !           329:        char c;
        !           330:        u_int parts[4];
        !           331:        u_int *pp = parts;
        !           332:
        !           333:        for (;;) {
        !           334:                /*
        !           335:                 * Collect number up to ``.''.
        !           336:                 * Values are specified as for C:
        !           337:                 * 0x=hex, 0=octal, other=decimal.
        !           338:                 */
        !           339:                val = 0;
        !           340:                while ((c = *cp) != '\0') {
        !           341:                        if (c >= '0' && c <= '9') {
        !           342:                                val = (val * 10) + (c - '0');
        !           343:                                cp++;
        !           344:                                continue;
        !           345:                        }
        !           346:                        break;
        !           347:                }
        !           348:                if (*cp == '.') {
        !           349:                        /*
        !           350:                         * Internet format:
        !           351:                         *      a.b.c.d
        !           352:                         *      a.b.c   (with c treated as 16-bits)
        !           353:                         *      a.b     (with b treated as 24 bits)
        !           354:                         */
        !           355:                        if (pp >= parts + 3 || val > 0xff)
        !           356:                                goto bad;
        !           357:                        *pp++ = val, cp++;
        !           358:                } else
        !           359:                        break;
        !           360:        }
        !           361:        /*
        !           362:         * Check for trailing characters.
        !           363:         */
        !           364:        if (*cp != '\0')
        !           365:                goto bad;
        !           366:
        !           367:        /*
        !           368:         * Concoct the address according to
        !           369:         * the number of parts specified.
        !           370:         */
        !           371:        n = pp - parts + 1;
        !           372:        switch (n) {
        !           373:
        !           374:        case 1:                         /* a -- 32 bits */
        !           375:                break;
        !           376:
        !           377:        case 2:                         /* a.b -- 8.24 bits */
        !           378:                if (val > 0xffffff)
        !           379:                        goto bad;
        !           380:                val |= parts[0] << 24;
        !           381:                break;
        !           382:
        !           383:        case 3:                         /* a.b.c -- 8.8.16 bits */
        !           384:                if (val > 0xffff)
        !           385:                        goto bad;
        !           386:                val |= (parts[0] << 24) | (parts[1] << 16);
        !           387:                break;
        !           388:
        !           389:        case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
        !           390:                if (val > 0xff)
        !           391:                        goto bad;
        !           392:                val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
        !           393:                break;
        !           394:        }
        !           395:
        !           396:        return (htonl(val));
        !           397:  bad:
        !           398:        return (htonl(INADDR_NONE));
        !           399: }
        !           400:
        !           401: char *
        !           402: inet_ntoa(struct in_addr ia)
        !           403: {
        !           404:        return (intoa(ia.s_addr));
        !           405: }
        !           406:
        !           407: /* Similar to inet_ntoa() */
        !           408: char *
        !           409: intoa(n_long addr)
        !           410: {
        !           411:        char *cp;
        !           412:        u_int byte;
        !           413:        int n;
        !           414:        static char buf[sizeof(".255.255.255.255")];
        !           415:
        !           416:        NTOHL(addr);
        !           417:        cp = &buf[sizeof buf];
        !           418:        *--cp = '\0';
        !           419:
        !           420:        n = 4;
        !           421:        do {
        !           422:                byte = addr & 0xff;
        !           423:                *--cp = byte % 10 + '0';
        !           424:                byte /= 10;
        !           425:                if (byte > 0) {
        !           426:                        *--cp = byte % 10 + '0';
        !           427:                        byte /= 10;
        !           428:                        if (byte > 0)
        !           429:                                *--cp = byte + '0';
        !           430:                }
        !           431:                *--cp = '.';
        !           432:                addr >>= 8;
        !           433:        } while (--n > 0);
        !           434:
        !           435:        return (cp+1);
        !           436: }
        !           437:
        !           438: static char *
        !           439: number(char *s, int *n)
        !           440: {
        !           441:        for (*n = 0; isdigit(*s); s++)
        !           442:                *n = (*n * 10) + *s - '0';
        !           443:        return s;
        !           444: }
        !           445:
        !           446: n_long
        !           447: ip_convertaddr(char *p)
        !           448: {
        !           449: #define IP_ANYADDR     0
        !           450:        n_long addr = 0, n;
        !           451:
        !           452:        if (p == (char *)0 || *p == '\0')
        !           453:                return IP_ANYADDR;
        !           454:        p = number(p, &n);
        !           455:        addr |= (n << 24) & 0xff000000;
        !           456:        if (*p == '\0' || *p++ != '.')
        !           457:                return IP_ANYADDR;
        !           458:        p = number(p, &n);
        !           459:        addr |= (n << 16) & 0xff0000;
        !           460:        if (*p == '\0' || *p++ != '.')
        !           461:                return IP_ANYADDR;
        !           462:        p = number(p, &n);
        !           463:        addr |= (n << 8) & 0xff00;
        !           464:        if (*p == '\0' || *p++ != '.')
        !           465:                return IP_ANYADDR;
        !           466:        p = number(p, &n);
        !           467:        addr |= n & 0xff;
        !           468:        if (*p != '\0')
        !           469:                return IP_ANYADDR;
        !           470:
        !           471:        return htonl(addr);
        !           472: }

CVSweb