1 /* $NetBSD: etherfun.c,v 1.8 2006/05/20 20:37:15 mrg Exp $ */
5 * Copyright (c) 1995 Charles D. Cranor and Seth Widoff
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
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.
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.
39 /* Construct and send a rev arp packet */
45 for (i
= 0; i
< 6; i
++) {
46 eh
->ether_dhost
[i
] = 0xff;
48 memcpy(eh
->ether_shost
, myea
, 6);
49 eh
->ether_type
= ETYPE_RARP
;
51 rarp
->ar_hrd
= 1; /* hardware type is 1 */
52 rarp
->ar_pro
= PTYPE_IP
;
53 rarp
->ar_hln
= 6; /* length of hardware address is 6 bytes */
54 rarp
->ar_pln
= 4; /* length of ip address is 4 byte */
55 rarp
->ar_op
= OPCODE_RARP
;
56 memcpy(rarp
->arp_sha
, myea
, sizeof(myea
));
57 memcpy(rarp
->arp_tha
, myea
, sizeof(myea
));
58 for (i
= 0; i
< 4; i
++) {
59 rarp
->arp_spa
[i
] = rarp
->arp_tpa
[i
] = 0x00;
65 /* Receive and disassemble the rev_arp reply */
71 le_get(buf
, sizeof(buf
), 6);
72 if (eh
->ether_type
== ETYPE_RARP
&& rarp
->ar_op
== OPCODE_REPLY
) {
73 memcpy(myip
, rarp
->arp_tpa
, sizeof(rarp
->arp_tpa
));
74 memcpy(servip
, rarp
->arp_spa
, sizeof(rarp
->arp_spa
));
75 memcpy(servea
, rarp
->arp_sha
, sizeof(rarp
->arp_sha
));
81 /* Try to get a reply to a rev arp request */
98 /* Send a tftp read request or acknowledgement
99 mesgtype 0 is a read request, 1 is an aknowledgement */
102 do_send_tftp(int mesgtype
)
104 u_long res
, iptmp
, lcv
;
108 tot
= tftp_r
+ (sizeof(MSG
) - 1);
109 myport
= (u_short
)time();
112 servport
= FTP_PORT
; /* to start */
114 tot
= (u_char
*)tftp_a
+ 4;
117 memcpy (eh
->ether_dhost
, servea
, sizeof(servea
));
118 memcpy (eh
->ether_shost
, myea
, sizeof(myea
));
119 eh
->ether_type
= ETYPE_IP
;
121 iph
->ip_v
= IP_VERSION
;
122 iph
->ip_hl
= IP_HLEN
;
123 iph
->ip_tos
= 0; /* type of service is 0 */
124 iph
->ip_id
= 0; /* id field is 0 */
126 iph
->ip_ttl
= 3; /* time to live is 3 seconds/hops */
128 memcpy(iph
->ip_src
, myip
, sizeof(myip
));
129 memcpy(iph
->ip_dst
, servip
, sizeof(servip
));
131 iph
->ip_len
= tot
- (u_char
*)iph
;
132 res
= oc_cksum(iph
, sizeof(struct ip
), 0);
133 iph
->ip_sum
= 0xffff & ~res
;
134 udph
->uh_sport
= myport
;
135 udph
->uh_dport
= servport
;
139 tftp_a
->op_code
= FTPOP_ACKN
;
140 tftp_a
->block
= (u_short
)(mesgtype
);
142 memcpy (&iptmp
, myip
, sizeof(iptmp
));
143 memcpy(tftp_r
, MSG
, (sizeof(MSG
)-1));
144 for (lcv
= 9; lcv
>= 2; lcv
--) {
145 tftp_r
[lcv
] = HEXDIGITS
[iptmp
& 0xF];
151 udph
->uh_ulen
= tot
- (u_char
*)udph
;
153 le_put(buf
, tot
- buf
);
156 /* Attempt to tftp a file and read it into memory */
161 int fail
= 0, oldlen
;
162 char *loadat
= (char *)LOAD_ADDR
;
167 if (le_get(buf
, sizeof(buf
), 5) == 0) { /* timeout occurred */
169 do_send_tftp(last_ack
);
179 printf("%x \r", tftp
->info
.block
*512);
180 if ((eh
->ether_type
!= ETYPE_IP
) ||
181 (iph
->ip_p
!= IPP_UDP
)) {
185 if (servport
== FTP_PORT
) servport
= udph
->uh_sport
;
186 if (tftp
->info
.op_code
== FTPOP_ERR
) {
187 printf("TFTP: Download error %d: %s\n",
188 tftp
->info
.block
, tftp
->data
);
191 if (tftp
->info
.block
!= last_ack
+ 1) {
192 /* we received the wrong block */
193 if (tftp
->info
.block
< last_ack
+1) {
194 /* ackn whatever we received */
195 do_send_tftp(tftp
->info
.block
);
197 /* ackn the last confirmed block */
198 do_send_tftp(last_ack
);
201 } else { /* we got the right block */
204 oldlen
= udph
->uh_ulen
;
205 do_send_tftp( last_ack
);
207 printf("memcpy %x %x %d\n", loadat
,
208 &tftp
->data
, oldlen
- 12);
210 memcpy(loadat
, &tftp
->data
, oldlen
- 12);
211 loadat
+= oldlen
- 12;
212 if (oldlen
< (8 + 4 + 512)) {