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

Annotation of sys/lib/libsa/arp.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: arp.c,v 1.11 2003/08/11 06:23:09 deraadt Exp $        */
                      2: /*     $NetBSD: arp.c,v 1.15 1996/10/13 02:28:58 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: arp.c,v 1.5 93/07/15 05:52:26 leres Exp  (LBL)
                     41:  */
                     42:
                     43: #include <sys/types.h>
                     44: #include <sys/socket.h>
                     45: #include <net/if.h>
                     46: #include <netinet/in.h>
                     47:
                     48: #include <netinet/if_ether.h>
                     49: #include <netinet/in_systm.h>
                     50:
                     51: #include "stand.h"
                     52: #include "net.h"
                     53:
                     54: /* Cache stuff */
                     55: #define ARP_NUM 8                      /* need at most 3 arp entries */
                     56:
                     57: struct arp_list {
                     58:        struct in_addr  addr;
                     59:        u_char          ea[6];
                     60: } arp_list[ARP_NUM] = {
                     61:        /* XXX - net order `INADDR_BROADCAST' must be a constant */
                     62:        { {0xffffffff}, BA }
                     63: };
                     64: int arp_num = 1;
                     65:
                     66: /* Local forwards */
                     67: static ssize_t arpsend(struct iodesc *, void *, size_t);
                     68: static ssize_t arprecv(struct iodesc *, void *, size_t, time_t);
                     69:
                     70: /* Broadcast an ARP packet, asking who has addr on interface d */
                     71: u_char *
                     72: arpwhohas(struct iodesc *d, struct in_addr addr)
                     73: {
                     74:        int i;
                     75:        struct ether_arp *ah;
                     76:        struct arp_list *al;
                     77:        struct {
                     78:                struct ether_header eh;
                     79:                struct {
                     80:                        struct ether_arp arp;
                     81:                        u_char pad[18];         /* 60 - sizeof(...) */
                     82:                } data;
                     83:        } wbuf;
                     84:        struct {
                     85:                struct ether_header eh;
                     86:                struct {
                     87:                        struct ether_arp arp;
                     88:                        u_char pad[24];         /* extra space */
                     89:                } data;
                     90:        } rbuf;
                     91:
                     92:        /* Try for cached answer first */
                     93:        for (i = 0, al = arp_list; i < arp_num; ++i, ++al)
                     94:                if (addr.s_addr == al->addr.s_addr)
                     95:                        return (al->ea);
                     96:
                     97:        /* Don't overflow cache */
                     98:        if (arp_num > ARP_NUM - 1) {
                     99:                arp_num = 1;    /* recycle */
                    100:                printf("arpwhohas: overflowed arp_list!\n");
                    101:        }
                    102:
                    103: #ifdef ARP_DEBUG
                    104:        if (debug)
                    105:            printf("arpwhohas: send request for %s\n", inet_ntoa(addr));
                    106: #endif
                    107:
                    108:        bzero((char *)&wbuf.data, sizeof(wbuf.data));
                    109:        ah = &wbuf.data.arp;
                    110:        ah->arp_hrd = htons(ARPHRD_ETHER);
                    111:        ah->arp_pro = htons(ETHERTYPE_IP);
                    112:        ah->arp_hln = sizeof(ah->arp_sha); /* hardware address length */
                    113:        ah->arp_pln = sizeof(ah->arp_spa); /* protocol address length */
                    114:        ah->arp_op = htons(ARPOP_REQUEST);
                    115:        MACPY(d->myea, ah->arp_sha);
                    116:        bcopy(&d->myip, ah->arp_spa, sizeof(ah->arp_spa));
                    117:        /* Leave zeros in arp_tha */
                    118:        bcopy(&addr, ah->arp_tpa, sizeof(ah->arp_tpa));
                    119:
                    120:        /* Store ip address in cache (incomplete entry). */
                    121:        al->addr = addr;
                    122:
                    123:        i = sendrecv(d,
                    124:            arpsend, &wbuf.data, sizeof(wbuf.data),
                    125:            arprecv, &rbuf.data, sizeof(rbuf.data));
                    126:        if (i == -1) {
                    127:                panic("arp: no response for %s", inet_ntoa(addr));
                    128:        }
                    129:
                    130:        /* Store ethernet address in cache */
                    131:        ah = &rbuf.data.arp;
                    132: #ifdef ARP_DEBUG
                    133:        if (debug) {
                    134:                printf("arp: response from %s\n",
                    135:                    ether_sprintf(rbuf.eh.ether_shost));
                    136:                printf("arp: cacheing %s --> %s\n",
                    137:                    inet_ntoa(addr), ether_sprintf(ah->arp_sha));
                    138:        }
                    139: #endif
                    140:        MACPY(ah->arp_sha, al->ea);
                    141:        ++arp_num;
                    142:
                    143:        return (al->ea);
                    144: }
                    145:
                    146: static ssize_t
                    147: arpsend(struct iodesc *d, void *pkt, size_t len)
                    148: {
                    149:
                    150: #ifdef ARP_DEBUG
                    151:        if (debug)
                    152:                printf("arpsend: called\n");
                    153: #endif
                    154:
                    155:        return (sendether(d, pkt, len, bcea, ETHERTYPE_ARP));
                    156: }
                    157:
                    158: /*
                    159:  * Returns 0 if this is the packet we're waiting for
                    160:  * else -1 (and errno == 0)
                    161:  */
                    162: static ssize_t
                    163: arprecv(struct iodesc *d, void *pkt, size_t len, time_t tleft)
                    164: {
                    165:        ssize_t n;
                    166:        struct ether_arp *ah;
                    167:        u_int16_t etype;        /* host order */
                    168:
                    169: #ifdef ARP_DEBUG
                    170:        if (debug)
                    171:                printf("arprecv: ");
                    172: #endif
                    173:
                    174:        n = readether(d, pkt, len, tleft, &etype);
                    175:        errno = 0;      /* XXX */
                    176:        if (n < 0 || (size_t)n < sizeof(struct ether_arp)) {
                    177: #ifdef ARP_DEBUG
                    178:                if (debug)
                    179:                        printf("bad len=%d\n", n);
                    180: #endif
                    181:                return (-1);
                    182:        }
                    183:
                    184:        if (etype != ETHERTYPE_ARP) {
                    185: #ifdef ARP_DEBUG
                    186:                if (debug)
                    187:                        printf("not arp type=%d\n", etype);
                    188: #endif
                    189:                return (-1);
                    190:        }
                    191:
                    192:        /* Ethernet address now checked in readether() */
                    193:
                    194:        ah = (struct ether_arp *)pkt;
                    195:        if (ah->arp_hrd != htons(ARPHRD_ETHER) ||
                    196:            ah->arp_pro != htons(ETHERTYPE_IP) ||
                    197:            ah->arp_hln != sizeof(ah->arp_sha) ||
                    198:            ah->arp_pln != sizeof(ah->arp_spa)) {
                    199: #ifdef ARP_DEBUG
                    200:                if (debug)
                    201:                        printf("bad hrd/pro/hln/pln\n");
                    202: #endif
                    203:                return (-1);
                    204:        }
                    205:
                    206:        if (ah->arp_op == htons(ARPOP_REQUEST)) {
                    207: #ifdef ARP_DEBUG
                    208:                if (debug)
                    209:                        printf("is request\n");
                    210: #endif
                    211:                arp_reply(d, ah);
                    212:                return (-1);
                    213:        }
                    214:
                    215:        if (ah->arp_op != htons(ARPOP_REPLY)) {
                    216: #ifdef ARP_DEBUG
                    217:                if (debug)
                    218:                        printf("not ARP reply\n");
                    219: #endif
                    220:                return (-1);
                    221:        }
                    222:
                    223:        /* Is the reply from the source we want? */
                    224:        if (bcmp(&arp_list[arp_num].addr, ah->arp_spa,
                    225:            sizeof(ah->arp_spa))) {
                    226: #ifdef ARP_DEBUG
                    227:                if (debug)
                    228:                        printf("unwanted address\n");
                    229: #endif
                    230:                return (-1);
                    231:        }
                    232:        /* We don't care who the reply was sent to. */
                    233:
                    234:        /* We have our answer. */
                    235: #ifdef ARP_DEBUG
                    236:        if (debug)
                    237:                printf("got it\n");
                    238: #endif
                    239:        return (n);
                    240: }
                    241:
                    242: /*
                    243:  * Convert an ARP request into a reply and send it.
                    244:  * Notes:  Re-uses buffer.  Pad to length = 46.
                    245:  */
                    246: void
                    247: arp_reply(struct iodesc *d, void *pkt)
                    248: {
                    249:        struct ether_arp *arp = pkt;
                    250:
                    251:        if (arp->arp_hrd != htons(ARPHRD_ETHER) ||
                    252:            arp->arp_pro != htons(ETHERTYPE_IP) ||
                    253:            arp->arp_hln != sizeof(arp->arp_sha) ||
                    254:            arp->arp_pln != sizeof(arp->arp_spa)) {
                    255: #ifdef ARP_DEBUG
                    256:                if (debug)
                    257:                        printf("arp_reply: bad hrd/pro/hln/pln\n");
                    258: #endif
                    259:                return;
                    260:        }
                    261:
                    262:        if (arp->arp_op != htons(ARPOP_REQUEST)) {
                    263: #ifdef ARP_DEBUG
                    264:                if (debug)
                    265:                        printf("arp_reply: not request!\n");
                    266: #endif
                    267:                return;
                    268:        }
                    269:
                    270:        /* If we are not the target, ignore the request. */
                    271:        if (bcmp(arp->arp_tpa, &d->myip, sizeof(arp->arp_tpa)))
                    272:                return;
                    273:
                    274: #ifdef ARP_DEBUG
                    275:        if (debug) {
                    276:                printf("arp_reply: to %s\n", ether_sprintf(arp->arp_sha));
                    277:        }
                    278: #endif
                    279:
                    280:        arp->arp_op = htons(ARPOP_REPLY);
                    281:        /* source becomes target */
                    282:        bcopy(arp->arp_sha, arp->arp_tha, sizeof(arp->arp_tha));
                    283:        bcopy(arp->arp_spa, arp->arp_tpa, sizeof(arp->arp_tpa));
                    284:        /* here becomes source */
                    285:        bcopy(d->myea,  arp->arp_sha, sizeof(arp->arp_sha));
                    286:        bcopy(&d->myip, arp->arp_spa, sizeof(arp->arp_spa));
                    287:
                    288:        /*
                    289:         * No need to get fancy here.  If the send fails, the
                    290:         * requestor will just ask again.
                    291:         */
                    292:        (void) sendether(d, pkt, sizeof(*arp) + 18,
                    293:            arp->arp_tha, ETHERTYPE_ARP);
                    294: }

CVSweb