/[gxemul]/upstream/0.3.1/src/net.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.1/src/net.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Mon Oct 8 16:17:52 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 63699 byte(s)
0.3.1
1 /*
2 * Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: net.c,v 1.72 2005/03/14 19:14:05 debug Exp $
29 *
30 * Emulated (ethernet / internet) network support.
31 *
32 *
33 * NOTE: This is just an ugly hack, and just barely enough to get some
34 * Internet networking up and running for the guest OS.
35 *
36 * TODO: o) TCP: fin/ack stuff, and connection time-outs and
37 * connection refused (reset on connect?), resend
38 * data to the guest OS if no ack has arrived for
39 * some time (? buffers?)
40 * http://www.tcpipguide.com/free/
41 * t_TCPConnectionTermination-2.htm
42 * o) remove the netbsd-specific options in the tcp header (?)
43 * o) Outgoing UDP packet fragment support.
44 * o) IPv6 (outgoing, incoming, and the nameserver/gateway)
45 * o) Incoming connections
46 * o) if multiple NICs are connected to the same network,
47 * they should be able to see each other's packets, and
48 * they should have different MAC addresses!
49 *
50 *
51 * The emulated NIC has a MAC address of (for example) 10:20:30:40:50:60.
52 * From the emulated environment, the only other machine existing on the
53 * network is a "gateway" or "firewall", which has an address of
54 * 60:50:40:30:20:10. This module (net.c) contains the emulation of that
55 * gateway. It works like a NAT firewall, but emulated in userland software.
56 *
57 * The gateway uses IPv4 address 10.0.0.254, the guest OS (inside the
58 * emulator) could use any 10.x.x.x address, except 10.0.0.254. A suitable
59 * choice is, for example 10.0.0.1.
60 *
61 *
62 * NOTE: The 'extra' argument used in many functions in this file is a pointer
63 * to something unique for each controller, so that if multiple controllers
64 * are emulated concurrently, they will not get packets that aren't meant
65 * for some other controller.
66 *
67 *
68 * <------------------ a network ------------------------------>
69 * ^ ^ ^
70 * | | |
71 * a NIC connected another NIC the gateway
72 * to the network |
73 * v
74 * outside
75 * world
76 *
77 * The gateway isn't connected as a NIC, but is an "implicit" machine on the
78 * network.
79 *
80 * (See http://www.sinclair.org.au/keith/networking/vendor.html for a list
81 * of ethernet MAC assignments.)
82 */
83
84 #include <stdio.h>
85 #include <stdlib.h>
86 #include <string.h>
87 #include <unistd.h>
88 #include <errno.h>
89 #include <sys/types.h>
90 #include <sys/time.h>
91 #include <sys/socket.h>
92 #include <netinet/in.h>
93 #include <arpa/inet.h>
94 #include <netdb.h>
95 #include <fcntl.h>
96 #include <signal.h>
97
98 #include "machine.h"
99 #include "misc.h"
100 #include "net.h"
101
102
103 /* #define debug fatal */
104
105
106 #define ADDR_IPV4 1
107 #define ADDR_IPV6 2
108 #define ADDR_ETHERNET 3
109
110
111 /*
112 * net_debugaddr():
113 *
114 * Print an address using debug().
115 */
116 static void net_debugaddr(void *ipv4_addr, int type)
117 {
118 int i;
119 unsigned char *p = ipv4_addr;
120
121 switch (type) {
122 case ADDR_IPV4:
123 for (i=0; i<4; i++)
124 debug("%s%i", i? "." : "", p[i]);
125 break;
126 case ADDR_IPV6:
127 for (i=0; i<16; i+=2)
128 debug("%s%4x", i? ":" : "", p[i] * 256 + p[i+1]);
129 break;
130 case ADDR_ETHERNET:
131 for (i=0; i<6; i++)
132 debug("%s%02x", i? ":" : "", p[i]);
133 break;
134 default:
135 fatal("( net_debugaddr(): UNIMPLEMTED type %i )\n", type);
136 }
137 }
138
139
140 /*
141 * net_generate_unique_mac():
142 *
143 * Generate a "unique" serial number for a machine. The machine's serial
144 * number is combined with the machine's current number of NICs to form a
145 * more-or-less valid MAC address.
146 *
147 * The return value (6 bytes) are written to macbuf.
148 */
149 void net_generate_unique_mac(struct machine *machine, unsigned char *macbuf)
150 {
151 int x, y;
152
153 if (macbuf == NULL || machine == NULL) {
154 fatal("**\n** net_generate_unique_mac(): NULL ptr\n**\n");
155 return;
156 }
157
158 x = machine->serial_nr;
159 y = machine->nr_of_nics;
160
161 /*
162 * TODO: What is a good starting value? Right now, it looks like this:
163 *
164 * +-----------+-------------------+-------------+-------------+
165 * | 16 bits | 16 bits machine | 12 bits | 4 bits of |
166 * | fixed | serial nr | NIC nr(*) | zeroes |
167 * +-----------+-------------------+-------------+-------------+
168 *
169 * (*) = almost
170 */
171 macbuf[0] = 0x10;
172 macbuf[1] = 0x20;
173 macbuf[2] = x >> 8;
174 macbuf[3] = x & 255;
175 macbuf[4] = y / 15;
176 macbuf[5] = (y % 15) * 0x10 + 0x10;
177
178 /* TODO: Remember the mac addresses somewhere? */
179 machine->nr_of_nics ++;
180 }
181
182
183 /*
184 * net_ip_checksum():
185 *
186 * Fill in an IP header checksum. (This works for ICMP too.)
187 * chksumoffset should be 10 for IP headers, and len = 20.
188 * For ICMP packets, chksumoffset = 2 and len = length of the ICMP packet.
189 */
190 void net_ip_checksum(unsigned char *ip_header, int chksumoffset, int len)
191 {
192 int i;
193 uint32_t sum = 0;
194
195 for (i=0; i<len; i+=2)
196 if (i != chksumoffset) {
197 uint16_t w = (ip_header[i] << 8) + ip_header[i+1];
198 sum += w;
199 while (sum > 65535) {
200 int to_add = sum >> 16;
201 sum = (sum & 0xffff) + to_add;
202 }
203 }
204
205 sum ^= 0xffff;
206 ip_header[chksumoffset + 0] = sum >> 8;
207 ip_header[chksumoffset + 1] = sum & 0xff;
208 }
209
210
211 /*
212 * net_ip_tcp_checksum():
213 *
214 * Fill in a TCP header checksum. This differs slightly from the IP
215 * checksum. The checksum is calculated on a pseudo header, the actual
216 * TCP header, and the data. This is what the pseudo header looks like:
217 *
218 * uint32_t srcaddr;
219 * uint32_t dstaddr;
220 * uint16_t protocol; (= 6 for tcp)
221 * uint16_t tcp_len;
222 *
223 * tcp_len is length of header PLUS data. The psedo header is created
224 * internally here, and does not need to be supplied by the caller.
225 */
226 static void net_ip_tcp_checksum(unsigned char *tcp_header, int chksumoffset,
227 int tcp_len, unsigned char *srcaddr, unsigned char *dstaddr,
228 int udpflag)
229 {
230 int i, pad = 0;
231 unsigned char pseudoh[12];
232 uint32_t sum = 0;
233
234 memcpy(pseudoh + 0, srcaddr, 4);
235 memcpy(pseudoh + 4, dstaddr, 4);
236 pseudoh[8] = 0x00;
237 pseudoh[9] = udpflag? 17 : 6;
238 pseudoh[10] = tcp_len >> 8;
239 pseudoh[11] = tcp_len & 255;
240
241 for (i=0; i<12; i+=2) {
242 uint16_t w = (pseudoh[i] << 8) + pseudoh[i+1];
243 sum += w;
244 while (sum > 65535) {
245 int to_add = sum >> 16;
246 sum = (sum & 0xffff) + to_add;
247 }
248 }
249
250 if (tcp_len & 1) {
251 tcp_len ++;
252 pad = 1;
253 }
254
255 for (i=0; i<tcp_len; i+=2)
256 if (i != chksumoffset) {
257 uint16_t w;
258 if (!pad || i < tcp_len-2)
259 w = (tcp_header[i] << 8) + tcp_header[i+1];
260 else
261 w = (tcp_header[i] << 8) + 0x00;
262 sum += w;
263 while (sum > 65535) {
264 int to_add = sum >> 16;
265 sum = (sum & 0xffff) + to_add;
266 }
267 }
268
269 sum ^= 0xffff;
270 tcp_header[chksumoffset + 0] = sum >> 8;
271 tcp_header[chksumoffset + 1] = sum & 0xff;
272 }
273
274
275 /*
276 * net_allocate_packet_link():
277 *
278 * This routine allocates an ethernet_packet_link struct, and adds it at
279 * the end of the packet chain. A data buffer is allocated (and zeroed),
280 * and the data, extra, and len fields of the link are set.
281 *
282 * Return value is a pointer to the link on success. It doesn't return on
283 * failure.
284 */
285 static struct ethernet_packet_link *net_allocate_packet_link(
286 struct net *net, void *extra, int len)
287 {
288 struct ethernet_packet_link *lp;
289
290 lp = malloc(sizeof(struct ethernet_packet_link));
291 if (lp == NULL) {
292 fprintf(stderr, "net_allocate_packet_link(): out of memory\n");
293 exit(1);
294 }
295
296 /* memset(lp, 0, sizeof(struct ethernet_packet_link)); */
297
298 lp->len = len;
299 lp->extra = extra;
300 lp->data = malloc(len);
301 if (lp->data == NULL) {
302 fprintf(stderr, "net_allocate_packet_link(): out of memory\n");
303 exit(1);
304 }
305 lp->next = NULL;
306
307 /* TODO: maybe this is not necessary: */
308 memset(lp->data, 0, len);
309
310 /* Add last in the link chain: */
311 lp->prev = net->last_ethernet_packet;
312 if (lp->prev != NULL)
313 lp->prev->next = lp;
314 else
315 net->first_ethernet_packet = lp;
316 net->last_ethernet_packet = lp;
317
318 return lp;
319 }
320
321
322 /*
323 * net_ip_icmp():
324 *
325 * Handle an ICMP packet.
326 *
327 * The IP header (at offset 14) could look something like
328 *
329 * ver=45 tos=00 len=0054 id=001a ofs=0000 ttl=ff p=01 sum=a87e
330 * src=0a000005 dst=03050607
331 *
332 * and the ICMP specific data (beginning at offset 34):
333 *
334 * type=08 code=00 chksum=b8bf
335 * 000c0008d5cee94089190c0008090a0b
336 * 0c0d0e0f101112131415161718191a1b
337 * 1c1d1e1f202122232425262728292a2b
338 * 2c2d2e2f3031323334353637
339 */
340 static void net_ip_icmp(struct net *net, void *extra,
341 unsigned char *packet, int len)
342 {
343 int type;
344 struct ethernet_packet_link *lp;
345
346 type = packet[34];
347
348 switch (type) {
349 case 8: /* ECHO request */
350 debug("[ ICMP echo ]\n");
351 lp = net_allocate_packet_link(net, extra, len);
352
353 /* Copy the old packet first: */
354 memcpy(lp->data, packet, len);
355
356 /* Switch to and from ethernet addresses: */
357 memcpy(lp->data + 0, packet + 6, 6);
358 memcpy(lp->data + 6, packet + 0, 6);
359
360 /* Switch to and from IP addresses: */
361 memcpy(lp->data + 26, packet + 30, 4);
362 memcpy(lp->data + 30, packet + 26, 4);
363
364 /* Change from echo REQUEST to echo REPLY: */
365 lp->data[34] = 0x00;
366
367 /* Decrease the TTL to a low value: */
368 lp->data[22] = 2;
369
370 /* Recalculate ICMP checksum: */
371 net_ip_checksum(lp->data + 34, 2, len - 34);
372
373 /* Recalculate IP header checksum: */
374 net_ip_checksum(lp->data + 14, 10, 20);
375
376 break;
377 default:
378 fatal("[ net: ICMP type %i not yet implemented ]\n", type);
379 }
380 }
381
382
383 /*
384 * tcp_closeconnection():
385 *
386 * Helper function which closes down a TCP connection completely.
387 */
388 static void tcp_closeconnection(struct net *net, int con_id)
389 {
390 close(net->tcp_connections[con_id].socket);
391 net->tcp_connections[con_id].state = TCP_OUTSIDE_DISCONNECTED;
392 net->tcp_connections[con_id].in_use = 0;
393 net->tcp_connections[con_id].incoming_buf_len = 0;
394 }
395
396
397 /*
398 * net_ip_tcp_connectionreply():
399 *
400 * When changing from state _TRYINGTOCONNECT to _CONNECTED, then this
401 * function should be called with connecting set to 1.
402 *
403 * To send a generic ack reply, set connecting to 0.
404 *
405 * To send data (PSH), set data to non-NULL and datalen to the length.
406 *
407 * This creates an ethernet packet for the guest OS with an ACK to the
408 * initial SYN packet.
409 */
410 static void net_ip_tcp_connectionreply(struct net *net, void *extra,
411 int con_id, int connecting, unsigned char *data, int datalen, int rst)
412 {
413 struct ethernet_packet_link *lp;
414 int tcp_length, ip_len, option_len = 20;
415
416 if (connecting)
417 net->tcp_connections[con_id].outside_acknr =
418 net->tcp_connections[con_id].inside_seqnr + 1;
419
420 net->tcp_connections[con_id].tcp_id ++;
421 tcp_length = 20 + option_len + datalen;
422 ip_len = 20 + tcp_length;
423 lp = net_allocate_packet_link(net, extra, 14 + ip_len);
424
425 /* Ethernet header: */
426 memcpy(lp->data + 0, net->tcp_connections[con_id].ethernet_address, 6);
427 memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
428 lp->data[12] = 0x08; /* IP = 0x0800 */
429 lp->data[13] = 0x00;
430
431 /* IP header: */
432 lp->data[14] = 0x45; /* ver */
433 lp->data[15] = 0x10; /* tos */
434 lp->data[16] = ip_len >> 8;
435 lp->data[17] = ip_len & 0xff;
436 lp->data[18] = net->tcp_connections[con_id].tcp_id >> 8;
437 lp->data[19] = net->tcp_connections[con_id].tcp_id & 0xff;
438 lp->data[20] = 0x40; /* don't fragment */
439 lp->data[21] = 0x00;
440 lp->data[22] = 0x40; /* ttl */
441 lp->data[23] = 6; /* p = TCP */
442 memcpy(lp->data + 26, net->tcp_connections[con_id].
443 outside_ip_address, 4);
444 memcpy(lp->data + 30, net->tcp_connections[con_id].
445 inside_ip_address, 4);
446 net_ip_checksum(lp->data + 14, 10, 20);
447
448 /* TCP header and options at offset 34: */
449 lp->data[34] = net->tcp_connections[con_id].outside_tcp_port >> 8;
450 lp->data[35] = net->tcp_connections[con_id].outside_tcp_port & 0xff;
451 lp->data[36] = net->tcp_connections[con_id].inside_tcp_port >> 8;
452 lp->data[37] = net->tcp_connections[con_id].inside_tcp_port & 0xff;
453 lp->data[38] = (net->tcp_connections[con_id].
454 outside_seqnr >> 24) & 0xff;
455 lp->data[39] = (net->tcp_connections[con_id].
456 outside_seqnr >> 16) & 0xff;
457 lp->data[40] = (net->tcp_connections[con_id].
458 outside_seqnr >> 8) & 0xff;
459 lp->data[41] = net->tcp_connections[con_id].
460 outside_seqnr & 0xff;
461 lp->data[42] = (net->tcp_connections[con_id].
462 outside_acknr >> 24) & 0xff;
463 lp->data[43] = (net->tcp_connections[con_id].
464 outside_acknr >> 16) & 0xff;
465 lp->data[44] = (net->tcp_connections[con_id].
466 outside_acknr >> 8) & 0xff;
467 lp->data[45] = net->tcp_connections[con_id].outside_acknr & 0xff;
468
469 /* Control */
470 lp->data[46] = (option_len + 20) / 4 * 0x10;
471 lp->data[47] = 0x10; /* ACK */
472 if (connecting)
473 lp->data[47] |= 0x02; /* SYN */
474 if (net->tcp_connections[con_id].state == TCP_OUTSIDE_CONNECTED)
475 lp->data[47] |= 0x08; /* PSH */
476 if (rst)
477 lp->data[47] |= 0x04; /* RST */
478 if (net->tcp_connections[con_id].state >= TCP_OUTSIDE_DISCONNECTED)
479 lp->data[47] |= 0x01; /* FIN */
480
481 /* Window */
482 lp->data[48] = 0x10;
483 lp->data[49] = 0x00;
484
485 /* no urgent ptr */
486
487 /* options */
488 /* TODO: HAHA, this is ugly */
489 lp->data[54] = 0x02;
490 lp->data[55] = 0x04;
491 lp->data[56] = 0x05;
492 lp->data[57] = 0xb4;
493 lp->data[58] = 0x01;
494 lp->data[59] = 0x03;
495 lp->data[60] = 0x03;
496 lp->data[61] = 0x00;
497 lp->data[62] = 0x01;
498 lp->data[63] = 0x01;
499 lp->data[64] = 0x08;
500 lp->data[65] = 0x0a;
501 lp->data[66] = (net->timestamp >> 24) & 0xff;
502 lp->data[67] = (net->timestamp >> 16) & 0xff;
503 lp->data[68] = (net->timestamp >> 8) & 0xff;
504 lp->data[69] = net->timestamp & 0xff;
505 lp->data[70] = (net->tcp_connections[con_id].
506 inside_timestamp >> 24) & 0xff;
507 lp->data[71] = (net->tcp_connections[con_id].
508 inside_timestamp >> 16) & 0xff;
509 lp->data[72] = (net->tcp_connections[con_id].
510 inside_timestamp >> 8) & 0xff;
511 lp->data[73] = net->tcp_connections[con_id].
512 inside_timestamp & 0xff;
513
514 /* data: */
515 if (data != NULL) {
516 memcpy(lp->data + 74, data, datalen);
517 net->tcp_connections[con_id].outside_seqnr += datalen;
518 }
519
520 /* Checksum: */
521 net_ip_tcp_checksum(lp->data + 34, 16, tcp_length,
522 lp->data + 26, lp->data + 30, 0);
523
524 #if 0
525 {
526 int i;
527 fatal("[ net_ip_tcp_connectionreply(%i): ", connecting);
528 for (i=0; i<ip_len+14; i++)
529 fatal("%02x", lp->data[i]);
530 fatal(" ]\n");
531 }
532 #endif
533
534 if (connecting)
535 net->tcp_connections[con_id].outside_seqnr ++;
536 }
537
538
539 /*
540 * net_ip_tcp():
541 *
542 * Handle a TCP packet comming from the emulated OS.
543 *
544 * The IP header (at offset 14) could look something like
545 *
546 * ver=45 tos=00 len=003c id=0006 ofs=0000 ttl=40 p=11 sum=b798
547 * src=0a000001 dst=c1abcdef
548 *
549 * TCP header, at offset 34:
550 *
551 * srcport=fffe dstport=0015 seqnr=af419a1d acknr=00000000
552 * control=a002 window=4000 checksum=fe58 urgent=0000
553 * and then "options and padding" and then data.
554 * (020405b4010303000101080a0000000000000000)
555 *
556 * See the following URLs for good descriptions of TCP:
557 *
558 * http://www.networksorcery.com/enp/protocol/tcp.htm
559 * http://www.tcpipguide.com/free/t_TCPIPTransmissionControlProtocolTCP.htm
560 */
561 static void net_ip_tcp(struct net *net, void *extra,
562 unsigned char *packet, int len)
563 {
564 int con_id, free_con_id, i, res;
565 int srcport, dstport, data_offset, window, checksum, urgptr;
566 int syn, ack, psh, rst, urg, fin;
567 uint32_t seqnr, acknr;
568 struct sockaddr_in remote_ip;
569 fd_set rfds;
570 struct timeval tv;
571 int send_ofs;
572
573 #if 0
574 fatal("[ net: TCP: ");
575 for (i=0; i<26; i++)
576 fatal("%02x", packet[i]);
577 fatal(" ");
578 #endif
579
580 srcport = (packet[34] << 8) + packet[35];
581 dstport = (packet[36] << 8) + packet[37];
582
583 seqnr = (packet[38] << 24) + (packet[39] << 16)
584 + (packet[40] << 8) + packet[41];
585 acknr = (packet[42] << 24) + (packet[43] << 16)
586 + (packet[44] << 8) + packet[45];
587
588 #if 0
589 fatal("%i.%i.%i.%i:%i -> %i.%i.%i.%i:%i, seqnr=%lli acknr=%lli ",
590 packet[26], packet[27], packet[28], packet[29], srcport,
591 packet[30], packet[31], packet[32], packet[33], dstport,
592 (long long)seqnr, (long long)acknr);
593 #endif
594
595 data_offset = (packet[46] >> 4) * 4 + 34;
596 /* data_offset is now data offset within packet :-) */
597
598 urg = packet[47] & 32;
599 ack = packet[47] & 16;
600 psh = packet[47] & 8;
601 rst = packet[47] & 4;
602 syn = packet[47] & 2;
603 fin = packet[47] & 1;
604 window = (packet[48] << 8) + packet[49];
605 checksum = (packet[50] << 8) + packet[51];
606 urgptr = (packet[52] << 8) + packet[53];
607
608 #if 0
609 fatal(urg? "URG " : "");
610 fatal(ack? "ACK " : "");
611 fatal(psh? "PSH " : "");
612 fatal(rst? "RST " : "");
613 fatal(syn? "SYN " : "");
614 fatal(fin? "FIN " : "");
615
616 fatal("window=0x%04x checksum=0x%04x urgptr=0x%04x ",
617 window, checksum, urgptr);
618
619 fatal("options=");
620 for (i=34+20; i<data_offset; i++)
621 fatal("%02x", packet[i]);
622
623 fatal(" data=");
624 for (i=data_offset; i<len; i++)
625 fatal("%02x", packet[i]);
626
627 fatal(" ]\n");
628 #endif
629
630 net_ip_tcp_checksum(packet + 34, 16, len - 34,
631 packet + 26, packet + 30, 0);
632 if (packet[50] * 256 + packet[51] != checksum) {
633 debug("TCP: dropping packet because of checksum mismatch "
634 "(0x%04x != 0x%04x)\n", packet[50] * 256 + packet[51],
635 checksum);
636
637 return;
638 }
639
640 /* Does this packet belong to a current connection? */
641 con_id = free_con_id = -1;
642 for (i=0; i<MAX_TCP_CONNECTIONS; i++) {
643 if (!net->tcp_connections[i].in_use)
644 free_con_id = i;
645 if (net->tcp_connections[i].in_use &&
646 net->tcp_connections[i].inside_tcp_port == srcport &&
647 net->tcp_connections[i].outside_tcp_port == dstport &&
648 memcmp(net->tcp_connections[i].inside_ip_address,
649 packet + 26, 4) == 0 &&
650 memcmp(net->tcp_connections[i].outside_ip_address,
651 packet + 30, 4) == 0) {
652 con_id = i;
653 break;
654 }
655 }
656
657 /*
658 * Unknown connection, and not SYN? Then drop the packet.
659 * TODO: Send back RST?
660 */
661 if (con_id < 0 && !syn) {
662 debug("[ net: TCP: dropping packet from unknown connection,"
663 " %i.%i.%i.%i:%i -> %i.%i.%i.%i:%i %s%s%s%s%s]\n",
664 packet[26], packet[27], packet[28], packet[29], srcport,
665 packet[30], packet[31], packet[32], packet[33], dstport,
666 fin? "FIN ": "", syn? "SYN ": "", ack? "ACK ": "",
667 psh? "PSH ": "", rst? "RST ": "");
668 return;
669 }
670
671 /* Known connection, and SYN? Then ignore the packet. */
672 if (con_id >= 0 && syn) {
673 debug("[ net: TCP: ignoring redundant SYN packet from known"
674 " connection, %i.%i.%i.%i:%i -> %i.%i.%i.%i:%i ]\n",
675 packet[26], packet[27], packet[28], packet[29], srcport,
676 packet[30], packet[31], packet[32], packet[33], dstport);
677 return;
678 }
679
680 /*
681 * A new outgoing connection?
682 */
683 if (con_id < 0 && syn) {
684 debug("[ net: TCP: new outgoing connection, %i.%i.%i.%i:%i"
685 " -> %i.%i.%i.%i:%i ]\n",
686 packet[26], packet[27], packet[28], packet[29], srcport,
687 packet[30], packet[31], packet[32], packet[33], dstport);
688
689 /* Find a free connection id to use: */
690 if (free_con_id < 0) {
691 #if 1
692 /*
693 * TODO: Reuse the oldest one currently in use, or
694 * just drop the new connection attempt? Drop for now.
695 */
696 fatal("[ TOO MANY TCP CONNECTIONS IN USE! "
697 "Increase MAX_TCP_CONNECTIONS! ]\n");
698 return;
699 #else
700 int i;
701 int64_t oldest = net->
702 tcp_connections[0].last_used_timestamp;
703 free_con_id = 0;
704
705 fatal("[ NO FREE TCP SLOTS, REUSING OLDEST ONE ]\n");
706 for (i=0; i<MAX_TCP_CONNECTIONS; i++)
707 if (net->tcp_connections[i].
708 last_used_timestamp < oldest) {
709 oldest = net->tcp_connections[i].
710 last_used_timestamp;
711 free_con_id = i;
712 }
713 tcp_closeconnection(net, free_con_id);
714 #endif
715 }
716
717 con_id = free_con_id;
718 memset(&net->tcp_connections[con_id], 0,
719 sizeof(struct tcp_connection));
720
721 memcpy(net->tcp_connections[con_id].ethernet_address,
722 packet + 6, 6);
723 memcpy(net->tcp_connections[con_id].inside_ip_address,
724 packet + 26, 4);
725 net->tcp_connections[con_id].inside_tcp_port = srcport;
726 memcpy(net->tcp_connections[con_id].outside_ip_address,
727 packet + 30, 4);
728 net->tcp_connections[con_id].outside_tcp_port = dstport;
729
730 net->tcp_connections[con_id].socket =
731 socket(AF_INET, SOCK_STREAM, 0);
732 if (net->tcp_connections[con_id].socket < 0) {
733 fatal("[ net: TCP: socket() returned %i ]\n",
734 net->tcp_connections[con_id].socket);
735 return;
736 }
737
738 debug("[ new tcp outgoing socket=%i ]\n",
739 net->tcp_connections[con_id].socket);
740
741 net->tcp_connections[con_id].in_use = 1;
742
743 /* Set the socket to non-blocking: */
744 res = fcntl(net->tcp_connections[con_id].socket, F_GETFL);
745 fcntl(net->tcp_connections[con_id].socket, F_SETFL,
746 res | O_NONBLOCK);
747
748 remote_ip.sin_family = AF_INET;
749 memcpy((unsigned char *)&remote_ip.sin_addr,
750 net->tcp_connections[con_id].outside_ip_address, 4);
751 remote_ip.sin_port = htons(
752 net->tcp_connections[con_id].outside_tcp_port);
753
754 res = connect(net->tcp_connections[con_id].socket,
755 (struct sockaddr *)&remote_ip, sizeof(remote_ip));
756
757 /* connect can return -1, and errno = EINPROGRESS
758 as we might not have connected right away. */
759
760 net->tcp_connections[con_id].state =
761 TCP_OUTSIDE_TRYINGTOCONNECT;
762
763 net->tcp_connections[con_id].outside_acknr = 0;
764 net->tcp_connections[con_id].outside_seqnr =
765 ((random() & 0xffff) << 16) + (random() & 0xffff);
766 }
767
768 if (rst) {
769 debug("[ 'rst': disconnecting TCP connection %i ]\n", con_id);
770 net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 1);
771 tcp_closeconnection(net, con_id);
772 return;
773 }
774
775 if (ack && net->tcp_connections[con_id].state
776 == TCP_OUTSIDE_DISCONNECTED2) {
777 debug("[ 'ack': guestOS's final termination of TCP "
778 "connection %i ]\n", con_id);
779
780 /* Send an RST? (TODO, this is wrong...) */
781 net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 1);
782
783 /* ... and forget about this connection: */
784 tcp_closeconnection(net, con_id);
785 return;
786 }
787
788 if (fin && net->tcp_connections[con_id].state
789 == TCP_OUTSIDE_DISCONNECTED) {
790 debug("[ 'fin': response to outside's disconnection of "
791 "TCP connection %i ]\n", con_id);
792
793 /* Send an ACK: */
794 net->tcp_connections[con_id].state = TCP_OUTSIDE_CONNECTED;
795 net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
796 net->tcp_connections[con_id].state = TCP_OUTSIDE_DISCONNECTED2;
797 return;
798 }
799
800 if (fin) {
801 debug("[ 'fin': guestOS disconnecting TCP connection %i ]\n",
802 con_id);
803
804 /* Send ACK: */
805 net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
806 net->tcp_connections[con_id].state = TCP_OUTSIDE_DISCONNECTED2;
807
808 /* Return and send FIN: */
809 goto ret;
810 }
811
812 if (ack) {
813 debug("ACK %i bytes, inside_acknr=%u outside_seqnr=%u\n",
814 net->tcp_connections[con_id].incoming_buf_len,
815 net->tcp_connections[con_id].inside_acknr,
816 net->tcp_connections[con_id].outside_seqnr);
817 net->tcp_connections[con_id].inside_acknr = acknr;
818 if (net->tcp_connections[con_id].inside_acknr ==
819 net->tcp_connections[con_id].outside_seqnr &&
820 net->tcp_connections[con_id].incoming_buf_len != 0) {
821 debug(" all acked\n");
822 net->tcp_connections[con_id].incoming_buf_len = 0;
823 }
824 }
825
826 net->tcp_connections[con_id].inside_seqnr = seqnr;
827
828 /* TODO: This is hardcoded for a specific NetBSD packet: */
829 if (packet[34 + 30] == 0x08 && packet[34 + 31] == 0x0a)
830 net->tcp_connections[con_id].inside_timestamp =
831 (packet[34 + 32 + 0] << 24) +
832 (packet[34 + 32 + 1] << 16) +
833 (packet[34 + 32 + 2] << 8) +
834 (packet[34 + 32 + 3] << 0);
835
836
837 net->timestamp ++;
838 net->tcp_connections[con_id].last_used_timestamp = net->timestamp;
839
840
841 if (net->tcp_connections[con_id].state != TCP_OUTSIDE_CONNECTED) {
842 debug("[ not connected to outside ]\n");
843 return;
844 }
845
846
847 if (data_offset >= len)
848 return;
849
850
851 /*
852 * We are here if this is a known connection, and data is to be
853 * transmitted to the outside world.
854 */
855
856 send_ofs = data_offset;
857 send_ofs += ((int32_t)net->tcp_connections[con_id].outside_acknr
858 - (int32_t)seqnr);
859 #if 1
860 debug("[ %i bytes of tcp data to be sent, beginning at seqnr %u, ",
861 len - data_offset, seqnr);
862 debug("outside is at acknr %u ==> %i actual bytes to be sent ]\n",
863 net->tcp_connections[con_id].outside_acknr, len - send_ofs);
864 #endif
865
866 /* Drop outgoing packet if the guest OS' seqnr is not
867 the same as we have acked. (We have missed something, perhaps.) */
868 if (seqnr != net->tcp_connections[con_id].outside_acknr) {
869 debug("!! outgoing TCP packet dropped (seqnr = %u, "
870 "outside_acknr = %u)\n", seqnr,
871 net->tcp_connections[con_id].outside_acknr);
872 goto ret;
873 }
874
875 if (len - send_ofs > 0) {
876 /* Is the socket available for output? */
877 FD_ZERO(&rfds); /* write */
878 FD_SET(net->tcp_connections[con_id].socket, &rfds);
879 tv.tv_sec = tv.tv_usec = 0;
880 errno = 0;
881 res = select(net->tcp_connections[con_id].socket+1,
882 NULL, &rfds, NULL, &tv);
883 if (res < 1) {
884 net->tcp_connections[con_id].state =
885 TCP_OUTSIDE_DISCONNECTED;
886 debug("[ TCP: disconnect on select for writing ]\n");
887 goto ret;
888 }
889
890 res = write(net->tcp_connections[con_id].socket,
891 packet + send_ofs, len - send_ofs);
892
893 if (res > 0) {
894 net->tcp_connections[con_id].outside_acknr += res;
895 } else if (errno == EAGAIN) {
896 /* Just ignore this attempt. */
897 return;
898 } else {
899 debug("[ error writing %i bytes to TCP connection %i:"
900 " errno = %i ]\n", len - send_ofs, con_id, errno);
901 net->tcp_connections[con_id].state =
902 TCP_OUTSIDE_DISCONNECTED;
903 debug("[ TCP: disconnect on write() ]\n");
904 goto ret;
905 }
906 }
907
908 ret:
909 /* Send an ACK (or FIN) to the guest OS: */
910 net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
911 }
912
913
914 /*
915 * net_ip_udp():
916 *
917 * Handle a UDP packet.
918 *
919 * (See http://www.networksorcery.com/enp/protocol/udp.htm.)
920 *
921 * The IP header (at offset 14) could look something like
922 *
923 * ver=45 tos=00 len=003c id=0006 ofs=0000 ttl=40 p=11 sum=b798
924 * src=0a000001 dst=c1abcdef
925 *
926 * and the UDP data (beginning at offset 34):
927 *
928 * srcport=fffc dstport=0035 length=0028 chksum=76b6
929 * 43e20100000100000000000003667470066e6574627364036f726700001c0001
930 */
931 static void net_ip_udp(struct net *net, void *extra,
932 unsigned char *packet, int len)
933 {
934 int con_id, free_con_id, i, srcport, dstport, udp_len;
935 ssize_t res;
936 struct sockaddr_in remote_ip;
937
938 if ((packet[20] & 0x3f) != 0) {
939 fatal("[ net_ip_udp(): WARNING! fragmented UDP "
940 "packet, TODO ]\n");
941 return;
942 }
943
944 srcport = (packet[34] << 8) + packet[35];
945 dstport = (packet[36] << 8) + packet[37];
946 udp_len = (packet[38] << 8) + packet[39];
947 /* chksum at offset 40 and 41 */
948
949 debug("[ net: UDP: ");
950 debug("srcport=%i dstport=%i len=%i ", srcport, dstport, udp_len);
951 for (i=42; i<len; i++) {
952 if (packet[i] >= ' ' && packet[i] < 127)
953 debug("%c", packet[i]);
954 else
955 debug("[%02x]", packet[i]);
956 }
957 debug(" ]\n");
958
959 /* Is this "connection" new, or a currently ongoing one? */
960 con_id = free_con_id = -1;
961 for (i=0; i<MAX_UDP_CONNECTIONS; i++) {
962 if (!net->udp_connections[i].in_use)
963 free_con_id = i;
964 if (net->udp_connections[i].in_use &&
965 net->udp_connections[i].inside_udp_port == srcport &&
966 net->udp_connections[i].outside_udp_port == dstport &&
967 memcmp(net->udp_connections[i].inside_ip_address,
968 packet + 26, 4) == 0 &&
969 memcmp(net->udp_connections[i].outside_ip_address,
970 packet + 30, 4) == 0) {
971 con_id = i;
972 break;
973 }
974 }
975
976 debug("&& UDP connection is ");
977 if (con_id >= 0)
978 debug("ONGOING");
979 else {
980 debug("NEW");
981 if (free_con_id < 0) {
982 int i;
983 int64_t oldest = net->
984 udp_connections[0].last_used_timestamp;
985 free_con_id = 0;
986
987 debug(", NO FREE SLOTS, REUSING OLDEST ONE");
988 for (i=0; i<MAX_UDP_CONNECTIONS; i++)
989 if (net->udp_connections[i].
990 last_used_timestamp < oldest) {
991 oldest = net->udp_connections[i].
992 last_used_timestamp;
993 free_con_id = i;
994 }
995 close(net->udp_connections[free_con_id].socket);
996 }
997 con_id = free_con_id;
998 memset(&net->udp_connections[con_id], 0,
999 sizeof(struct udp_connection));
1000
1001 memcpy(net->udp_connections[con_id].ethernet_address,
1002 packet + 6, 6);
1003 memcpy(net->udp_connections[con_id].inside_ip_address,
1004 packet + 26, 4);
1005 net->udp_connections[con_id].inside_udp_port = srcport;
1006 memcpy(net->udp_connections[con_id].outside_ip_address,
1007 packet + 30, 4);
1008 net->udp_connections[con_id].outside_udp_port = dstport;
1009
1010 net->udp_connections[con_id].socket = socket(AF_INET,
1011 SOCK_DGRAM, 0);
1012 if (net->udp_connections[con_id].socket < 0) {
1013 fatal("[ net: UDP: socket() returned %i ]\n",
1014 net->udp_connections[con_id].socket);
1015 return;
1016 }
1017
1018 debug(" {socket=%i}", net->udp_connections[con_id].socket);
1019
1020 net->udp_connections[con_id].in_use = 1;
1021
1022 /* Set the socket to non-blocking: */
1023 res = fcntl(net->udp_connections[con_id].socket, F_GETFL);
1024 fcntl(net->udp_connections[con_id].socket, F_SETFL,
1025 res | O_NONBLOCK);
1026 }
1027
1028 debug(", connection id %i\n", con_id);
1029
1030 net->timestamp ++;
1031 net->udp_connections[con_id].last_used_timestamp = net->timestamp;
1032
1033 remote_ip.sin_family = AF_INET;
1034 memcpy((unsigned char *)&remote_ip.sin_addr,
1035 net->udp_connections[con_id].outside_ip_address, 4);
1036
1037 /*
1038 * Special case for the nameserver: If a UDP packet is sent to
1039 * the gateway, it will be forwarded to the nameserver, if it is
1040 * known.
1041 */
1042 if (net->nameserver_known &&
1043 memcmp(net->udp_connections[con_id].outside_ip_address,
1044 &net->gateway_ipv4_addr[0], 4) == 0) {
1045 memcpy((unsigned char *)&remote_ip.sin_addr,
1046 &net->nameserver_ipv4, 4);
1047 net->udp_connections[con_id].fake_ns = 1;
1048 }
1049
1050 remote_ip.sin_port = htons(
1051 net->udp_connections[con_id].outside_udp_port);
1052
1053 res = sendto(net->udp_connections[con_id].socket, packet + 42,
1054 len - 42, 0, (const struct sockaddr *)&remote_ip,
1055 sizeof(remote_ip));
1056
1057 if (res != len-42)
1058 debug("[ net: UDP: unable to send %i bytes ]\n", len-42);
1059 else
1060 debug("[ net: UDP: OK!!! ]\n");
1061 }
1062
1063
1064 /*
1065 * net_ip():
1066 *
1067 * Handle an IP packet, coming from the emulated NIC.
1068 */
1069 static void net_ip(struct net *net, void *extra,
1070 unsigned char *packet, int len)
1071 {
1072 #if 1
1073 int i;
1074
1075 debug("[ net: IP: ");
1076 debug("ver=%02x ", packet[14]);
1077 debug("tos=%02x ", packet[15]);
1078 debug("len=%02x%02x ", packet[16], packet[17]);
1079 debug("id=%02x%02x ", packet[18], packet[19]);
1080 debug("ofs=%02x%02x ", packet[20], packet[21]);
1081 debug("ttl=%02x ", packet[22]);
1082 debug("p=%02x ", packet[23]);
1083 debug("sum=%02x%02x ", packet[24], packet[25]);
1084 debug("src=%02x%02x%02x%02x ",
1085 packet[26], packet[27], packet[28], packet[29]);
1086 debug("dst=%02x%02x%02x%02x ",
1087 packet[30], packet[31], packet[32], packet[33]);
1088 for (i=34; i<len; i++)
1089 debug("%02x", packet[i]);
1090 debug(" ]\n");
1091 #endif
1092
1093 /* Cut off overflowing tail data: */
1094 if (len > 14 + packet[16]*256 + packet[17])
1095 len = 14 + packet[16]*256 + packet[17];
1096
1097 if (packet[14] == 0x45) {
1098 /* IPv4: */
1099 switch (packet[23]) {
1100 case 1: /* ICMP */
1101 net_ip_icmp(net, extra, packet, len);
1102 break;
1103 case 6: /* TCP */
1104 net_ip_tcp(net, extra, packet, len);
1105 break;
1106 case 17:/* UDP */
1107 net_ip_udp(net, extra, packet, len);
1108 break;
1109 default:
1110 fatal("[ net: IP: UNIMPLEMENTED protocol %i ]\n",
1111 packet[23]);
1112 }
1113 } else
1114 fatal("[ net: IP: UNIMPLEMENTED ip, first byte = 0x%02x ]\n",
1115 packet[14]);
1116 }
1117
1118
1119 /*
1120 * net_ip_broadcast_dhcp():
1121 *
1122 * Handle an IPv4 DHCP broadcast packet, coming from the emulated NIC.
1123 *
1124 * Read http://www.ietf.org/rfc/rfc2131.txt for details on DHCP.
1125 * (And http://users.telenet.be/mydotcom/library/network/dhcp.htm.)
1126 */
1127 static void net_ip_broadcast_dhcp(struct net *net, void *extra,
1128 unsigned char *packet, int len)
1129 {
1130 /*
1131 * TODO
1132 */
1133 #if 0
1134 struct ethernet_packet_link *lp;
1135 int i;
1136
1137 fatal("[ net: IPv4 DHCP: ");
1138 #if 0
1139 fatal("ver=%02x ", packet[14]);
1140 fatal("tos=%02x ", packet[15]);
1141 fatal("len=%02x%02x ", packet[16], packet[17]);
1142 fatal("id=%02x%02x ", packet[18], packet[19]);
1143 fatal("ofs=%02x%02x ", packet[20], packet[21]);
1144 fatal("ttl=%02x ", packet[22]);
1145 fatal("p=%02x ", packet[23]);
1146 fatal("sum=%02x%02x ", packet[24], packet[25]);
1147 #endif
1148 fatal("src=%02x%02x%02x%02x ",
1149 packet[26], packet[27], packet[28], packet[29]);
1150 fatal("dst=%02x%02x%02x%02x ",
1151 packet[30], packet[31], packet[32], packet[33]);
1152 #if 0
1153 for (i=34; i<len; i++)
1154 fatal("%02x", packet[i]);
1155 #endif
1156
1157 if (len < 34 + 8 + 236) {
1158 fatal("[ DHCP packet too short? Len=%i ]\n", len);
1159 return;
1160 }
1161
1162 /*
1163 * UDP data (at offset 34):
1164 *
1165 * srcport=0044 dstport=0043 length=0134 chksum=a973
1166 * data = 01010600d116d276000000000000000000000000000000
1167 * 0000000000102030405060...0000...638253633501...000
1168 */
1169
1170 fatal("op=%02x ", packet[42]);
1171 fatal("htype=%02x ", packet[43]);
1172 fatal("hlen=%02x ", packet[44]);
1173 fatal("hops=%02x ", packet[45]);
1174 fatal("xid=%02x%02x%02x%02x ", packet[46], packet[47],
1175 packet[48], packet[49]);
1176 fatal("secs=%02x%02x ", packet[50], packet[51]);
1177 fatal("flags=%02x%02x ", packet[52], packet[53]);
1178 fatal("ciaddr=%02x%02x%02x%02x ", packet[54], packet[55],
1179 packet[56], packet[57]);
1180 fatal("yiaddr=%02x%02x%02x%02x ", packet[58], packet[59],
1181 packet[60], packet[61]);
1182 fatal("siaddr=%02x%02x%02x%02x ", packet[62], packet[63],
1183 packet[64], packet[65]);
1184 fatal("giaddr=%02x%02x%02x%02x ", packet[66], packet[67],
1185 packet[68], packet[69]);
1186 fatal("chaddr=");
1187 for (i=70; i<70+16; i++)
1188 fatal("%02x", packet[i]);
1189 /*
1190 | sname (64) |
1191 | file (128) |
1192 */
1193 fatal(" ]\n");
1194
1195 lp = net_allocate_packet_link(net, extra, len);
1196
1197 /* Copy the old packet first: */
1198 memcpy(lp->data, packet, len);
1199
1200 /* We are sending to the client, from the gateway: */
1201 memcpy(lp->data + 0, packet + 6, 6);
1202 memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
1203
1204 memcpy(lp->data + 26, &net->gateway_ipv4_addr[0], 4);
1205 lp->data[30] = 0xff;
1206 lp->data[31] = 0xff;
1207 lp->data[32] = 0xff;
1208 lp->data[33] = 0xff;
1209
1210 /* Switch src and dst ports: */
1211 memcpy(lp->data + 34, packet + 36, 2);
1212 memcpy(lp->data + 36, packet + 34, 2);
1213
1214 /* Client's (yiaddr) IPv4 address: */
1215 lp->data[58] = 10;
1216 lp->data[59] = 0;
1217 lp->data[60] = 0;
1218 lp->data[61] = 1;
1219
1220 /* Server's IPv4 address: (giaddr) */
1221 memcpy(lp->data + 66, &net->gateway_ipv4_addr[0], 4);
1222
1223 /* This is a Reply: */
1224 lp->data[42] = 0x02;
1225
1226 sprintf(lp->data + 70+16+64, "gxemul");
1227
1228 /* Recalculate IP header checksum: */
1229 net_ip_checksum(lp->data + 14, 10, 20);
1230
1231 /* ... and the UDP checksum: */
1232 net_ip_tcp_checksum(lp->data + 34, 6, len - 34 - 8,
1233 lp->data + 26, lp->data + 30, 1);
1234
1235
1236 /* Debug dump: */
1237 packet = lp->data;
1238 fatal("[ net: IPv4 DHCP REPLY: ");
1239 for (i=0; i<14; i++)
1240 fatal("%02x", packet[i]);
1241 fatal("ver=%02x ", packet[14]);
1242 fatal("tos=%02x ", packet[15]);
1243 fatal("len=%02x%02x ", packet[16], packet[17]);
1244 fatal("id=%02x%02x ", packet[18], packet[19]);
1245 fatal("ofs=%02x%02x ", packet[20], packet[21]);
1246 fatal("ttl=%02x ", packet[22]);
1247 fatal("p=%02x ", packet[23]);
1248 fatal("sum=%02x%02x ", packet[24], packet[25]);
1249 fatal("src=%02x%02x%02x%02x ",
1250 packet[26], packet[27], packet[28], packet[29]);
1251 fatal("dst=%02x%02x%02x%02x ",
1252 packet[30], packet[31], packet[32], packet[33]);
1253 fatal("op=%02x ", packet[42]);
1254 fatal("htype=%02x ", packet[43]);
1255 fatal("hlen=%02x ", packet[44]);
1256 fatal("hops=%02x ", packet[45]);
1257 fatal("xid=%02x%02x%02x%02x ", packet[46], packet[47],
1258 packet[48], packet[49]);
1259 fatal("secs=%02x%02x ", packet[50], packet[51]);
1260 fatal("flags=%02x%02x ", packet[52], packet[53]);
1261 fatal("ciaddr=%02x%02x%02x%02x ", packet[54], packet[55],
1262 packet[56], packet[57]);
1263 fatal("yiaddr=%02x%02x%02x%02x ", packet[58], packet[59],
1264 packet[60], packet[61]);
1265 fatal("siaddr=%02x%02x%02x%02x ", packet[62], packet[63],
1266 packet[64], packet[65]);
1267 fatal("giaddr=%02x%02x%02x%02x ", packet[66], packet[67],
1268 packet[68], packet[69]);
1269 fatal("chaddr=");
1270 for (i=70; i<70+16; i++)
1271 fatal("%02x", packet[i]);
1272 fatal(" ]\n");
1273
1274 #endif
1275 }
1276
1277
1278 /*
1279 * net_ip_broadcast():
1280 *
1281 * Handle an IP broadcast packet, coming from the emulated NIC.
1282 * (This is usually a DHCP request, or similar.)
1283 */
1284 static void net_ip_broadcast(struct net *net, void *extra,
1285 unsigned char *packet, int len)
1286 {
1287 unsigned char *p = (void *) &net->netmask_ipv4;
1288 uint32_t x, y;
1289 int i, xl, warning = 0, match = 0;
1290
1291 #if 0
1292 fatal("[ net: IP BROADCAST: ");
1293 fatal("ver=%02x ", packet[14]);
1294 fatal("tos=%02x ", packet[15]);
1295 fatal("len=%02x%02x ", packet[16], packet[17]);
1296 fatal("id=%02x%02x ", packet[18], packet[19]);
1297 fatal("ofs=%02x%02x ", packet[20], packet[21]);
1298 fatal("ttl=%02x ", packet[22]);
1299 fatal("p=%02x ", packet[23]);
1300 fatal("sum=%02x%02x ", packet[24], packet[25]);
1301 fatal("src=%02x%02x%02x%02x ",
1302 packet[26], packet[27], packet[28], packet[29]);
1303 fatal("dst=%02x%02x%02x%02x ",
1304 packet[30], packet[31], packet[32], packet[33]);
1305 for (i=34; i<len; i++)
1306 fatal("%02x", packet[i]);
1307 fatal(" ]\n");
1308 #endif
1309
1310 /* Check for 10.0.0.255 first, maybe some guest OSes think that
1311 it's a /24 network, regardless of what it actually is. */
1312 y = (packet[30] << 24) + (packet[31] << 16) +
1313 (packet[32] << 8) + packet[33];
1314
1315 x = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
1316 /* Example: x = 10.0.0.0 */
1317 x |= 255;
1318
1319 if (x == y) {
1320 warning = 1;
1321 match = 1;
1322 }
1323
1324 xl = 32 - net->netmask_ipv4_len;
1325 x |= (1 << xl) - 1;
1326 /* x = 10.255.255.255 */
1327
1328 if (x == y)
1329 match = 1;
1330 if (y == 0xffffffff)
1331 match = 1;
1332
1333 if (warning)
1334 fatal("[ net_ip_broadcast(): warning: broadcast to "
1335 "0x%08x, expecting broadcast to 0x%08x or "
1336 "0xffffffff ]\n", y, x);
1337
1338 /* Cut off overflowing tail data: */
1339 if (len > 14 + packet[16]*256 + packet[17])
1340 len = 14 + packet[16]*256 + packet[17];
1341
1342 /* Check for known packets: */
1343 if (packet[14] == 0x45 && /* IPv4 */
1344 packet[23] == 0x11 && /* UDP */
1345 packet[34] == 0 && packet[35] == 68 && /* DHCP client */
1346 packet[36] == 0 && packet[37] == 67) { /* DHCP server */
1347 net_ip_broadcast_dhcp(net, extra, packet, len);
1348 return;
1349 }
1350
1351 /* Unknown packet: */
1352 fatal("[ net: UNIMPLEMENTED IP BROADCAST: ");
1353 fatal("ver=%02x ", packet[14]);
1354 fatal("tos=%02x ", packet[15]);
1355 fatal("len=%02x%02x ", packet[16], packet[17]);
1356 fatal("id=%02x%02x ", packet[18], packet[19]);
1357 fatal("ofs=%02x%02x ", packet[20], packet[21]);
1358 fatal("ttl=%02x ", packet[22]);
1359 fatal("p=%02x ", packet[23]);
1360 fatal("sum=%02x%02x ", packet[24], packet[25]);
1361 fatal("src=%02x%02x%02x%02x ",
1362 packet[26], packet[27], packet[28], packet[29]);
1363 fatal("dst=%02x%02x%02x%02x ",
1364 packet[30], packet[31], packet[32], packet[33]);
1365 for (i=34; i<len; i++)
1366 fatal("%02x", packet[i]);
1367 fatal(" ]\n");
1368 }
1369
1370
1371 /*
1372 * net_arp():
1373 *
1374 * Handle an ARP (or RARP) packet, coming from the emulated NIC.
1375 *
1376 * An ARP packet might look like this:
1377 *
1378 * ARP header:
1379 * ARP hardware addr family: 0001
1380 * ARP protocol addr family: 0800
1381 * ARP addr lengths: 06 04
1382 * ARP request: 0001
1383 * ARP from: 112233445566 01020304
1384 * ARP to: 000000000000 01020301
1385 *
1386 * An ARP request with a 'to' IP value of the gateway should cause an
1387 * ARP response packet to be created.
1388 *
1389 * An ARP request with the same from and to IP addresses should be ignored.
1390 * (This would be a host testing to see if there is an IP collision.)
1391 */
1392 static void net_arp(struct net *net, void *extra,
1393 unsigned char *packet, int len, int reverse)
1394 {
1395 int q;
1396 int i;
1397
1398 /* TODO: This debug dump assumes ethernet->IPv4 translation: */
1399 if (reverse)
1400 debug("[ net: RARP: ");
1401 else
1402 debug("[ net: ARP: ");
1403 for (i=0; i<2; i++)
1404 debug("%02x", packet[i]);
1405 debug(" ");
1406 for (i=2; i<4; i++)
1407 debug("%02x", packet[i]);
1408 debug(" ");
1409 debug("%02x", packet[4]);
1410 debug(" ");
1411 debug("%02x", packet[5]);
1412 debug(" req=");
1413 debug("%02x", packet[6]); /* Request type */
1414 debug("%02x", packet[7]);
1415 debug(" from=");
1416 for (i=8; i<18; i++)
1417 debug("%02x", packet[i]);
1418 debug(" to=");
1419 for (i=18; i<28; i++)
1420 debug("%02x", packet[i]);
1421 debug(" ]\n");
1422
1423 if (packet[0] == 0x00 && packet[1] == 0x01 &&
1424 packet[2] == 0x08 && packet[3] == 0x00 &&
1425 packet[4] == 0x06 && packet[5] == 0x04) {
1426 int r = (packet[6] << 8) + packet[7];
1427 struct ethernet_packet_link *lp;
1428
1429 switch (r) {
1430 case 1: /* Request */
1431 /* Only create a reply if this was meant for the
1432 gateway: */
1433 if (memcmp(packet+24, net->gateway_ipv4_addr, 4) != 0)
1434 break;
1435
1436 lp = net_allocate_packet_link(net, extra, len + 14);
1437
1438 /* Copy the old packet first: */
1439 memcpy(lp->data + 14, packet, len);
1440
1441 /* Add ethernet ARP header: */
1442 memcpy(lp->data + 0, lp->data + 8 + 14, 6);
1443 memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
1444 lp->data[12] = 0x08; lp->data[13] = 0x06;
1445
1446 /* Address of the emulated machine: */
1447 memcpy(lp->data + 18 + 14, lp->data + 8 + 14, 10);
1448
1449 /* Address of the gateway: */
1450 memcpy(lp->data + 8 + 14, net->gateway_ethernet_addr,
1451 6);
1452 memcpy(lp->data + 14 + 14, net->gateway_ipv4_addr, 4);
1453
1454 /* This is a Reply: */
1455 lp->data[6 + 14] = 0x00; lp->data[7 + 14] = 0x02;
1456
1457 break;
1458 case 3: /* Reverse Request */
1459 lp = net_allocate_packet_link(net, extra, len + 14);
1460
1461 /* Copy the old packet first: */
1462 memcpy(lp->data + 14, packet, len);
1463
1464 /* Add ethernet RARP header: */
1465 memcpy(lp->data + 0, packet + 8, 6);
1466 memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
1467 lp->data[12] = 0x80; lp->data[13] = 0x35;
1468
1469 /* This is a RARP reply: */
1470 lp->data[6 + 14] = 0x00; lp->data[7 + 14] = 0x04;
1471
1472 /* Address of the gateway: */
1473 memcpy(lp->data + 8 + 14, net->gateway_ethernet_addr,
1474 6);
1475 memcpy(lp->data + 14 + 14, net->gateway_ipv4_addr, 4);
1476
1477 /* MAC address of emulated machine: */
1478 memcpy(lp->data + 18 + 14, packet + 8, 6);
1479
1480 /*
1481 * IP address of the emulated machine: Automagically
1482 * generated from the MAC address. :-)
1483 *
1484 * packet+8 points to the client's mac address,
1485 * for example 10:20:30:x0:y0:z0, where x,y,z are
1486 * 1..15.
1487 * 10:20:30:10:10:10 results in 10.0.0.1.
1488 */
1489 q = (((packet[8 + 3]) >> 4) - 1);
1490 q = q*15 + (((packet[8 + 4]) >> 4) - 1);
1491 q = q*15 + (((packet[8 + 5]) >> 4) - 1);
1492 lp->data[24 + 14] = 10;
1493 lp->data[25 + 14] = q / 225; q /= 15;
1494 lp->data[26 + 14] = q / 15; q /= 15;
1495 lp->data[27 + 14] = q + 1;
1496
1497 break;
1498 case 2: /* Reply */
1499 case 4: /* Reverse Reply */
1500 default:
1501 fatal("[ net: ARP: UNIMPLEMENTED request type "
1502 "0x%04x ]\n", r);
1503 }
1504 } else {
1505 fatal("[ net: ARP: UNIMPLEMENTED arp packet type: ");
1506 for (i=0; i<len; i++)
1507 fatal("%02x", packet[i]);
1508 fatal(" ]\n");
1509 }
1510 }
1511
1512
1513 /*
1514 * net_ethernet_rx_avail():
1515 *
1516 * Return 1 if there is a packet available for this 'extra' pointer, otherwise
1517 * return 0.
1518 *
1519 * Appart from actually checking for incoming packets from the outside world,
1520 * this function basically works like net_ethernet_rx() but it only receives
1521 * a return value telling us whether there is a packet or not, we don't
1522 * actually get the packet.
1523 */
1524 int net_ethernet_rx_avail(struct net *net, void *extra)
1525 {
1526 int received_packets_this_tick = 0;
1527 int max_packets_this_tick = 200;
1528 int con_id;
1529
1530 if (net == NULL)
1531 return 0;
1532
1533 /*
1534 * UDP:
1535 */
1536 for (con_id=0; con_id<MAX_UDP_CONNECTIONS; con_id++) {
1537 ssize_t res;
1538 unsigned char buf[66000];
1539 unsigned char udp_data[66008];
1540 struct sockaddr_in from;
1541 socklen_t from_len = sizeof(from);
1542 int ip_len, udp_len;
1543 struct ethernet_packet_link *lp;
1544 int max_per_packet;
1545 int bytes_converted = 0;
1546 int this_packets_data_length;
1547 int fragment_ofs = 0;
1548
1549 if (received_packets_this_tick > max_packets_this_tick)
1550 break;
1551
1552 if (!net->udp_connections[con_id].in_use)
1553 continue;
1554
1555 if (net->udp_connections[con_id].socket < 0) {
1556 fatal("INTERNAL ERROR in net.c, udp socket < 0 "
1557 "but in use?\n");
1558 continue;
1559 }
1560
1561 res = recvfrom(net->udp_connections[con_id].socket, buf,
1562 sizeof(buf), 0, (struct sockaddr *)&from, &from_len);
1563
1564 /* No more incoming UDP on this connection? */
1565 if (res < 0)
1566 continue;
1567
1568 net->timestamp ++;
1569 net->udp_connections[con_id].last_used_timestamp =
1570 net->timestamp;
1571
1572 net->udp_connections[con_id].udp_id ++;
1573
1574 /*
1575 * Special case for the nameserver: If a UDP packet is
1576 * received from the nameserver (if the nameserver's IP is
1577 * known), fake it so that it comes from the gateway instead.
1578 */
1579 if (net->udp_connections[con_id].fake_ns)
1580 memcpy(((unsigned char *)(&from))+4,
1581 &net->gateway_ipv4_addr[0], 4);
1582
1583 /*
1584 * We now have a UDP packet of size 'res' which we need
1585 * turn into one or more ethernet packets for the emulated
1586 * operating system. Ethernet packets are at most 1518
1587 * bytes long. With some margin, that means we can have
1588 * about 1500 bytes per packet.
1589 *
1590 * Ethernet = 14 bytes
1591 * IP = 20 bytes
1592 * (UDP = 8 bytes + data)
1593 *
1594 * So data can be at most max_per_packet - 34. For UDP
1595 * fragments, each multiple should (?) be a multiple of
1596 * 8 bytes, except the last which doesn't have any such
1597 * restriction.
1598 */
1599 max_per_packet = 1500;
1600
1601 /* UDP: */
1602 udp_len = res + 8;
1603 /* from[2..3] = outside_udp_port */
1604 udp_data[0] = ((unsigned char *)&from)[2];
1605 udp_data[1] = ((unsigned char *)&from)[3];
1606 udp_data[2] = (net->udp_connections[con_id].
1607 inside_udp_port >> 8) & 0xff;
1608 udp_data[3] = net->udp_connections[con_id].
1609 inside_udp_port & 0xff;
1610 udp_data[4] = udp_len >> 8;
1611 udp_data[5] = udp_len & 0xff;
1612 udp_data[6] = 0;
1613 udp_data[7] = 0;
1614 memcpy(udp_data + 8, buf, res);
1615 /*
1616 * TODO: UDP checksum, if necessary. At least NetBSD
1617 * and OpenBSD accept UDP packets with 0x0000 in the
1618 * checksum field anyway.
1619 */
1620
1621 while (bytes_converted < udp_len) {
1622 this_packets_data_length = udp_len - bytes_converted;
1623
1624 /* Do we need to fragment? */
1625 if (this_packets_data_length > max_per_packet-34) {
1626 this_packets_data_length =
1627 max_per_packet - 34;
1628 while (this_packets_data_length & 7)
1629 this_packets_data_length --;
1630 }
1631
1632 ip_len = 20 + this_packets_data_length;
1633
1634 lp = net_allocate_packet_link(net, extra,
1635 14 + 20 + this_packets_data_length);
1636
1637 /* Ethernet header: */
1638 memcpy(lp->data + 0, net->udp_connections[con_id].
1639 ethernet_address, 6);
1640 memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
1641 lp->data[12] = 0x08; /* IP = 0x0800 */
1642 lp->data[13] = 0x00;
1643
1644 /* IP header: */
1645 lp->data[14] = 0x45; /* ver */
1646 lp->data[15] = 0x00; /* tos */
1647 lp->data[16] = ip_len >> 8;
1648 lp->data[17] = ip_len & 0xff;
1649 lp->data[18] = net->udp_connections[con_id].udp_id >> 8;
1650 lp->data[19] = net->udp_connections[con_id].udp_id
1651 & 0xff;
1652 lp->data[20] = (fragment_ofs >> 8);
1653 if (bytes_converted + this_packets_data_length
1654 < udp_len)
1655 lp->data[20] |= 0x20; /* More fragments */
1656 lp->data[21] = fragment_ofs & 0xff;
1657 lp->data[22] = 0x40; /* ttl */
1658 lp->data[23] = 17; /* p = UDP */
1659 lp->data[26] = ((unsigned char *)&from)[4];
1660 lp->data[27] = ((unsigned char *)&from)[5];
1661 lp->data[28] = ((unsigned char *)&from)[6];
1662 lp->data[29] = ((unsigned char *)&from)[7];
1663 memcpy(lp->data + 30, net->udp_connections[con_id].
1664 inside_ip_address, 4);
1665 net_ip_checksum(lp->data + 14, 10, 20);
1666
1667 memcpy(lp->data+34, udp_data + bytes_converted,
1668 this_packets_data_length);
1669
1670 bytes_converted += this_packets_data_length;
1671 fragment_ofs = bytes_converted / 8;
1672
1673 received_packets_this_tick ++;
1674 }
1675
1676 /* This makes sure we check this connection AGAIN
1677 for more incoming UDP packets, before moving to the
1678 next connection: */
1679 con_id --;
1680 }
1681
1682 /*
1683 * TCP:
1684 */
1685 for (con_id=0; con_id<MAX_TCP_CONNECTIONS; con_id++) {
1686 unsigned char buf[66000];
1687 ssize_t res, res2;
1688 fd_set rfds;
1689 struct timeval tv;
1690
1691 if (received_packets_this_tick > max_packets_this_tick)
1692 break;
1693
1694 if (!net->tcp_connections[con_id].in_use)
1695 continue;
1696
1697 if (net->tcp_connections[con_id].socket < 0) {
1698 fatal("INTERNAL ERROR in net.c, tcp socket < 0"
1699 " but in use?\n");
1700 continue;
1701 }
1702
1703 if (net->tcp_connections[con_id].incoming_buf == NULL) {
1704 net->tcp_connections[con_id].incoming_buf =
1705 malloc(TCP_INCOMING_BUF_LEN);
1706 if (net->tcp_connections[con_id].incoming_buf == NULL) {
1707 printf("out of memory allocating "
1708 "incoming_buf for con_id %i\n", con_id);
1709 exit(1);
1710 }
1711 }
1712
1713 if (net->tcp_connections[con_id].state >=
1714 TCP_OUTSIDE_DISCONNECTED)
1715 continue;
1716
1717 /* Is the socket available for output? */
1718 FD_ZERO(&rfds); /* write */
1719 FD_SET(net->tcp_connections[con_id].socket, &rfds);
1720 tv.tv_sec = tv.tv_usec = 0;
1721 errno = 0;
1722 res = select(net->tcp_connections[con_id].socket+1,
1723 NULL, &rfds, NULL, &tv);
1724
1725 if (errno == ECONNREFUSED) {
1726 fatal("[ ECONNREFUSED: TODO ]\n");
1727 net->tcp_connections[con_id].state =
1728 TCP_OUTSIDE_DISCONNECTED;
1729 fatal("CHANGING TO TCP_OUTSIDE_DISCONNECTED "
1730 "(refused connection)\n");
1731 continue;
1732 }
1733
1734 if (errno == ETIMEDOUT) {
1735 fatal("[ ETIMEDOUT: TODO ]\n");
1736 /* TODO */
1737 net->tcp_connections[con_id].state =
1738 TCP_OUTSIDE_DISCONNECTED;
1739 fatal("CHANGING TO TCP_OUTSIDE_DISCONNECTED "
1740 "(timeout)\n");
1741 continue;
1742 }
1743
1744 if (net->tcp_connections[con_id].state ==
1745 TCP_OUTSIDE_TRYINGTOCONNECT && res > 0) {
1746 net->tcp_connections[con_id].state =
1747 TCP_OUTSIDE_CONNECTED;
1748 debug("CHANGING TO TCP_OUTSIDE_CONNECTED\n");
1749 net_ip_tcp_connectionreply(net, extra, con_id, 1,
1750 NULL, 0, 0);
1751 }
1752
1753 if (net->tcp_connections[con_id].state ==
1754 TCP_OUTSIDE_CONNECTED && res < 1) {
1755 continue;
1756 }
1757
1758 /*
1759 * Does this connection have unacknowledged data? Then, if
1760 * enough number of rounds have passed, try to resend it using
1761 * the old value of seqnr.
1762 */
1763 if (net->tcp_connections[con_id].incoming_buf_len != 0) {
1764 net->tcp_connections[con_id].incoming_buf_rounds ++;
1765 if (net->tcp_connections[con_id].incoming_buf_rounds >
1766 10000) {
1767 debug(" at seqnr %u but backing back to %u,"
1768 " resending %i bytes\n",
1769 net->tcp_connections[con_id].outside_seqnr,
1770 net->tcp_connections[con_id].
1771 incoming_buf_seqnr,
1772 net->tcp_connections[con_id].
1773 incoming_buf_len);
1774
1775 net->tcp_connections[con_id].
1776 incoming_buf_rounds = 0;
1777 net->tcp_connections[con_id].outside_seqnr =
1778 net->tcp_connections[con_id].
1779 incoming_buf_seqnr;
1780
1781 net_ip_tcp_connectionreply(net, extra, con_id,
1782 0, net->tcp_connections[con_id].
1783 incoming_buf,
1784 net->tcp_connections[con_id].
1785 incoming_buf_len, 0);
1786 }
1787 continue;
1788 }
1789
1790 /* Don't receive unless the guest OS is ready! */
1791 if (((int32_t)net->tcp_connections[con_id].outside_seqnr -
1792 (int32_t)net->tcp_connections[con_id].inside_acknr) > 0) {
1793 /* fatal("YOYO 1! outside_seqnr - inside_acknr = %i\n",
1794 net->tcp_connections[con_id].outside_seqnr -
1795 net->tcp_connections[con_id].inside_acknr); */
1796 continue;
1797 }
1798
1799 /* Is there incoming data available on the socket? */
1800 FD_ZERO(&rfds); /* read */
1801 FD_SET(net->tcp_connections[con_id].socket, &rfds);
1802 tv.tv_sec = tv.tv_usec = 0;
1803 res2 = select(net->tcp_connections[con_id].socket+1, &rfds,
1804 NULL, NULL, &tv);
1805
1806 /* No more incoming TCP data on this connection? */
1807 if (res2 < 1)
1808 continue;
1809
1810 res = read(net->tcp_connections[con_id].socket, buf, 1400);
1811 if (res > 0) {
1812 /* debug("\n -{- %lli -}-\n", (long long)res); */
1813 net->tcp_connections[con_id].incoming_buf_len = res;
1814 net->tcp_connections[con_id].incoming_buf_rounds = 0;
1815 net->tcp_connections[con_id].incoming_buf_seqnr =
1816 net->tcp_connections[con_id].outside_seqnr;
1817 debug(" putting %i bytes (seqnr %u) in the incoming "
1818 "buf\n", res, net->tcp_connections[con_id].
1819 incoming_buf_seqnr);
1820 memcpy(net->tcp_connections[con_id].incoming_buf,
1821 buf, res);
1822
1823 net_ip_tcp_connectionreply(net, extra, con_id, 0,
1824 buf, res, 0);
1825 } else if (res == 0) {
1826 net->tcp_connections[con_id].state =
1827 TCP_OUTSIDE_DISCONNECTED;
1828 debug("CHANGING TO TCP_OUTSIDE_DISCONNECTED, read"
1829 " res=0\n");
1830 net_ip_tcp_connectionreply(net, extra, con_id, 0,
1831 NULL, 0, 0);
1832 } else {
1833 net->tcp_connections[con_id].state =
1834 TCP_OUTSIDE_DISCONNECTED;
1835 fatal("CHANGING TO TCP_OUTSIDE_DISCONNECTED, "
1836 "read res<=0, errno = %i\n", errno);
1837 net_ip_tcp_connectionreply(net, extra, con_id, 0,
1838 NULL, 0, 0);
1839 }
1840
1841 net->timestamp ++;
1842 net->tcp_connections[con_id].last_used_timestamp =
1843 net->timestamp;
1844 }
1845
1846 return net_ethernet_rx(net, extra, NULL, NULL);
1847 }
1848
1849
1850 /*
1851 * net_ethernet_rx():
1852 *
1853 * Receive an ethernet packet. (This means handing over an already prepared
1854 * packet from this module (net.c) to a specific ethernet controller device.)
1855 *
1856 * Return value is 1 if there was a packet available. *packetp and *lenp
1857 * will be set to the packet's data pointer and length, respectively, and
1858 * the packet will be removed from the linked list). If there was no packet
1859 * available, 0 is returned.
1860 *
1861 * If packetp is NULL, then the search is aborted as soon as a packet with
1862 * the correct 'extra' field is found, and a 1 is returned, but as packetp
1863 * is NULL we can't return the actual packet. (This is the internal form
1864 * if net_ethernet_rx_avail().)
1865 */
1866 int net_ethernet_rx(struct net *net, void *extra,
1867 unsigned char **packetp, int *lenp)
1868 {
1869 struct ethernet_packet_link *lp, *prev;
1870
1871 if (net == NULL)
1872 return 0;
1873
1874 /* Find the first packet which has the right 'extra' field. */
1875
1876 lp = net->first_ethernet_packet;
1877 prev = NULL;
1878 while (lp != NULL) {
1879 if (lp->extra == extra) {
1880 /* We found a packet for this controller! */
1881 if (packetp == NULL || lenp == NULL)
1882 return 1;
1883
1884 /* Let's return it: */
1885 (*packetp) = lp->data;
1886 (*lenp) = lp->len;
1887
1888 /* Remove this link from the linked list: */
1889 if (prev == NULL)
1890 net->first_ethernet_packet = lp->next;
1891 else
1892 prev->next = lp->next;
1893
1894 if (lp->next == NULL)
1895 net->last_ethernet_packet = prev;
1896 else
1897 lp->next->prev = prev;
1898
1899 free(lp);
1900
1901 /* ... and return successfully: */
1902 return 1;
1903 }
1904
1905 prev = lp;
1906 lp = lp->next;
1907 }
1908
1909 /* No packet found. :-( */
1910 return 0;
1911 }
1912
1913
1914 /*
1915 * net_ethernet_tx():
1916 *
1917 * Transmit an ethernet packet, as seen from the emulated ethernet controller.
1918 * If the packet can be handled here, it will not necessarily be transmitted
1919 * to the outside world.
1920 */
1921 void net_ethernet_tx(struct net *net, void *extra,
1922 unsigned char *packet, int len)
1923 {
1924 int i, n;
1925
1926 if (net == NULL)
1927 return;
1928
1929 /* Drop too small packets: */
1930 if (len < 20)
1931 return;
1932
1933 /* Copy this packet to all other NICs on this network: */
1934 if (extra != NULL && net->n_nics > 0) {
1935 for (i=0; i<net->n_nics; i++)
1936 if (extra != net->nic_extra[i]) {
1937 struct ethernet_packet_link *lp;
1938 lp = net_allocate_packet_link(net,
1939 net->nic_extra[i], len);
1940
1941 /* Copy the entire packet: */
1942 memcpy(lp->data, packet, len);
1943 }
1944 }
1945
1946 /* Drop packets that are not destined for the gateway: */
1947 if (memcmp(packet, net->gateway_ethernet_addr, 6) != 0
1948 && packet[0] != 0xff && packet[0] != 0x00)
1949 return;
1950
1951 #if 0
1952 fatal("[ net: ethernet: ");
1953 for (i=0; i<6; i++)
1954 fatal("%02x", packet[i]);
1955 fatal(" ");
1956 for (i=6; i<12; i++)
1957 fatal("%02x", packet[i]);
1958 fatal(" ");
1959 for (i=12; i<14; i++)
1960 fatal("%02x", packet[i]);
1961 fatal(" ");
1962 for (i=14; i<len; i++)
1963 fatal("%02x", packet[i]);
1964 fatal(" ]\n");
1965 #endif
1966
1967 /* Sprite: */
1968 if (packet[12] == 0x05 && packet[13] == 0x00) {
1969 /* TODO. */
1970 fatal("[ net: TX: UNIMPLEMENTED Sprite packet ]\n");
1971 return;
1972 }
1973
1974 /* IP: */
1975 if (packet[12] == 0x08 && packet[13] == 0x00) {
1976 /* Routed via the gateway? */
1977 if (memcmp(packet+0, net->gateway_ethernet_addr, 6) == 0) {
1978 net_ip(net, extra, packet, len);
1979 return;
1980 }
1981
1982 /* Broadcast? (DHCP does this.) */
1983 n = 0;
1984 for (i=0; i<6; i++)
1985 if (packet[i] == 0xff)
1986 n++;
1987 if (n == 6) {
1988 net_ip_broadcast(net, extra, packet, len);
1989 return;
1990 }
1991
1992 if (net->n_nics < 2) {
1993 fatal("[ net: TX: IP packet not for gateway, "
1994 "and not broadcast: ");
1995 for (i=0; i<14; i++)
1996 fatal("%02x", packet[i]);
1997 fatal(" ]\n");
1998 }
1999 return;
2000 }
2001
2002 /* ARP: */
2003 if (packet[12] == 0x08 && packet[13] == 0x06) {
2004 if (len != 60)
2005 fatal("[ net_ethernet_tx: WARNING! unusual "
2006 "ARP len (%i) ]\n", len);
2007 net_arp(net, extra, packet + 14, len - 14, 0);
2008 return;
2009 }
2010
2011 /* RARP: */
2012 if (packet[12] == 0x80 && packet[13] == 0x35) {
2013 net_arp(net, extra, packet + 14, len - 14, 1);
2014 return;
2015 }
2016
2017 /* IPv6: */
2018 if (packet[12] == 0x86 && packet[13] == 0xdd) {
2019 /* TODO. */
2020 fatal("[ net: TX: UNIMPLEMENTED IPv6 packet ]\n");
2021 return;
2022 }
2023
2024 fatal("[ net: TX: UNIMPLEMENTED ethernet packet type 0x%02x%02x! ]\n",
2025 packet[12], packet[13]);
2026 }
2027
2028
2029 /*
2030 * parse_resolvconf():
2031 *
2032 * This function parses "/etc/resolv.conf" to figure out the nameserver
2033 * and domain used by the host.
2034 */
2035 static void parse_resolvconf(struct net *net)
2036 {
2037 FILE *f;
2038 char buf[8000];
2039 size_t len;
2040 int res;
2041 unsigned int i, start;
2042
2043 /*
2044 * This is a very ugly hack, which tries to figure out which
2045 * nameserver the host uses by looking for the string 'nameserver'
2046 * in /etc/resolv.conf.
2047 *
2048 * This can later on be used for DHCP autoconfiguration. (TODO)
2049 *
2050 * TODO: This is hardcoded to use /etc/resolv.conf. Not all
2051 * operating systems use that filename.
2052 *
2053 * TODO: This is hardcoded for AF_INET (that is, IPv4).
2054 *
2055 * TODO: This assumes that the first nameserver listed is the
2056 * one to use.
2057 */
2058 f = fopen("/etc/resolv.conf", "r");
2059 if (f == NULL)
2060 return;
2061
2062 /* TODO: get rid of the hardcoded values */
2063 memset(buf, 0, sizeof(buf));
2064 len = fread(buf, 1, sizeof(buf) - 100, f);
2065 fclose(f);
2066 buf[sizeof(buf) - 1] = '\0';
2067
2068 for (i=0; i<len; i++)
2069 if (strncmp(buf+i, "nameserver", 10) == 0) {
2070 char *p;
2071
2072 /*
2073 * "nameserver" (1 or more whitespace)
2074 * "x.y.z.w" (non-digit)
2075 */
2076
2077 /* debug("found nameserver at offset %i\n", i); */
2078 i += 10;
2079 while (i<len && (buf[i]==' ' || buf[i]=='\t'))
2080 i++;
2081 if (i >= len)
2082 break;
2083 start = i;
2084
2085 p = buf+start;
2086 while ((*p >= '0' && *p <= '9') || *p == '.')
2087 p++;
2088 *p = '\0';
2089
2090 #ifdef HAVE_INET_PTON
2091 res = inet_pton(AF_INET, buf + start,
2092 &net->nameserver_ipv4);
2093 #else
2094 res = inet_aton(buf + start, &net->nameserver_ipv4);
2095 #endif
2096 if (res < 1)
2097 break;
2098
2099 net->nameserver_known = 1;
2100 break;
2101 }
2102
2103 for (i=0; i<len; i++)
2104 if (strncmp(buf+i, "domain", 6) == 0) {
2105 /* "domain" (1 or more whitespace) domain_name */
2106 i += 6;
2107 while (i<len && (buf[i]==' ' || buf[i]=='\t'))
2108 i++;
2109 if (i >= len)
2110 break;
2111
2112 start = i;
2113 while (i<len && buf[i]!='\n' && buf[i]!='\r')
2114 i++;
2115 if (i < len)
2116 buf[i] = '\0';
2117 /* fatal("DOMAIN='%s'\n", buf + start); */
2118 net->domain_name = strdup(buf + start);
2119 break;
2120 }
2121 }
2122
2123
2124 /*
2125 * net_add_nic():
2126 *
2127 * Add a NIC to a network. (All NICs on a network will see each other's
2128 * packets.)
2129 */
2130 void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
2131 {
2132 if (net == NULL)
2133 return;
2134
2135 if (extra == NULL) {
2136 fprintf(stderr, "net_add_nic(): extra = NULL\n");
2137 exit(1);
2138 }
2139
2140 net->n_nics ++;
2141 net->nic_extra = realloc(net->nic_extra, sizeof(void *)
2142 * net->n_nics);
2143 if (net->nic_extra == NULL) {
2144 fprintf(stderr, "net_add_nic(): out of memory\n");
2145 exit(1);
2146 }
2147
2148 net->nic_extra[net->n_nics - 1] = extra;
2149 }
2150
2151
2152 /*
2153 * net_gateway_init():
2154 *
2155 * This function creates a "gateway" machine (for example at IPv4 address
2156 * 10.0.0.254, if the net is 10.0.0.0/8), which acts as a gateway/router/
2157 * nameserver etc.
2158 */
2159 static void net_gateway_init(struct net *net)
2160 {
2161 unsigned char *p = (void *) &net->netmask_ipv4;
2162 uint32_t x;
2163 int xl;
2164
2165 x = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
2166 xl = 32 - net->netmask_ipv4_len;
2167 if (xl > 8)
2168 xl = 8;
2169 x |= ((1 << xl) - 1) & ~1;
2170
2171 net->gateway_ipv4_addr[0] = x >> 24;
2172 net->gateway_ipv4_addr[1] = x >> 16;
2173 net->gateway_ipv4_addr[2] = x >> 8;
2174 net->gateway_ipv4_addr[3] = x;
2175
2176 net->gateway_ethernet_addr[0] = 0x60;
2177 net->gateway_ethernet_addr[1] = 0x50;
2178 net->gateway_ethernet_addr[2] = 0x40;
2179 net->gateway_ethernet_addr[3] = 0x30;
2180 net->gateway_ethernet_addr[4] = 0x20;
2181 net->gateway_ethernet_addr[5] = 0x10;
2182 }
2183
2184
2185 /*
2186 * net_dumpinfo():
2187 *
2188 * Called from the debugger's "machine" command, to print some info about
2189 * a network.
2190 */
2191 void net_dumpinfo(struct net *net)
2192 {
2193 int iadd = 4;
2194
2195 debug("net: ");
2196
2197 net_debugaddr(&net->netmask_ipv4, ADDR_IPV4);
2198 debug("/%i", net->netmask_ipv4_len);
2199
2200 debug(" (max outgoing: TCP=%i, UDP=%i)\n",
2201 MAX_TCP_CONNECTIONS, MAX_UDP_CONNECTIONS);
2202
2203 debug_indentation(iadd);
2204
2205 debug("gateway: ");
2206 net_debugaddr(&net->gateway_ipv4_addr, ADDR_IPV4);
2207 debug(" (");
2208 net_debugaddr(&net->gateway_ethernet_addr, ADDR_ETHERNET);
2209 debug(")\n");
2210
2211 debug_indentation(iadd);
2212 if (net->domain_name != NULL && net->domain_name[0])
2213 debug("domain \"%s\", ", net->domain_name);
2214 if (!net->nameserver_known) {
2215 debug("(could not determine nameserver)");
2216 } else {
2217 debug("nameserver ");
2218 net_debugaddr(&net->nameserver_ipv4, ADDR_IPV4);
2219 }
2220 debug("\n");
2221 debug_indentation(-iadd);
2222
2223 debug_indentation(-iadd);
2224 }
2225
2226
2227 /*
2228 * net_init():
2229 *
2230 * This function creates a network, and returns a pointer to it.
2231 * Example: ipv4addr should be something like "10.0.0.0", netipv4len = 8.
2232 *
2233 * (On failure, exit() is called.)
2234 */
2235 struct net *net_init(struct emul *emul, int init_flags,
2236 char *ipv4addr, int netipv4len)
2237 {
2238 struct net *net;
2239 int res;
2240
2241 net = malloc(sizeof(struct net));
2242 if (net == NULL) {
2243 fprintf(stderr, "net_init(): out of memory\n");
2244 exit(1);
2245 }
2246
2247 memset(net, 0, sizeof(struct net));
2248
2249 /* Set the back pointer: */
2250 net->emul = emul;
2251
2252 /* Sane defaults: */
2253 net->timestamp = 0;
2254 net->first_ethernet_packet = net->last_ethernet_packet = NULL;
2255
2256 #ifdef HAVE_INET_PTON
2257 res = inet_pton(AF_INET, ipv4addr, &net->netmask_ipv4);
2258 #else
2259 res = inet_aton(ipv4addr, &net->netmask_ipv4);
2260 #endif
2261 if (res < 1) {
2262 fprintf(stderr, "net_init(): could not parse IPv4 address"
2263 " '%s'\n", ipv4addr);
2264 exit(1);
2265 }
2266
2267 if (netipv4len < 1 || netipv4len > 30) {
2268 fprintf(stderr, "net_init(): extremely weird ipv4 "
2269 "network length (%i)\n", netipv4len);
2270 exit(1);
2271 }
2272 net->netmask_ipv4_len = netipv4len;
2273
2274 net->nameserver_known = 0;
2275 net->domain_name = "";
2276 parse_resolvconf(net);
2277
2278 if (init_flags & NET_INIT_FLAG_GATEWAY)
2279 net_gateway_init(net);
2280
2281 net_dumpinfo(net);
2282
2283 /* This is neccessary when using the real network: */
2284 signal(SIGPIPE, SIG_IGN);
2285
2286 return net;
2287 }
2288

  ViewVC Help
Powered by ViewVC 1.1.26