[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

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