/[gxemul]/upstream/0.3.7/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.7/src/net.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26