[BACK]Return to etherfun.c CVS log [TXT][DIR] Up to [local] / sys / arch / mvme88k / stand / sboot

Annotation of sys/arch/mvme88k/stand/sboot/etherfun.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: etherfun.c,v 1.3 2001/09/20 17:02:31 mpech Exp $      */
        !             2:
        !             3: /*
        !             4:  *
        !             5:  * Copyright (c) 1995 Charles D. Cranor and Seth Widoff
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *      This product includes software developed by Charles D. Cranor
        !            19:  *     and Seth Widoff.
        !            20:  * 4. The name of the author may not be used to endorse or promote products
        !            21:  *    derived from this software without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  */
        !            34: /* etherfun.c */
        !            35:
        !            36: #include <sys/cdefs.h>
        !            37: #include "sboot.h"
        !            38: #include "etherfun.h"
        !            39:
        !            40: /* Construct and send a rev arp packet */
        !            41: void
        !            42: do_rev_arp()
        !            43: {
        !            44:        int     i;
        !            45:
        !            46:        for (i = 0; i < 6; i++)
        !            47:                eh->ether_dhost[i] = 0xff;
        !            48:
        !            49:        bcopy(myea, eh->ether_shost, 6);
        !            50:        eh->ether_type = ETYPE_RARP;
        !            51:
        !            52:        rarp->ar_hrd = 1;       /* hardware type is 1 */
        !            53:        rarp->ar_pro = PTYPE_IP;
        !            54:        rarp->ar_hln = 6;       /* length of hardware address is 6 bytes */
        !            55:        rarp->ar_pln = 4;       /* length of ip address is 4 byte */
        !            56:        rarp->ar_op = OPCODE_RARP;
        !            57:        bcopy(myea, rarp->arp_sha, sizeof(myea));
        !            58:        bcopy(myea, rarp->arp_tha, sizeof(myea));
        !            59:        for (i = 0; i < 4; i++)
        !            60:                rarp->arp_spa[i] = rarp->arp_tpa[i] = 0x00;
        !            61:
        !            62:        le_put(buf, 76);
        !            63: }
        !            64:
        !            65: /* Receive and disassemble the rev_arp reply */
        !            66: int
        !            67: get_rev_arp()
        !            68: {
        !            69:        le_get(buf, sizeof(buf), 6);
        !            70:        if (eh->ether_type == ETYPE_RARP && rarp->ar_op == OPCODE_REPLY) {
        !            71:                bcopy(rarp->arp_tpa, myip, sizeof(rarp->arp_tpa));
        !            72:                bcopy(rarp->arp_spa, servip, sizeof(rarp->arp_spa));
        !            73:                bcopy(rarp->arp_sha, servea, sizeof(rarp->arp_sha));
        !            74:                return (1);
        !            75:        }
        !            76:        return (0);
        !            77: }
        !            78:
        !            79: /* Try to get a reply to a rev arp request */
        !            80: int
        !            81: rev_arp()
        !            82: {
        !            83:        int     tries = 0;
        !            84:        while (tries < 5) {
        !            85:                do_rev_arp();
        !            86:                if (get_rev_arp())
        !            87:                        return (1);
        !            88:                tries++;
        !            89:        }
        !            90:        return (0);
        !            91: }
        !            92:
        !            93: /*
        !            94:  * Send a tftp read request or acknowledgement
        !            95:  * mesgtype 0 is a read request, 1 is an
        !            96:  * acknowledgement
        !            97:  */
        !            98: void
        !            99: do_send_tftp(mesgtype)
        !           100:        int mesgtype;
        !           101: {
        !           102:        u_long  res, iptmp, lcv;
        !           103:        char   *tot;
        !           104:
        !           105:        if (mesgtype == 0) {
        !           106:                tot = tftp_r + (sizeof(MSG) - 1);
        !           107:                myport = (u_short) time();
        !           108:                if (myport < 1000)
        !           109:                        myport += 1000;
        !           110:                servport = FTP_PORT;    /* to start */
        !           111:        } else {
        !           112:                tot = (char *) tftp_a + 4;
        !           113:        }
        !           114:
        !           115:        bcopy(servea, eh->ether_dhost, sizeof(servea));
        !           116:        bcopy(myea, eh->ether_shost, sizeof(myea));
        !           117:        eh->ether_type = ETYPE_IP;
        !           118:
        !           119:        iph->ip_v = IP_VERSION;
        !           120:        iph->ip_hl = IP_HLEN;
        !           121:        iph->ip_tos = 0;        /* type of service is 0 */
        !           122:        iph->ip_id = 0;         /* id field is 0 */
        !           123:        iph->ip_off = IP_DF;
        !           124:        iph->ip_ttl = 3;        /* time to live is 3 seconds/hops */
        !           125:        iph->ip_p = IPP_UDP;
        !           126:        bcopy(myip, iph->ip_src, sizeof(myip));
        !           127:        bcopy(servip, iph->ip_dst, sizeof(servip));
        !           128:        iph->ip_sum = 0;
        !           129:        iph->ip_len = tot - (char *) iph;
        !           130:        res = oc_cksum(iph, sizeof(struct ip), 0);
        !           131:        iph->ip_sum = 0xffff & ~res;
        !           132:        udph->uh_sport = myport;
        !           133:        udph->uh_dport = servport;
        !           134:        udph->uh_sum = 0;
        !           135:
        !           136:        if (mesgtype) {
        !           137:                tftp_a->op_code = FTPOP_ACKN;
        !           138:                tftp_a->block = (u_short) (mesgtype);
        !           139:        } else {
        !           140:                bcopy(myip, &iptmp, sizeof(iptmp));
        !           141:                bcopy(MSG, tftp_r, (sizeof(MSG) - 1));
        !           142:                for (lcv = 9; lcv >= 2; lcv--) {
        !           143:                        tftp_r[lcv] = "0123456789ABCDEF"[iptmp & 0xF];
        !           144:
        !           145:                        iptmp = iptmp >> 4;
        !           146:                }
        !           147:        }
        !           148:
        !           149:        udph->uh_ulen = tot - (char *) udph;
        !           150:
        !           151:        le_put(buf, tot - buf);
        !           152: }
        !           153:
        !           154: /* Attempt to tftp a file and read it into memory */
        !           155: int
        !           156: do_get_file()
        !           157: {
        !           158:        int     fail = 0, oldlen;
        !           159:        char   *loadat = (char *) LOAD_ADDR;
        !           160:        last_ack = 0;
        !           161:
        !           162:        do_send_tftp(READ);
        !           163:        while (1) {
        !           164:                if (le_get(buf, sizeof(buf), 5) == 0) {
        !           165:                        /* timeout occurred */
        !           166:                        if (last_ack)
        !           167:                                do_send_tftp(last_ack);
        !           168:                        else
        !           169:                                do_send_tftp(READ);
        !           170:
        !           171:                        fail++;
        !           172:                        if (fail > 5) {
        !           173:                                printf("\n");
        !           174:                                return (1);
        !           175:                        }
        !           176:                } else {
        !           177:                        printf("%x \r", tftp->info.block * 512);
        !           178:                        if ((eh->ether_type != ETYPE_IP) || (iph->ip_p != IPP_UDP)) {
        !           179:                                fail++;
        !           180:                                continue;
        !           181:                        }
        !           182:                        if (servport == FTP_PORT)
        !           183:                                servport = udph->uh_sport;
        !           184:                        if (tftp->info.op_code == FTPOP_ERR) {
        !           185:                                printf("TFTP: Download error %d: %s\n",
        !           186:                                    tftp->info.block, tftp->data);
        !           187:                                return (1);
        !           188:                        }
        !           189:                        if (tftp->info.block != last_ack + 1) {
        !           190:                                /* we received the wrong block */
        !           191:                                if (tftp->info.block < last_ack + 1) {
        !           192:                                        /* nack whatever we received */
        !           193:                                        do_send_tftp(tftp->info.block);
        !           194:                                } else {
        !           195:                                        /* nack the last confirmed block */
        !           196:                                        do_send_tftp(last_ack);
        !           197:                                }
        !           198:                                fail++;
        !           199:                        } else {/* we got the right block */
        !           200:                                fail = 0;
        !           201:                                last_ack++;
        !           202:                                oldlen = udph->uh_ulen;
        !           203:                                do_send_tftp(last_ack);
        !           204:                                /* printf("bcopy %x %x %d\n", &tftp->data,
        !           205:                                 * loadat, oldlen - 12); */
        !           206:                                bcopy(&tftp->data, loadat, oldlen - 12);
        !           207:                                loadat += oldlen - 12;
        !           208:                                if (oldlen < (8 + 4 + 512)) {
        !           209:                                        printf("\n");
        !           210:                                        return (0);
        !           211:                                }
        !           212:                        }
        !           213:                }
        !           214:        }
        !           215:        printf("\n");
        !           216:        return (0);
        !           217: }

CVSweb