net_ip.cc Source File

Back to the index.

net_ip.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2010 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  * Internet Protocol related networking stuff.
29  */
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/socket.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <errno.h>
39 #include <fcntl.h>
40 
41 #include "misc.h"
42 #include "net.h"
43 
44 
45 /* #define debug fatal */
46 
47 
48 /*
49  * net_ip_checksum():
50  *
51  * Fill in an IP header checksum. (This works for ICMP too.)
52  * chksumoffset should be 10 for IP headers, and len = 20.
53  * For ICMP packets, chksumoffset = 2 and len = length of the ICMP packet.
54  */
55 void net_ip_checksum(unsigned char *ip_header, int chksumoffset, int len)
56 {
57  int i;
58  uint32_t sum = 0;
59 
60  for (i=0; i<len; i+=2)
61  if (i != chksumoffset) {
62  uint16_t w = (ip_header[i] << 8) + ip_header[i+1];
63  sum += w;
64  while (sum > 65535) {
65  int to_add = sum >> 16;
66  sum = (sum & 0xffff) + to_add;
67  }
68  }
69 
70  sum ^= 0xffff;
71  ip_header[chksumoffset + 0] = sum >> 8;
72  ip_header[chksumoffset + 1] = sum & 0xff;
73 }
74 
75 
76 /*
77  * net_ip_tcp_checksum():
78  *
79  * Fill in a TCP header checksum. This differs slightly from the IP
80  * checksum. The checksum is calculated on a pseudo header, the actual
81  * TCP header, and the data. This is what the pseudo header looks like:
82  *
83  * uint32_t srcaddr;
84  * uint32_t dstaddr;
85  * uint16_t protocol; (= 6 for tcp)
86  * uint16_t tcp_len;
87  *
88  * tcp_len is length of header PLUS data. The psedo header is created
89  * internally here, and does not need to be supplied by the caller.
90  */
91 void net_ip_tcp_checksum(unsigned char *tcp_header, int chksumoffset,
92  int tcp_len, unsigned char *srcaddr, unsigned char *dstaddr,
93  int udpflag)
94 {
95  int i, pad = 0;
96  unsigned char pseudoh[12];
97  uint32_t sum = 0;
98 
99  memcpy(pseudoh + 0, srcaddr, 4);
100  memcpy(pseudoh + 4, dstaddr, 4);
101  pseudoh[8] = 0x00;
102  pseudoh[9] = udpflag? 17 : 6;
103  pseudoh[10] = tcp_len >> 8;
104  pseudoh[11] = tcp_len & 255;
105 
106  for (i=0; i<12; i+=2) {
107  uint16_t w = (pseudoh[i] << 8) + pseudoh[i+1];
108  sum += w;
109  while (sum > 65535) {
110  int to_add = sum >> 16;
111  sum = (sum & 0xffff) + to_add;
112  }
113  }
114 
115  if (tcp_len & 1) {
116  tcp_len ++;
117  pad = 1;
118  }
119 
120  for (i=0; i<tcp_len; i+=2)
121  if (i != chksumoffset) {
122  uint16_t w;
123  if (!pad || i < tcp_len-2)
124  w = (tcp_header[i] << 8) + tcp_header[i+1];
125  else
126  w = (tcp_header[i] << 8) + 0x00;
127  sum += w;
128  while (sum > 65535) {
129  int to_add = sum >> 16;
130  sum = (sum & 0xffff) + to_add;
131  }
132  }
133 
134  sum ^= 0xffff;
135  tcp_header[chksumoffset + 0] = sum >> 8;
136  tcp_header[chksumoffset + 1] = sum & 0xff;
137 }
138 
139 
140 /*
141  * net_ip_icmp():
142  *
143  * Handle an ICMP packet.
144  *
145  * The IP header (at offset 14) could look something like
146  *
147  * ver=45 tos=00 len=0054 id=001a ofs=0000 ttl=ff p=01 sum=a87e
148  * src=0a000005 dst=03050607
149  *
150  * and the ICMP specific data (beginning at offset 34):
151  *
152  * type=08 code=00 chksum=b8bf
153  * 000c0008d5cee94089190c0008090a0b
154  * 0c0d0e0f101112131415161718191a1b
155  * 1c1d1e1f202122232425262728292a2b
156  * 2c2d2e2f3031323334353637
157  */
158 static void net_ip_icmp(struct net *net, void *extra,
159  unsigned char *packet, int len)
160 {
161  int type;
162  struct ethernet_packet_link *lp;
163 
164  type = packet[34];
165 
166  switch (type) {
167  case 8: /* ECHO request */
168  debug("[ ICMP echo ]\n");
170 
171  /* Copy the old packet first: */
172  memcpy(lp->data + 12, packet + 12, len - 12);
173 
174  /* Switch to and from ethernet addresses: */
175  memcpy(lp->data + 0, packet + 6, 6);
176  memcpy(lp->data + 6, packet + 0, 6);
177 
178  /* Switch to and from IP addresses: */
179  memcpy(lp->data + 26, packet + 30, 4);
180  memcpy(lp->data + 30, packet + 26, 4);
181 
182  /* Change from echo REQUEST to echo REPLY: */
183  lp->data[34] = 0x00;
184 
185  /* Decrease the TTL to a low value: */
186  lp->data[22] = 2;
187 
188  /* Recalculate ICMP checksum: */
189  net_ip_checksum(lp->data + 34, 2, len - 34);
190 
191  /* Recalculate IP header checksum: */
192  net_ip_checksum(lp->data + 14, 10, 20);
193 
194  break;
195  default:
196  fatal("[ net: ICMP type %i not yet implemented ]\n", type);
197  }
198 }
199 
200 
201 /*
202  * tcp_closeconnection():
203  *
204  * Helper function which closes down a TCP connection completely.
205  */
206 static void tcp_closeconnection(struct net *net, int con_id)
207 {
208  close(net->tcp_connections[con_id].socket);
210  net->tcp_connections[con_id].in_use = 0;
211  net->tcp_connections[con_id].incoming_buf_len = 0;
212 }
213 
214 
215 /*
216  * net_ip_tcp_connectionreply():
217  *
218  * When changing from state _TRYINGTOCONNECT to _CONNECTED, then this
219  * function should be called with connecting set to 1.
220  *
221  * To send a generic ack reply, set connecting to 0.
222  *
223  * To send data (PSH), set data to non-NULL and datalen to the length.
224  *
225  * This creates an ethernet packet for the guest OS with an ACK to the
226  * initial SYN packet.
227  */
228 void net_ip_tcp_connectionreply(struct net *net, void *extra,
229  int con_id, int connecting, unsigned char *data, int datalen, int rst)
230 {
231  struct ethernet_packet_link *lp;
232  int tcp_length, ip_len, option_len = 20;
233 
234  if (connecting)
235  net->tcp_connections[con_id].outside_acknr =
236  net->tcp_connections[con_id].inside_seqnr + 1;
237 
238  net->tcp_connections[con_id].tcp_id ++;
239  tcp_length = 20 + option_len + datalen;
240  ip_len = 20 + tcp_length;
241  lp = net_allocate_ethernet_packet_link(net, extra, 14 + ip_len);
242 
243  /* Ethernet header: */
244  memcpy(lp->data + 0, net->tcp_connections[con_id].ethernet_address, 6);
245  memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
246  lp->data[12] = 0x08; /* IP = 0x0800 */
247  lp->data[13] = 0x00;
248 
249  /* IP header: */
250  lp->data[14] = 0x45; /* ver */
251  lp->data[15] = 0x10; /* tos */
252  lp->data[16] = ip_len >> 8;
253  lp->data[17] = ip_len & 0xff;
254  lp->data[18] = net->tcp_connections[con_id].tcp_id >> 8;
255  lp->data[19] = net->tcp_connections[con_id].tcp_id & 0xff;
256  lp->data[20] = 0x40; /* don't fragment */
257  lp->data[21] = 0x00;
258  lp->data[22] = 0x40; /* ttl */
259  lp->data[23] = 6; /* p = TCP */
260  memcpy(lp->data + 26, net->tcp_connections[con_id].
261  outside_ip_address, 4);
262  memcpy(lp->data + 30, net->tcp_connections[con_id].
263  inside_ip_address, 4);
264  net_ip_checksum(lp->data + 14, 10, 20);
265 
266  /* TCP header and options at offset 34: */
267  lp->data[34] = net->tcp_connections[con_id].outside_tcp_port >> 8;
268  lp->data[35] = net->tcp_connections[con_id].outside_tcp_port & 0xff;
269  lp->data[36] = net->tcp_connections[con_id].inside_tcp_port >> 8;
270  lp->data[37] = net->tcp_connections[con_id].inside_tcp_port & 0xff;
271  lp->data[38] = (net->tcp_connections[con_id].
272  outside_seqnr >> 24) & 0xff;
273  lp->data[39] = (net->tcp_connections[con_id].
274  outside_seqnr >> 16) & 0xff;
275  lp->data[40] = (net->tcp_connections[con_id].
276  outside_seqnr >> 8) & 0xff;
277  lp->data[41] = net->tcp_connections[con_id].
278  outside_seqnr & 0xff;
279  lp->data[42] = (net->tcp_connections[con_id].
280  outside_acknr >> 24) & 0xff;
281  lp->data[43] = (net->tcp_connections[con_id].
282  outside_acknr >> 16) & 0xff;
283  lp->data[44] = (net->tcp_connections[con_id].
284  outside_acknr >> 8) & 0xff;
285  lp->data[45] = net->tcp_connections[con_id].outside_acknr & 0xff;
286 
287  /* Control */
288  lp->data[46] = (option_len + 20) / 4 * 0x10;
289  lp->data[47] = 0x10; /* ACK */
290  if (connecting)
291  lp->data[47] |= 0x02; /* SYN */
292  if (net->tcp_connections[con_id].state == TCP_OUTSIDE_CONNECTED)
293  lp->data[47] |= 0x08; /* PSH */
294  if (rst)
295  lp->data[47] |= 0x04; /* RST */
296  if (net->tcp_connections[con_id].state >= TCP_OUTSIDE_DISCONNECTED)
297  lp->data[47] |= 0x01; /* FIN */
298 
299  /* Window */
300  lp->data[48] = 0x10;
301  lp->data[49] = 0x00;
302 
303  /* no urgent ptr */
304 
305  /* options */
306  /* TODO: HAHA, this is ugly */
307  lp->data[54] = 0x02;
308  lp->data[55] = 0x04;
309  lp->data[56] = 0x05;
310  lp->data[57] = 0xb4;
311  lp->data[58] = 0x01;
312  lp->data[59] = 0x03;
313  lp->data[60] = 0x03;
314  lp->data[61] = 0x00;
315  lp->data[62] = 0x01;
316  lp->data[63] = 0x01;
317  lp->data[64] = 0x08;
318  lp->data[65] = 0x0a;
319  lp->data[66] = (net->timestamp >> 24) & 0xff;
320  lp->data[67] = (net->timestamp >> 16) & 0xff;
321  lp->data[68] = (net->timestamp >> 8) & 0xff;
322  lp->data[69] = net->timestamp & 0xff;
323  lp->data[70] = (net->tcp_connections[con_id].
324  inside_timestamp >> 24) & 0xff;
325  lp->data[71] = (net->tcp_connections[con_id].
326  inside_timestamp >> 16) & 0xff;
327  lp->data[72] = (net->tcp_connections[con_id].
328  inside_timestamp >> 8) & 0xff;
329  lp->data[73] = net->tcp_connections[con_id].
330  inside_timestamp & 0xff;
331 
332  /* data: */
333  if (data != NULL) {
334  memcpy(lp->data + 74, data, datalen);
335  net->tcp_connections[con_id].outside_seqnr += datalen;
336  }
337 
338  /* Checksum: */
339  net_ip_tcp_checksum(lp->data + 34, 16, tcp_length,
340  lp->data + 26, lp->data + 30, 0);
341 
342 #if 0
343  {
344  int i;
345  fatal("[ net_ip_tcp_connectionreply(%i): ", connecting);
346  for (i=0; i<ip_len+14; i++)
347  fatal("%02x", lp->data[i]);
348  fatal(" ]\n");
349  }
350 #endif
351 
352  if (connecting)
353  net->tcp_connections[con_id].outside_seqnr ++;
354 }
355 
356 
357 /*
358  * net_ip_tcp():
359  *
360  * Handle a TCP packet comming from the emulated OS.
361  *
362  * The IP header (at offset 14) could look something like
363  *
364  * ver=45 tos=00 len=003c id=0006 ofs=0000 ttl=40 p=11 sum=b798
365  * src=0a000001 dst=c1abcdef
366  *
367  * TCP header, at offset 34:
368  *
369  * srcport=fffe dstport=0015 seqnr=af419a1d acknr=00000000
370  * control=a002 window=4000 checksum=fe58 urgent=0000
371  * and then "options and padding" and then data.
372  * (020405b4010303000101080a0000000000000000)
373  *
374  * See the following URLs for good descriptions of TCP:
375  *
376  * http://www.networksorcery.com/enp/protocol/tcp.htm
377  * http://www.tcpipguide.com/free/t_TCPIPTransmissionControlProtocolTCP.htm
378  */
379 static void net_ip_tcp(struct net *net, void *extra,
380  unsigned char *packet, int len)
381 {
382  int con_id, free_con_id, i, res;
383  int srcport, dstport, data_offset, window, checksum, urgptr;
384  int syn, ack, psh, rst, urg, fin;
385  uint32_t seqnr, acknr;
386  struct sockaddr_in remote_ip;
387  fd_set rfds;
388  struct timeval tv;
389  int send_ofs;
390 
391 #if 0
392  fatal("[ net: TCP: ");
393  for (i=0; i<26; i++)
394  fatal("%02x", packet[i]);
395  fatal(" ");
396 #endif
397 
398  srcport = (packet[34] << 8) + packet[35];
399  dstport = (packet[36] << 8) + packet[37];
400 
401  seqnr = (packet[38] << 24) + (packet[39] << 16)
402  + (packet[40] << 8) + packet[41];
403  acknr = (packet[42] << 24) + (packet[43] << 16)
404  + (packet[44] << 8) + packet[45];
405 
406 #if 0
407  fatal("%i.%i.%i.%i:%i -> %i.%i.%i.%i:%i, seqnr=%lli acknr=%lli ",
408  packet[26], packet[27], packet[28], packet[29], srcport,
409  packet[30], packet[31], packet[32], packet[33], dstport,
410  (long long)seqnr, (long long)acknr);
411 #endif
412 
413  data_offset = (packet[46] >> 4) * 4 + 34;
414  /* data_offset is now data offset within packet :-) */
415 
416  urg = packet[47] & 32;
417  ack = packet[47] & 16;
418  psh = packet[47] & 8;
419  rst = packet[47] & 4;
420  syn = packet[47] & 2;
421  fin = packet[47] & 1;
422  window = (packet[48] << 8) + packet[49];
423  checksum = (packet[50] << 8) + packet[51];
424  urgptr = (packet[52] << 8) + packet[53];
425 
426 #if 0
427  fatal(urg? "URG " : "");
428  fatal(ack? "ACK " : "");
429  fatal(psh? "PSH " : "");
430  fatal(rst? "RST " : "");
431  fatal(syn? "SYN " : "");
432  fatal(fin? "FIN " : "");
433 
434  fatal("window=0x%04x checksum=0x%04x urgptr=0x%04x ",
435  window, checksum, urgptr);
436 
437  fatal("options=");
438  for (i=34+20; i<data_offset; i++)
439  fatal("%02x", packet[i]);
440 
441  fatal(" data=");
442  for (i=data_offset; i<len; i++)
443  fatal("%02x", packet[i]);
444 
445  fatal(" ]\n");
446 #endif
447 
448  net_ip_tcp_checksum(packet + 34, 16, len - 34,
449  packet + 26, packet + 30, 0);
450  if (packet[50] * 256 + packet[51] != checksum) {
451  debug("TCP: dropping packet because of checksum mismatch "
452  "(0x%04x != 0x%04x)\n", packet[50] * 256 + packet[51],
453  checksum);
454 
455  return;
456  }
457 
458  /* Does this packet belong to a current connection? */
459  con_id = free_con_id = -1;
460  for (i=0; i<MAX_TCP_CONNECTIONS; i++) {
461  if (!net->tcp_connections[i].in_use)
462  free_con_id = i;
463  if (net->tcp_connections[i].in_use &&
464  net->tcp_connections[i].inside_tcp_port == srcport &&
465  net->tcp_connections[i].outside_tcp_port == dstport &&
466  memcmp(net->tcp_connections[i].inside_ip_address,
467  packet + 26, 4) == 0 &&
468  memcmp(net->tcp_connections[i].outside_ip_address,
469  packet + 30, 4) == 0) {
470  con_id = i;
471  break;
472  }
473  }
474 
475  /*
476  * Unknown connection, and not SYN? Then drop the packet.
477  * TODO: Send back RST?
478  */
479  if (con_id < 0 && !syn) {
480  debug("[ net: TCP: dropping packet from unknown connection,"
481  " %i.%i.%i.%i:%i -> %i.%i.%i.%i:%i %s%s%s%s%s]\n",
482  packet[26], packet[27], packet[28], packet[29], srcport,
483  packet[30], packet[31], packet[32], packet[33], dstport,
484  fin? "FIN ": "", syn? "SYN ": "", ack? "ACK ": "",
485  psh? "PSH ": "", rst? "RST ": "");
486  return;
487  }
488 
489  /* Known connection, and SYN? Then ignore the packet. */
490  if (con_id >= 0 && syn) {
491  debug("[ net: TCP: ignoring redundant SYN packet from known"
492  " connection, %i.%i.%i.%i:%i -> %i.%i.%i.%i:%i ]\n",
493  packet[26], packet[27], packet[28], packet[29], srcport,
494  packet[30], packet[31], packet[32], packet[33], dstport);
495  return;
496  }
497 
498  /*
499  * A new outgoing connection?
500  */
501  if (con_id < 0 && syn) {
502  debug("[ net: TCP: new outgoing connection, %i.%i.%i.%i:%i"
503  " -> %i.%i.%i.%i:%i ]\n",
504  packet[26], packet[27], packet[28], packet[29], srcport,
505  packet[30], packet[31], packet[32], packet[33], dstport);
506 
507  /* Find a free connection id to use: */
508  if (free_con_id < 0) {
509 #if 1
510  /*
511  * TODO: Reuse the oldest one currently in use, or
512  * just drop the new connection attempt? Drop for now.
513  */
514  fatal("[ TOO MANY TCP CONNECTIONS IN USE! "
515  "Increase MAX_TCP_CONNECTIONS! ]\n");
516  return;
517 #else
518  int i;
519  int64_t oldest = net->
520  tcp_connections[0].last_used_timestamp;
521  free_con_id = 0;
522 
523  fatal("[ NO FREE TCP SLOTS, REUSING OLDEST ONE ]\n");
524  for (i=0; i<MAX_TCP_CONNECTIONS; i++)
525  if (net->tcp_connections[i].
526  last_used_timestamp < oldest) {
527  oldest = net->tcp_connections[i].
528  last_used_timestamp;
529  free_con_id = i;
530  }
531  tcp_closeconnection(net, free_con_id);
532 #endif
533  }
534 
535  con_id = free_con_id;
536  memset(&net->tcp_connections[con_id], 0,
537  sizeof(struct tcp_connection));
538 
539  memcpy(net->tcp_connections[con_id].ethernet_address,
540  packet + 6, 6);
541  memcpy(net->tcp_connections[con_id].inside_ip_address,
542  packet + 26, 4);
543  net->tcp_connections[con_id].inside_tcp_port = srcport;
544  memcpy(net->tcp_connections[con_id].outside_ip_address,
545  packet + 30, 4);
546  net->tcp_connections[con_id].outside_tcp_port = dstport;
547 
548  net->tcp_connections[con_id].socket =
549  socket(AF_INET, SOCK_STREAM, 0);
550  if (net->tcp_connections[con_id].socket < 0) {
551  fatal("[ net: TCP: socket() returned %i ]\n",
552  net->tcp_connections[con_id].socket);
553  return;
554  }
555 
556  debug("[ new tcp outgoing socket=%i ]\n",
557  net->tcp_connections[con_id].socket);
558 
559  net->tcp_connections[con_id].in_use = 1;
560 
561  /* Set the socket to non-blocking: */
562  res = fcntl(net->tcp_connections[con_id].socket, F_GETFL);
563  fcntl(net->tcp_connections[con_id].socket, F_SETFL,
564  res | O_NONBLOCK);
565 
566  remote_ip.sin_family = AF_INET;
567  memcpy((unsigned char *)&remote_ip.sin_addr,
568  net->tcp_connections[con_id].outside_ip_address, 4);
569  remote_ip.sin_port = htons(
570  net->tcp_connections[con_id].outside_tcp_port);
571 
572  res = connect(net->tcp_connections[con_id].socket,
573  (struct sockaddr *)&remote_ip, sizeof(remote_ip));
574 
575  /* connect can return -1, and errno = EINPROGRESS
576  as we might not have connected right away. */
577 
578  net->tcp_connections[con_id].state =
580 
581  net->tcp_connections[con_id].outside_acknr = 0;
582  net->tcp_connections[con_id].outside_seqnr =
583  ((random() & 0xffff) << 16) + (random() & 0xffff);
584  }
585 
586  if (rst) {
587  debug("[ 'rst': disconnecting TCP connection %i ]\n", con_id);
588  net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 1);
589  tcp_closeconnection(net, con_id);
590  return;
591  }
592 
593  if (ack && net->tcp_connections[con_id].state
595  debug("[ 'ack': guestOS's final termination of TCP "
596  "connection %i ]\n", con_id);
597 
598  /* Send an RST? (TODO, this is wrong...) */
599  net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 1);
600 
601  /* ... and forget about this connection: */
602  tcp_closeconnection(net, con_id);
603  return;
604  }
605 
606  if (fin && net->tcp_connections[con_id].state
608  debug("[ 'fin': response to outside's disconnection of "
609  "TCP connection %i ]\n", con_id);
610 
611  /* Send an ACK: */
613  net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
615  return;
616  }
617 
618  if (fin) {
619  debug("[ 'fin': guestOS disconnecting TCP connection %i ]\n",
620  con_id);
621 
622  /* Send ACK: */
623  net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
625 
626  /* Return and send FIN: */
627  goto ret;
628  }
629 
630  if (ack) {
631 debug("ACK %i bytes, inside_acknr=%u outside_seqnr=%u\n",
632  net->tcp_connections[con_id].incoming_buf_len,
633  net->tcp_connections[con_id].inside_acknr,
634  net->tcp_connections[con_id].outside_seqnr);
635  net->tcp_connections[con_id].inside_acknr = acknr;
636  if (net->tcp_connections[con_id].inside_acknr ==
637  net->tcp_connections[con_id].outside_seqnr &&
638  net->tcp_connections[con_id].incoming_buf_len != 0) {
639 debug(" all acked\n");
640  net->tcp_connections[con_id].incoming_buf_len = 0;
641  }
642  }
643 
644  net->tcp_connections[con_id].inside_seqnr = seqnr;
645 
646  /* TODO: This is hardcoded for a specific NetBSD packet: */
647  if (packet[34 + 30] == 0x08 && packet[34 + 31] == 0x0a)
648  net->tcp_connections[con_id].inside_timestamp =
649  (packet[34 + 32 + 0] << 24) +
650  (packet[34 + 32 + 1] << 16) +
651  (packet[34 + 32 + 2] << 8) +
652  (packet[34 + 32 + 3] << 0);
653 
654 
655  net->timestamp ++;
656  net->tcp_connections[con_id].last_used_timestamp = net->timestamp;
657 
658 
659  if (net->tcp_connections[con_id].state != TCP_OUTSIDE_CONNECTED) {
660  debug("[ not connected to outside ]\n");
661  return;
662  }
663 
664 
665  if (data_offset >= len)
666  return;
667 
668 
669  /*
670  * We are here if this is a known connection, and data is to be
671  * transmitted to the outside world.
672  */
673 
674  send_ofs = data_offset;
675  send_ofs += ((int32_t)net->tcp_connections[con_id].outside_acknr
676  - (int32_t)seqnr);
677 #if 1
678  debug("[ %i bytes of tcp data to be sent, beginning at seqnr %u, ",
679  len - data_offset, seqnr);
680  debug("outside is at acknr %u ==> %i actual bytes to be sent ]\n",
681  net->tcp_connections[con_id].outside_acknr, len - send_ofs);
682 #endif
683 
684  /* Drop outgoing packet if the guest OS' seqnr is not
685  the same as we have acked. (We have missed something, perhaps.) */
686  if (seqnr != net->tcp_connections[con_id].outside_acknr) {
687  debug("!! outgoing TCP packet dropped (seqnr = %u, "
688  "outside_acknr = %u)\n", seqnr,
689  net->tcp_connections[con_id].outside_acknr);
690  goto ret;
691  }
692 
693  if (len - send_ofs > 0) {
694  /* Is the socket available for output? */
695  FD_ZERO(&rfds); /* write */
696  FD_SET(net->tcp_connections[con_id].socket, &rfds);
697  tv.tv_sec = tv.tv_usec = 0;
698  errno = 0;
699  res = select(net->tcp_connections[con_id].socket+1,
700  NULL, &rfds, NULL, &tv);
701  if (res < 1) {
702  net->tcp_connections[con_id].state =
704  debug("[ TCP: disconnect on select for writing ]\n");
705  goto ret;
706  }
707 
708  res = write(net->tcp_connections[con_id].socket,
709  packet + send_ofs, len - send_ofs);
710 
711  if (res > 0) {
712  net->tcp_connections[con_id].outside_acknr += res;
713  } else if (errno == EAGAIN) {
714  /* Just ignore this attempt. */
715  return;
716  } else {
717  debug("[ error writing %i bytes to TCP connection %i:"
718  " errno = %i ]\n", len - send_ofs, con_id, errno);
719  net->tcp_connections[con_id].state =
721  debug("[ TCP: disconnect on write() ]\n");
722  goto ret;
723  }
724  }
725 
726 ret:
727  /* Send an ACK (or FIN) to the guest OS: */
728  net_ip_tcp_connectionreply(net, extra, con_id, 0, NULL, 0, 0);
729 }
730 
731 
732 /*
733  * net_ip_udp():
734  *
735  * Handle a UDP packet.
736  *
737  * (See http://www.networksorcery.com/enp/protocol/udp.htm.)
738  *
739  * The IP header (at offset 14) could look something like
740  *
741  * ver=45 tos=00 len=003c id=0006 ofs=0000 ttl=40 p=11 sum=b798
742  * src=0a000001 dst=c1abcdef
743  *
744  * and the UDP data (beginning at offset 34):
745  *
746  * srcport=fffc dstport=0035 length=0028 chksum=76b6
747  * 43e20100000100000000000003667470066e6574627364036f726700001c0001
748  */
749 static void net_ip_udp(struct net *net, void *extra,
750  unsigned char *packet, int len)
751 {
752  int con_id, free_con_id, i, srcport, dstport, udp_len;
753  ssize_t res;
754  struct sockaddr_in remote_ip;
755 
756  if ((packet[20] & 0x3f) != 0) {
757  fatal("[ net_ip_udp(): WARNING! fragmented UDP "
758  "packet, TODO ]\n");
759  return;
760  }
761 
762  srcport = (packet[34] << 8) + packet[35];
763  dstport = (packet[36] << 8) + packet[37];
764  udp_len = (packet[38] << 8) + packet[39];
765  /* chksum at offset 40 and 41 */
766 
767  debug("[ net: UDP: ");
768  debug("srcport=%i dstport=%i len=%i ", srcport, dstport, udp_len);
769  for (i=42; i<len; i++) {
770  if (packet[i] >= ' ' && packet[i] < 127)
771  debug("%c", packet[i]);
772  else
773  debug("[%02x]", packet[i]);
774  }
775  debug(" ]\n");
776 
777  /* Is this "connection" new, or a currently ongoing one? */
778  con_id = free_con_id = -1;
779  for (i=0; i<MAX_UDP_CONNECTIONS; i++) {
780  if (!net->udp_connections[i].in_use)
781  free_con_id = i;
782  if (net->udp_connections[i].in_use &&
783  net->udp_connections[i].inside_udp_port == srcport &&
784  net->udp_connections[i].outside_udp_port == dstport &&
785  memcmp(net->udp_connections[i].inside_ip_address,
786  packet + 26, 4) == 0 &&
787  memcmp(net->udp_connections[i].outside_ip_address,
788  packet + 30, 4) == 0) {
789  con_id = i;
790  break;
791  }
792  }
793 
794  debug("&& UDP connection is ");
795  if (con_id >= 0)
796  debug("ONGOING");
797  else {
798  debug("NEW");
799  if (free_con_id < 0) {
800  int64_t oldest = net->
801  udp_connections[0].last_used_timestamp;
802  free_con_id = 0;
803 
804  debug(", NO FREE SLOTS, REUSING OLDEST ONE");
805  for (int j=0; j<MAX_UDP_CONNECTIONS; j++)
806  if (net->udp_connections[j].last_used_timestamp < oldest) {
807  oldest = net->udp_connections[j].last_used_timestamp;
808  free_con_id = j;
809  }
810 
811  close(net->udp_connections[free_con_id].socket);
812  }
813  con_id = free_con_id;
814  memset(&net->udp_connections[con_id], 0,
815  sizeof(struct udp_connection));
816 
817  memcpy(net->udp_connections[con_id].ethernet_address,
818  packet + 6, 6);
819  memcpy(net->udp_connections[con_id].inside_ip_address,
820  packet + 26, 4);
821  net->udp_connections[con_id].inside_udp_port = srcport;
822  memcpy(net->udp_connections[con_id].outside_ip_address,
823  packet + 30, 4);
824  net->udp_connections[con_id].outside_udp_port = dstport;
825 
826  net->udp_connections[con_id].socket = socket(AF_INET,
827  SOCK_DGRAM, 0);
828  if (net->udp_connections[con_id].socket < 0) {
829  fatal("[ net: UDP: socket() returned %i ]\n",
830  net->udp_connections[con_id].socket);
831  return;
832  }
833 
834  debug(" {socket=%i}", net->udp_connections[con_id].socket);
835 
836  net->udp_connections[con_id].in_use = 1;
837 
838  /* Set the socket to non-blocking: */
839  res = fcntl(net->udp_connections[con_id].socket, F_GETFL);
840  fcntl(net->udp_connections[con_id].socket, F_SETFL,
841  res | O_NONBLOCK);
842  }
843 
844  debug(", connection id %i\n", con_id);
845 
846  net->timestamp ++;
847  net->udp_connections[con_id].last_used_timestamp = net->timestamp;
848 
849  remote_ip.sin_family = AF_INET;
850  memcpy((unsigned char *)&remote_ip.sin_addr,
851  net->udp_connections[con_id].outside_ip_address, 4);
852 
853  /*
854  * Special case for the nameserver: If a UDP packet is sent to
855  * the gateway, it will be forwarded to the nameserver, if it is
856  * known.
857  */
858  if (net->nameserver_known &&
859  memcmp(net->udp_connections[con_id].outside_ip_address,
860  &net->gateway_ipv4_addr[0], 4) == 0) {
861  memcpy((unsigned char *)&remote_ip.sin_addr,
862  &net->nameserver_ipv4, 4);
863  net->udp_connections[con_id].fake_ns = 1;
864  }
865 
866  remote_ip.sin_port = htons(
867  net->udp_connections[con_id].outside_udp_port);
868 
869  res = sendto(net->udp_connections[con_id].socket, packet + 42,
870  len - 42, 0, (const struct sockaddr *)&remote_ip,
871  sizeof(remote_ip));
872 
873  if (res != len-42)
874  debug("[ net: UDP: unable to send %i bytes ]\n", len-42);
875  else
876  debug("[ net: UDP: OK!!! ]\n");
877 }
878 
879 
880 /*
881  * net_ip():
882  *
883  * Handle an IP packet, coming from the emulated NIC.
884  */
885 void net_ip(struct net *net, void *extra, unsigned char *packet, int len)
886 {
887 #if 1
888  int i;
889 
890  debug("[ net: IP: ");
891  debug("ver=%02x ", packet[14]);
892  debug("tos=%02x ", packet[15]);
893  debug("len=%02x%02x ", packet[16], packet[17]);
894  debug("id=%02x%02x ", packet[18], packet[19]);
895  debug("ofs=%02x%02x ", packet[20], packet[21]);
896  debug("ttl=%02x ", packet[22]);
897  debug("p=%02x ", packet[23]);
898  debug("sum=%02x%02x ", packet[24], packet[25]);
899  debug("src=%02x%02x%02x%02x ",
900  packet[26], packet[27], packet[28], packet[29]);
901  debug("dst=%02x%02x%02x%02x ",
902  packet[30], packet[31], packet[32], packet[33]);
903  for (i=34; i<len; i++)
904  debug("%02x", packet[i]);
905  debug(" ]\n");
906 #endif
907 
908  /* Cut off overflowing tail data: */
909  if (len > 14 + packet[16]*256 + packet[17])
910  len = 14 + packet[16]*256 + packet[17];
911 
912  if (packet[14] == 0x45) {
913  /* IPv4: */
914  switch (packet[23]) {
915  case 1: /* ICMP */
916  net_ip_icmp(net, extra, packet, len);
917  break;
918  case 6: /* TCP */
919  net_ip_tcp(net, extra, packet, len);
920  break;
921  case 17:/* UDP */
922  net_ip_udp(net, extra, packet, len);
923  break;
924  default:
925  fatal("[ net: IP: UNIMPLEMENTED protocol %i ]\n",
926  packet[23]);
927  }
928  } else
929  fatal("[ net: IP: UNIMPLEMENTED ip, first byte = 0x%02x ]\n",
930  packet[14]);
931 }
932 
933 
934 /*
935  * net_ip_broadcast_dhcp():
936  *
937  * Handle an IPv4 DHCP broadcast packet, coming from the emulated NIC.
938  *
939  * Read http://tools.ietf.org/html/rfc2131 for details on DHCP.
940  * (And http://users.telenet.be/mydotcom/library/network/dhcp.htm.)
941  */
942 static void net_ip_broadcast_dhcp(struct net *net, void *extra,
943  unsigned char *packet, int len)
944 {
945  /*
946  * TODO
947  */
948 #if 1
949  struct ethernet_packet_link *lp;
950  int i, reply_len;
951 
952  fatal("[ net: IPv4 DHCP: ");
953 #if 1
954  fatal("ver=%02x ", packet[14]);
955  fatal("tos=%02x ", packet[15]);
956  fatal("len=%02x%02x ", packet[16], packet[17]);
957  fatal("id=%02x%02x ", packet[18], packet[19]);
958  fatal("ofs=%02x%02x ", packet[20], packet[21]);
959  fatal("ttl=%02x ", packet[22]);
960  fatal("p=%02x ", packet[23]);
961  fatal("sum=%02x%02x ", packet[24], packet[25]);
962 #endif
963  fatal("src=%02x%02x%02x%02x ",
964  packet[26], packet[27], packet[28], packet[29]);
965  fatal("dst=%02x%02x%02x%02x ",
966  packet[30], packet[31], packet[32], packet[33]);
967 #if 0
968  for (i=34; i<len; i++)
969  fatal("%02x", packet[i]);
970 #endif
971 
972  if (len < 34 + 8 + 236) {
973  fatal("[ DHCP packet too short? Len=%i ]\n", len);
974  return;
975  }
976 
977  /*
978  * UDP data (at offset 34):
979  *
980  * srcport=0044 dstport=0043 length=0134 chksum=a973
981  * data = 01010600d116d276000000000000000000000000000000
982  * 0000000000102030405060...0000...638253633501...000
983  */
984 
985  fatal("op=%02x ", packet[42]);
986  fatal("htype=%02x ", packet[43]);
987  fatal("hlen=%02x ", packet[44]);
988  fatal("hops=%02x ", packet[45]);
989  fatal("xid=%02x%02x%02x%02x ", packet[46], packet[47],
990  packet[48], packet[49]);
991  fatal("secs=%02x%02x ", packet[50], packet[51]);
992  fatal("flags=%02x%02x ", packet[52], packet[53]);
993  fatal("ciaddr=%02x%02x%02x%02x ", packet[54], packet[55],
994  packet[56], packet[57]);
995  fatal("yiaddr=%02x%02x%02x%02x ", packet[58], packet[59],
996  packet[60], packet[61]);
997  fatal("siaddr=%02x%02x%02x%02x ", packet[62], packet[63],
998  packet[64], packet[65]);
999  fatal("giaddr=%02x%02x%02x%02x ", packet[66], packet[67],
1000  packet[68], packet[69]);
1001  fatal("chaddr=");
1002  for (i=70; i<70+16; i++)
1003  fatal("%02x", packet[i]);
1004  /*
1005  | sname (64) |
1006  | file (128) |
1007  */
1008  fatal(" ]\n");
1009 
1010  reply_len = 307;
1011  lp = net_allocate_ethernet_packet_link(net, extra, reply_len);
1012 
1013  /* From old packet, copy everything before options field: */
1014  memcpy(lp->data, packet, 278);
1015 
1016  /* We are sending to the client, from the gateway: */
1017  memcpy(lp->data + 0, packet + 6, 6);
1018  memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
1019 
1020  /* Set IP length: */
1021  lp->data[16] = (reply_len - 14) >> 8;
1022  lp->data[17] = (reply_len - 14) & 0xff;
1023 
1024  /* Set IP addresses: */
1025  memcpy(lp->data + 26, &net->gateway_ipv4_addr[0], 4);
1026  lp->data[30] = 0xff;
1027  lp->data[31] = 0xff;
1028  lp->data[32] = 0xff;
1029  lp->data[33] = 0xff;
1030 
1031  /* Switch src and dst ports: */
1032  memcpy(lp->data + 34, packet + 36, 2);
1033  memcpy(lp->data + 36, packet + 34, 2);
1034 
1035  /* Set UDP length: */
1036  lp->data[38] = (reply_len - 34) >> 8;
1037  lp->data[39] = (reply_len - 34) & 0xff;
1038 
1039  /* Client's (yiaddr) IPv4 address: */
1040  lp->data[58] = 10;
1041  lp->data[59] = 0;
1042  lp->data[60] = 0;
1043  lp->data[61] = 1;
1044 
1045  /* Server's IPv4 address: (giaddr) */
1046  memcpy(lp->data + 66, &net->gateway_ipv4_addr[0], 4);
1047 
1048  /* This is a Reply: */
1049  lp->data[42] = 0x02;
1050 
1051  snprintf((char *)lp->data + 70+16+64, 8, "gxemul");
1052 
1053  /* Options field at offset 278: */
1054  lp->data[278] = 99;
1055  lp->data[279] = 130;
1056  lp->data[280] = 83;
1057  lp->data[281] = 99;
1058 
1059  /* DHCP options, http://tools.ietf.org/html/rfc1533 */
1060  lp->data[282] = 1; /* subnet mask */
1061  lp->data[283] = 4;
1062  lp->data[284] = 255;
1063  lp->data[285] = 0;
1064  lp->data[286] = 0;
1065  lp->data[287] = 0;
1066  lp->data[288] = 3; /* router */
1067  lp->data[289] = 4;
1068  memcpy(lp->data + 290, &net->gateway_ipv4_addr[0], 4);
1069  lp->data[294] = 6; /* domain name server */
1070  lp->data[295] = 4;
1071  memcpy(lp->data + 296, &net->gateway_ipv4_addr[0], 4);
1072  lp->data[300] = 54; /* server identifier */
1073  lp->data[301] = 4;
1074  memcpy(lp->data + 302, &net->gateway_ipv4_addr[0], 4);
1075  lp->data[306] = 255; /* end */
1076 
1077  /* Recalculate IP header checksum: */
1078  net_ip_checksum(lp->data + 14, 10, 20);
1079 
1080  /* ... and the UDP checksum: */
1081  net_ip_tcp_checksum(lp->data + 34, 6, reply_len - 34,
1082  lp->data + 26, lp->data + 30, 1);
1083 
1084 
1085 /* Debug dump: */
1086 packet = lp->data;
1087  fatal("[ net: IPv4 DHCP REPLY: ");
1088  for (i=0; i<14; i++)
1089  fatal("%02x", packet[i]);
1090  fatal("ver=%02x ", packet[14]);
1091  fatal("tos=%02x ", packet[15]);
1092  fatal("len=%02x%02x ", packet[16], packet[17]);
1093  fatal("id=%02x%02x ", packet[18], packet[19]);
1094  fatal("ofs=%02x%02x ", packet[20], packet[21]);
1095  fatal("ttl=%02x ", packet[22]);
1096  fatal("p=%02x ", packet[23]);
1097  fatal("sum=%02x%02x ", packet[24], packet[25]);
1098  fatal("src=%02x%02x%02x%02x ",
1099  packet[26], packet[27], packet[28], packet[29]);
1100  fatal("dst=%02x%02x%02x%02x ",
1101  packet[30], packet[31], packet[32], packet[33]);
1102  fatal("op=%02x ", packet[42]);
1103  fatal("htype=%02x ", packet[43]);
1104  fatal("hlen=%02x ", packet[44]);
1105  fatal("hops=%02x ", packet[45]);
1106  fatal("xid=%02x%02x%02x%02x ", packet[46], packet[47],
1107  packet[48], packet[49]);
1108  fatal("secs=%02x%02x ", packet[50], packet[51]);
1109  fatal("flags=%02x%02x ", packet[52], packet[53]);
1110  fatal("ciaddr=%02x%02x%02x%02x ", packet[54], packet[55],
1111  packet[56], packet[57]);
1112  fatal("yiaddr=%02x%02x%02x%02x ", packet[58], packet[59],
1113  packet[60], packet[61]);
1114  fatal("siaddr=%02x%02x%02x%02x ", packet[62], packet[63],
1115  packet[64], packet[65]);
1116  fatal("giaddr=%02x%02x%02x%02x ", packet[66], packet[67],
1117  packet[68], packet[69]);
1118  fatal("chaddr=");
1119  for (i=70; i<70+16; i++)
1120  fatal("%02x", packet[i]);
1121  fatal(" ]\n");
1122 
1123 #endif
1124 }
1125 
1126 
1127 /*
1128  * net_ip_broadcast():
1129  *
1130  * Handle an IP broadcast packet, coming from the emulated NIC.
1131  * (This is usually a DHCP request, or similar.)
1132  */
1133 void net_ip_broadcast(struct net *net, void *extra,
1134  unsigned char *packet, int len)
1135 {
1136  unsigned char *p = (unsigned char *) &net->netmask_ipv4;
1137  uint32_t x, y;
1138  int i, xl, warning = 0, match = 0;
1139 
1140 #if 0
1141  fatal("[ net: IP BROADCAST: ");
1142  fatal("ver=%02x ", packet[14]);
1143  fatal("tos=%02x ", packet[15]);
1144  fatal("len=%02x%02x ", packet[16], packet[17]);
1145  fatal("id=%02x%02x ", packet[18], packet[19]);
1146  fatal("ofs=%02x%02x ", packet[20], packet[21]);
1147  fatal("ttl=%02x ", packet[22]);
1148  fatal("p=%02x ", packet[23]);
1149  fatal("sum=%02x%02x ", packet[24], packet[25]);
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  for (i=34; i<len; i++)
1155  fatal("%02x", packet[i]);
1156  fatal(" ]\n");
1157 #endif
1158 
1159  /* Check for 10.0.0.255 first, maybe some guest OSes think that
1160  it's a /24 network, regardless of what it actually is. */
1161  y = (packet[30] << 24) + (packet[31] << 16) +
1162  (packet[32] << 8) + packet[33];
1163 
1164  x = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
1165  /* Example: x = 10.0.0.0 */
1166  x |= 255;
1167 
1168  if (x == y) {
1169  warning = 1;
1170  match = 1;
1171  }
1172 
1173  xl = 32 - net->netmask_ipv4_len;
1174  x |= (1 << xl) - 1;
1175  /* x = 10.255.255.255 */
1176 
1177  if (x == y)
1178  match = 1;
1179  if (y == 0xffffffff)
1180  match = 1;
1181 
1182  if (warning)
1183  fatal("[ net_ip_broadcast(): warning: broadcast to "
1184  "0x%08x, expecting broadcast to 0x%08x or "
1185  "0xffffffff ]\n", y, x);
1186 
1187  /* Cut off overflowing tail data: */
1188  if (len > 14 + packet[16]*256 + packet[17])
1189  len = 14 + packet[16]*256 + packet[17];
1190 
1191  /* Check for known packets: */
1192  if (packet[14] == 0x45 && /* IPv4 */
1193  packet[23] == 0x11 && /* UDP */
1194  packet[34] == 0 && packet[35] == 68 && /* DHCP client */
1195  packet[36] == 0 && packet[37] == 67) { /* DHCP server */
1196  net_ip_broadcast_dhcp(net, extra, packet, len);
1197  return;
1198  }
1199 
1200  /* Unknown packet: */
1201  fatal("[ net: UNIMPLEMENTED IP BROADCAST: ");
1202  fatal("ver=%02x ", packet[14]);
1203  fatal("tos=%02x ", packet[15]);
1204  fatal("len=%02x%02x ", packet[16], packet[17]);
1205  fatal("id=%02x%02x ", packet[18], packet[19]);
1206  fatal("ofs=%02x%02x ", packet[20], packet[21]);
1207  fatal("ttl=%02x ", packet[22]);
1208  fatal("p=%02x ", packet[23]);
1209  fatal("sum=%02x%02x ", packet[24], packet[25]);
1210  fatal("src=%02x%02x%02x%02x ",
1211  packet[26], packet[27], packet[28], packet[29]);
1212  fatal("dst=%02x%02x%02x%02x ",
1213  packet[30], packet[31], packet[32], packet[33]);
1214  for (i=34; i<len; i++)
1215  fatal("%02x", packet[i]);
1216  fatal(" ]\n");
1217 }
1218 
1219 
1220 /*
1221  * net_udp_rx_avail():
1222  *
1223  * Receive any available UDP packets (from the outside world).
1224  */
1225 void net_udp_rx_avail(struct net *net, void *extra)
1226 {
1227  int received_packets_this_tick = 0;
1228  int max_packets_this_tick = 200;
1229  int con_id;
1230 
1231  for (con_id=0; con_id<MAX_UDP_CONNECTIONS; con_id++) {
1232  ssize_t res;
1233  unsigned char buf[66000];
1234  unsigned char udp_data[66008];
1235  struct sockaddr_in from;
1236  socklen_t from_len = sizeof(from);
1237  int ip_len, udp_len;
1238  struct ethernet_packet_link *lp;
1239  int max_per_packet;
1240  int bytes_converted = 0;
1241  int this_packets_data_length;
1242  int fragment_ofs = 0;
1243 
1244  if (received_packets_this_tick > max_packets_this_tick)
1245  break;
1246 
1247  if (!net->udp_connections[con_id].in_use)
1248  continue;
1249 
1250  if (net->udp_connections[con_id].socket < 0) {
1251  fatal("INTERNAL ERROR in net.c, udp socket < 0 "
1252  "but in use?\n");
1253  continue;
1254  }
1255 
1256  res = recvfrom(net->udp_connections[con_id].socket, buf,
1257  sizeof(buf), 0, (struct sockaddr *)&from, &from_len);
1258 
1259  /* No more incoming UDP on this connection? */
1260  if (res < 0)
1261  continue;
1262 
1263  net->timestamp ++;
1264  net->udp_connections[con_id].last_used_timestamp =
1265  net->timestamp;
1266 
1267  net->udp_connections[con_id].udp_id ++;
1268 
1269  /*
1270  * Special case for the nameserver: If a UDP packet is
1271  * received from the nameserver (if the nameserver's IP is
1272  * known), fake it so that it comes from the gateway instead.
1273  */
1274  if (net->udp_connections[con_id].fake_ns)
1275  memcpy(((unsigned char *)(&from))+4,
1276  &net->gateway_ipv4_addr[0], 4);
1277 
1278  /*
1279  * We now have a UDP packet of size 'res' which we need
1280  * turn into one or more ethernet packets for the emulated
1281  * operating system. Ethernet packets are at most 1518
1282  * bytes long. With some margin, that means we can have
1283  * about 1500 bytes per packet.
1284  *
1285  * Ethernet = 14 bytes
1286  * IP = 20 bytes
1287  * (UDP = 8 bytes + data)
1288  *
1289  * So data can be at most max_per_packet - 34. For UDP
1290  * fragments, each multiple should (?) be a multiple of
1291  * 8 bytes, except the last which doesn't have any such
1292  * restriction.
1293  */
1294  max_per_packet = 1500;
1295 
1296  /* UDP: */
1297  udp_len = res + 8;
1298  /* from[2..3] = outside_udp_port */
1299  udp_data[0] = ((unsigned char *)&from)[2];
1300  udp_data[1] = ((unsigned char *)&from)[3];
1301  udp_data[2] = (net->udp_connections[con_id].
1302  inside_udp_port >> 8) & 0xff;
1303  udp_data[3] = net->udp_connections[con_id].
1304  inside_udp_port & 0xff;
1305  udp_data[4] = udp_len >> 8;
1306  udp_data[5] = udp_len & 0xff;
1307  udp_data[6] = 0;
1308  udp_data[7] = 0;
1309  memcpy(udp_data + 8, buf, res);
1310  /*
1311  * TODO: UDP checksum, if necessary. At least NetBSD
1312  * and OpenBSD accept UDP packets with 0x0000 in the
1313  * checksum field anyway.
1314  */
1315 
1316  while (bytes_converted < udp_len) {
1317  this_packets_data_length = udp_len - bytes_converted;
1318 
1319  /* Do we need to fragment? */
1320  if (this_packets_data_length > max_per_packet-34) {
1321  this_packets_data_length =
1322  max_per_packet - 34;
1323  while (this_packets_data_length & 7)
1324  this_packets_data_length --;
1325  }
1326 
1327  ip_len = 20 + this_packets_data_length;
1328 
1329  lp = net_allocate_ethernet_packet_link(net, extra,
1330  14 + 20 + this_packets_data_length);
1331 
1332  /* Ethernet header: */
1333  memcpy(lp->data + 0, net->udp_connections[con_id].
1334  ethernet_address, 6);
1335  memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
1336  lp->data[12] = 0x08; /* IP = 0x0800 */
1337  lp->data[13] = 0x00;
1338 
1339  /* IP header: */
1340  lp->data[14] = 0x45; /* ver */
1341  lp->data[15] = 0x00; /* tos */
1342  lp->data[16] = ip_len >> 8;
1343  lp->data[17] = ip_len & 0xff;
1344  lp->data[18] = net->udp_connections[con_id].udp_id >> 8;
1345  lp->data[19] = net->udp_connections[con_id].udp_id
1346  & 0xff;
1347  lp->data[20] = (fragment_ofs >> 8);
1348  if (bytes_converted + this_packets_data_length
1349  < udp_len)
1350  lp->data[20] |= 0x20; /* More fragments */
1351  lp->data[21] = fragment_ofs & 0xff;
1352  lp->data[22] = 0x40; /* ttl */
1353  lp->data[23] = 17; /* p = UDP */
1354  lp->data[26] = ((unsigned char *)&from)[4];
1355  lp->data[27] = ((unsigned char *)&from)[5];
1356  lp->data[28] = ((unsigned char *)&from)[6];
1357  lp->data[29] = ((unsigned char *)&from)[7];
1358  memcpy(lp->data + 30, net->udp_connections[con_id].
1359  inside_ip_address, 4);
1360  net_ip_checksum(lp->data + 14, 10, 20);
1361 
1362  memcpy(lp->data+34, udp_data + bytes_converted,
1363  this_packets_data_length);
1364 
1365  bytes_converted += this_packets_data_length;
1366  fragment_ofs = bytes_converted / 8;
1367 
1368  received_packets_this_tick ++;
1369  }
1370 
1371  /* This makes sure we check this connection AGAIN
1372  for more incoming UDP packets, before moving to the
1373  next connection: */
1374  con_id --;
1375  }
1376 }
1377 
1378 
1379 /*
1380  * net_tcp_rx_avail():
1381  *
1382  * Receive any available TCP packets (from the outside world).
1383  */
1384 void net_tcp_rx_avail(struct net *net, void *extra)
1385 {
1386  int received_packets_this_tick = 0;
1387  int max_packets_this_tick = 200;
1388  int con_id;
1389 
1390  for (con_id=0; con_id<MAX_TCP_CONNECTIONS; con_id++) {
1391  unsigned char buf[66000];
1392  ssize_t res, res2;
1393  fd_set rfds;
1394  struct timeval tv;
1395 
1396  if (received_packets_this_tick > max_packets_this_tick)
1397  break;
1398 
1399  if (!net->tcp_connections[con_id].in_use)
1400  continue;
1401 
1402  if (net->tcp_connections[con_id].socket < 0) {
1403  fatal("INTERNAL ERROR in net.c, tcp socket < 0"
1404  " but in use?\n");
1405  continue;
1406  }
1407 
1408  if (net->tcp_connections[con_id].incoming_buf == NULL)
1409  CHECK_ALLOCATION(net->tcp_connections[con_id].
1410  incoming_buf = (unsigned char *) malloc(TCP_INCOMING_BUF_LEN));
1411 
1412  if (net->tcp_connections[con_id].state >=
1414  continue;
1415 
1416  /* Is the socket available for output? */
1417  FD_ZERO(&rfds); /* write */
1418  FD_SET(net->tcp_connections[con_id].socket, &rfds);
1419  tv.tv_sec = tv.tv_usec = 0;
1420  errno = 0;
1421  res = select(net->tcp_connections[con_id].socket+1,
1422  NULL, &rfds, NULL, &tv);
1423 
1424  if (errno == ECONNREFUSED) {
1425  fatal("[ ECONNREFUSED: TODO ]\n");
1426  net->tcp_connections[con_id].state =
1428  fatal("CHANGING TO TCP_OUTSIDE_DISCONNECTED "
1429  "(refused connection)\n");
1430  continue;
1431  }
1432 
1433  if (errno == ETIMEDOUT) {
1434  fatal("[ ETIMEDOUT: TODO ]\n");
1435  /* TODO */
1436  net->tcp_connections[con_id].state =
1438  fatal("CHANGING TO TCP_OUTSIDE_DISCONNECTED "
1439  "(timeout)\n");
1440  continue;
1441  }
1442 
1443  if (net->tcp_connections[con_id].state ==
1444  TCP_OUTSIDE_TRYINGTOCONNECT && res > 0) {
1445  net->tcp_connections[con_id].state =
1447  debug("CHANGING TO TCP_OUTSIDE_CONNECTED\n");
1448  net_ip_tcp_connectionreply(net, extra, con_id, 1,
1449  NULL, 0, 0);
1450  }
1451 
1452  if (net->tcp_connections[con_id].state ==
1453  TCP_OUTSIDE_CONNECTED && res < 1) {
1454  continue;
1455  }
1456 
1457  /*
1458  * Does this connection have unacknowledged data? Then, if
1459  * enough number of rounds have passed, try to resend it using
1460  * the old value of seqnr.
1461  */
1462  if (net->tcp_connections[con_id].incoming_buf_len != 0) {
1463  net->tcp_connections[con_id].incoming_buf_rounds ++;
1464  if (net->tcp_connections[con_id].incoming_buf_rounds >
1465  10000) {
1466  debug(" at seqnr %u but backing back to %u,"
1467  " resending %i bytes\n",
1468  net->tcp_connections[con_id].outside_seqnr,
1469  net->tcp_connections[con_id].
1470  incoming_buf_seqnr,
1471  net->tcp_connections[con_id].
1472  incoming_buf_len);
1473 
1474  net->tcp_connections[con_id].
1475  incoming_buf_rounds = 0;
1476  net->tcp_connections[con_id].outside_seqnr =
1477  net->tcp_connections[con_id].
1478  incoming_buf_seqnr;
1479 
1480  net_ip_tcp_connectionreply(net, extra, con_id,
1481  0, net->tcp_connections[con_id].
1482  incoming_buf,
1483  net->tcp_connections[con_id].
1484  incoming_buf_len, 0);
1485  }
1486  continue;
1487  }
1488 
1489  /* Don't receive unless the guest OS is ready! */
1490  if (((int32_t)net->tcp_connections[con_id].outside_seqnr -
1491  (int32_t)net->tcp_connections[con_id].inside_acknr) > 0) {
1492 /* fatal("YOYO 1! outside_seqnr - inside_acknr = %i\n",
1493  net->tcp_connections[con_id].outside_seqnr -
1494  net->tcp_connections[con_id].inside_acknr); */
1495  continue;
1496  }
1497 
1498  /* Is there incoming data available on the socket? */
1499  FD_ZERO(&rfds); /* read */
1500  FD_SET(net->tcp_connections[con_id].socket, &rfds);
1501  tv.tv_sec = tv.tv_usec = 0;
1502  res2 = select(net->tcp_connections[con_id].socket+1, &rfds,
1503  NULL, NULL, &tv);
1504 
1505  /* No more incoming TCP data on this connection? */
1506  if (res2 < 1)
1507  continue;
1508 
1509  res = read(net->tcp_connections[con_id].socket, buf, 1400);
1510  if (res > 0) {
1511  /* debug("\n -{- %lli -}-\n", (long long)res); */
1512  net->tcp_connections[con_id].incoming_buf_len = res;
1513  net->tcp_connections[con_id].incoming_buf_rounds = 0;
1514  net->tcp_connections[con_id].incoming_buf_seqnr =
1515  net->tcp_connections[con_id].outside_seqnr;
1516  debug(" putting %i bytes (seqnr %u) in the incoming "
1517  "buf\n", res, net->tcp_connections[con_id].
1518  incoming_buf_seqnr);
1519  memcpy(net->tcp_connections[con_id].incoming_buf,
1520  buf, res);
1521 
1522  net_ip_tcp_connectionreply(net, extra, con_id, 0,
1523  buf, res, 0);
1524  } else if (res == 0) {
1525  net->tcp_connections[con_id].state =
1527  debug("CHANGING TO TCP_OUTSIDE_DISCONNECTED, read"
1528  " res=0\n");
1529  net_ip_tcp_connectionreply(net, extra, con_id, 0,
1530  NULL, 0, 0);
1531  } else {
1532  net->tcp_connections[con_id].state =
1534  fatal("CHANGING TO TCP_OUTSIDE_DISCONNECTED, "
1535  "read res<=0, errno = %i\n", errno);
1536  net_ip_tcp_connectionreply(net, extra, con_id, 0,
1537  NULL, 0, 0);
1538  }
1539 
1540  net->timestamp ++;
1541  net->tcp_connections[con_id].last_used_timestamp =
1542  net->timestamp;
1543  }
1544 }
1545 
1546 
void fatal(const char *fmt,...)
Definition: main.cc:152
#define TCP_INCOMING_BUF_LEN
Definition: net.h:216
unsigned char gateway_ipv4_addr[4]
Definition: net.h:132
uint32_t inside_seqnr
Definition: net.h:99
unsigned char outside_ip_address[4]
Definition: net.h:79
void net_ip_tcp_connectionreply(struct net *net, void *extra, int con_id, int connecting, unsigned char *data, int datalen, int rst)
Definition: net_ip.cc:228
unsigned char * incoming_buf
Definition: net.h:94
int64_t timestamp
Definition: net.h:140
int inside_udp_port
Definition: net.h:71
int outside_tcp_port
Definition: net.h:109
#define TCP_OUTSIDE_DISCONNECTED2
Definition: net.h:214
uint32_t outside_seqnr
Definition: net.h:101
#define MAX_TCP_CONNECTIONS
Definition: net.h:116
unsigned char inside_ip_address[4]
Definition: net.h:70
uint32_t outside_acknr
Definition: net.h:102
unsigned char ethernet_address[6]
Definition: net.h:88
int fake_ns
Definition: net.h:74
void net_ip_checksum(unsigned char *ip_header, int chksumoffset, int len)
Definition: net_ip.cc:55
struct ethernet_packet_link * net_allocate_ethernet_packet_link(struct net *net, void *extra, size_t len)
Definition: net.cc:72
unsigned char ethernet_address[6]
Definition: net.h:69
int in_use
Definition: net.h:84
#define TCP_OUTSIDE_TRYINGTOCONNECT
Definition: net.h:211
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
int state
Definition: net.h:105
unsigned char inside_ip_address[4]
Definition: net.h:89
u_short data
Definition: siireg.h:79
int64_t last_used_timestamp
Definition: net.h:66
uint32_t inside_timestamp
Definition: net.h:91
Definition: net.h:119
#define TCP_OUTSIDE_DISCONNECTED
Definition: net.h:213
void net_ip_tcp_checksum(unsigned char *tcp_header, int chksumoffset, int tcp_len, unsigned char *srcaddr, unsigned char *dstaddr, int udpflag)
Definition: net_ip.cc:91
int in_use
Definition: net.h:65
int tcp_id
Definition: net.h:106
int udp_id
Definition: net.h:77
unsigned char outside_ip_address[4]
Definition: net.h:108
int incoming_buf_rounds
Definition: net.h:95
#define TCP_OUTSIDE_CONNECTED
Definition: net.h:212
struct in_addr nameserver_ipv4
Definition: net.h:138
#define debug
Definition: dev_adb.cc:57
int inside_tcp_port
Definition: net.h:90
void net_ip_broadcast(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net_ip.cc:1133
int64_t last_used_timestamp
Definition: net.h:85
int incoming_buf_len
Definition: net.h:96
int outside_udp_port
Definition: net.h:80
void net_udp_rx_avail(struct net *net, void *extra)
Definition: net_ip.cc:1225
#define MAX_UDP_CONNECTIONS
Definition: net.h:117
int netmask_ipv4_len
Definition: net.h:125
int socket
Definition: net.h:107
void net_tcp_rx_avail(struct net *net, void *extra)
Definition: net_ip.cc:1384
struct in_addr netmask_ipv4
Definition: net.h:124
uint32_t inside_acknr
Definition: net.h:100
unsigned char gateway_ethernet_addr[6]
Definition: net.h:133
struct udp_connection udp_connections[MAX_UDP_CONNECTIONS]
Definition: net.h:145
int socket
Definition: net.h:78
uint32_t incoming_buf_seqnr
Definition: net.h:97
void net_ip(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net_ip.cc:885
int nameserver_known
Definition: net.h:137
struct tcp_connection tcp_connections[MAX_TCP_CONNECTIONS]
Definition: net.h:146

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13