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