net.cc Source File

Back to the index.

net.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2009 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  * Emulated network.
29  *
30  * (Read the README file in this directory for more details.)
31  *
32  *
33  * NOTE: The 'extra' argument used in many functions in this file is a pointer
34  * to something unique for each NIC (i.e. the NIC itself :-), so that if
35  * multiple NICs are emulated concurrently, they will not get packets that
36  * are meant for some other controller.
37  */
38 
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <errno.h>
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <netdb.h>
49 #include <fcntl.h>
50 #include <signal.h>
51 
52 #include "machine.h"
53 #include "misc.h"
54 #include "net.h"
55 
56 
57 /* #define debug fatal */
58 
59 
60 /*
61  * net_allocate_ethernet_packet_link():
62  *
63  * This routine allocates an ethernet_packet_link struct, and adds it at
64  * the end of the packet chain. A data buffer is allocated, and the data,
65  * extra, and len fields of the link are set.
66  *
67  * Note: The data buffer is not zeroed.
68  *
69  * Return value is a pointer to the link on success. It doesn't return on
70  * failure.
71  */
73  struct net *net, void *extra, size_t len)
74 {
75  struct ethernet_packet_link *lp;
76 
78  malloc(sizeof(struct ethernet_packet_link)));
79 
80  lp->len = len;
81  lp->extra = extra;
82  CHECK_ALLOCATION(lp->data = (unsigned char *) malloc(len));
83 
84  lp->next = NULL;
85 
86  /* Add last in the link chain: */
88  if (lp->prev != NULL)
89  lp->prev->next = lp;
90  else
93 
94  return lp;
95 }
96 
97 
98 /*
99  * net_arp():
100  *
101  * Handle an ARP (or RARP) packet, coming from the emulated NIC.
102  *
103  * An ARP packet might look like this:
104  *
105  * ARP header:
106  * ARP hardware addr family: 0001
107  * ARP protocol addr family: 0800
108  * ARP addr lengths: 06 04
109  * ARP request: 0001
110  * ARP from: 112233445566 01020304
111  * ARP to: 000000000000 01020301
112  *
113  * An ARP request with a 'to' IP value of the gateway should cause an
114  * ARP response packet to be created.
115  *
116  * An ARP request with the same from and to IP addresses should be ignored.
117  * (This would be a host testing to see if there is an IP collision.)
118  */
119 static void net_arp(struct net *net, void *extra,
120  unsigned char *packet, int len, int reverse)
121 {
122  int q;
123  int i;
124 
125  /* TODO: This debug dump assumes ethernet->IPv4 translation: */
126  if (reverse)
127  debug("[ net: RARP: ");
128  else
129  debug("[ net: ARP: ");
130  for (i=0; i<2; i++)
131  debug("%02x", packet[i]);
132  debug(" ");
133  for (i=2; i<4; i++)
134  debug("%02x", packet[i]);
135  debug(" ");
136  debug("%02x", packet[4]);
137  debug(" ");
138  debug("%02x", packet[5]);
139  debug(" req=");
140  debug("%02x", packet[6]); /* Request type */
141  debug("%02x", packet[7]);
142  debug(" from=");
143  for (i=8; i<18; i++)
144  debug("%02x", packet[i]);
145  debug(" to=");
146  for (i=18; i<28; i++)
147  debug("%02x", packet[i]);
148  debug(" ]\n");
149 
150  if (packet[0] == 0x00 && packet[1] == 0x01 &&
151  packet[2] == 0x08 && packet[3] == 0x00 &&
152  packet[4] == 0x06 && packet[5] == 0x04) {
153  int r = (packet[6] << 8) + packet[7];
154  struct ethernet_packet_link *lp;
155 
156  switch (r) {
157  case 1: /* Request */
158  /* Only create a reply if this was meant for the
159  gateway: */
160  if (memcmp(packet+24, net->gateway_ipv4_addr, 4) != 0)
161  break;
162 
164  net, extra, 60 + 14);
165 
166  /* Copy the old packet first: */
167  memset(lp->data, 0, 60 + 14);
168  memcpy(lp->data + 14, packet, len);
169 
170  /* Add ethernet ARP header: */
171  memcpy(lp->data + 0, lp->data + 8 + 14, 6);
172  memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
173  lp->data[12] = 0x08; lp->data[13] = 0x06;
174 
175  /* Address of the emulated machine: */
176  memcpy(lp->data + 18 + 14, lp->data + 8 + 14, 10);
177 
178  /* Address of the gateway: */
179  memcpy(lp->data + 8 + 14, net->gateway_ethernet_addr,
180  6);
181  memcpy(lp->data + 14 + 14, net->gateway_ipv4_addr, 4);
182 
183  /* This is a Reply: */
184  lp->data[6 + 14] = 0x00; lp->data[7 + 14] = 0x02;
185 
186  break;
187  case 3: /* Reverse Request */
189  net, extra, 60 + 14);
190 
191  /* Copy the old packet first: */
192  memset(lp->data, 0, 60 + 14);
193  memcpy(lp->data + 14, packet, len);
194 
195  /* Add ethernet RARP header: */
196  memcpy(lp->data + 0, packet + 8, 6);
197  memcpy(lp->data + 6, net->gateway_ethernet_addr, 6);
198  lp->data[12] = 0x80; lp->data[13] = 0x35;
199 
200  /* This is a RARP reply: */
201  lp->data[6 + 14] = 0x00; lp->data[7 + 14] = 0x04;
202 
203  /* Address of the gateway: */
204  memcpy(lp->data + 8 + 14, net->gateway_ethernet_addr,
205  6);
206  memcpy(lp->data + 14 + 14, net->gateway_ipv4_addr, 4);
207 
208  /* MAC address of emulated machine: */
209  memcpy(lp->data + 18 + 14, packet + 8, 6);
210 
211  /*
212  * IP address of the emulated machine: Automagically
213  * generated from the MAC address. :-)
214  *
215  * packet+8 points to the client's mac address,
216  * for example 10:20:30:00:00:z0, where z is 0..15.
217  * 10:20:30:00:00:10 results in 10.0.0.1.
218  */
219  /* q = (packet[8 + 3]) >> 4; */
220  /* q = q*15 + ((packet[8 + 4]) >> 4); */
221  q = (packet[8 + 5]) >> 4;
222  lp->data[24 + 14] = 10;
223  lp->data[25 + 14] = 0;
224  lp->data[26 + 14] = 0;
225  lp->data[27 + 14] = q;
226  break;
227  case 2: /* Reply */
228  case 4: /* Reverse Reply */
229  default:
230  fatal("[ net: ARP: UNIMPLEMENTED request type "
231  "0x%04x ]\n", r);
232  }
233  } else {
234  fatal("[ net: ARP: UNIMPLEMENTED arp packet type: ");
235  for (i=0; i<len; i++)
236  fatal("%02x", packet[i]);
237  fatal(" ]\n");
238  }
239 }
240 
241 
242 /*
243  * net_ethernet_rx_avail():
244  *
245  * Return 1 if there is a packet available for this 'extra' pointer, otherwise
246  * return 0.
247  *
248  * Appart from actually checking for incoming packets from the outside world,
249  * this function basically works like net_ethernet_rx() but it only receives
250  * a return value telling us whether there is a packet or not, we don't
251  * actually get the packet.
252  */
253 int net_ethernet_rx_avail(struct net *net, void *extra)
254 {
255  if (net == NULL)
256  return 0;
257 
258  /*
259  * If the network is distributed across multiple emulator processes,
260  * then receive incoming packets from those processes.
261  */
262  if (net->local_port != 0) {
263  struct sockaddr_in si;
264  socklen_t si_len = sizeof(si);
265  int res, i, nreceived = 0;
266  unsigned char buf[60000];
267 
268  do {
269  res = recvfrom(net->local_port_socket, buf,
270  sizeof(buf), 0, (struct sockaddr *)&si, &si_len);
271 
272  if (res != -1) {
273  nreceived ++;
274 
275  /* fatal("[ incoming DISTRIBUTED packet, %i "
276  "bytes from %s:%d\n", res,
277  inet_ntoa(si.sin_addr),
278  ntohs(si.sin_port)); */
279 
280  /* Add the packet to all "our" NICs on this
281  network: */
282  for (i=0; i<net->n_nics; i++) {
283  struct ethernet_packet_link *lp;
285  net, net->nic_extra[i], res);
286  memcpy(lp->data, buf, res);
287  }
288  }
289  } while (res != -1 && nreceived < 100);
290  }
291 
292  /* IP protocol specific: */
295 
296  return net_ethernet_rx(net, extra, NULL, NULL);
297 }
298 
299 
300 /*
301  * net_ethernet_rx():
302  *
303  * Receive an ethernet packet. (This means handing over an already prepared
304  * packet from this module to a specific ethernet controller device.)
305  *
306  * Return value is 1 if there was a packet available. *packetp and *lenp
307  * will be set to the packet's data pointer and length, respectively, and
308  * the packet will be removed from the linked list). If there was no packet
309  * available, 0 is returned.
310  *
311  * If packetp is NULL, then the search is aborted as soon as a packet with
312  * the correct 'extra' field is found, and a 1 is returned, but as packetp
313  * is NULL we can't return the actual packet. (This is the internal form
314  * if net_ethernet_rx_avail().)
315  */
316 int net_ethernet_rx(struct net *net, void *extra,
317  unsigned char **packetp, int *lenp)
318 {
319  struct ethernet_packet_link *lp, *prev;
320 
321  if (net == NULL)
322  return 0;
323 
324  /* Find the first packet which has the right 'extra' field. */
325 
327  prev = NULL;
328  while (lp != NULL) {
329  if (lp->extra == extra) {
330  /* We found a packet for this controller! */
331  if (packetp == NULL || lenp == NULL)
332  return 1;
333 
334  /* Let's return it: */
335  (*packetp) = lp->data;
336  (*lenp) = lp->len;
337 
338  /* Remove this link from the linked list: */
339  if (prev == NULL)
341  else
342  prev->next = lp->next;
343 
344  if (lp->next == NULL)
346  else
347  lp->next->prev = prev;
348 
349  free(lp);
350 
351  /* ... and return successfully: */
352  return 1;
353  }
354 
355  prev = lp;
356  lp = lp->next;
357  }
358 
359  /* No packet found. :-( */
360  return 0;
361 }
362 
363 
364 /*
365  * net_ethernet_tx():
366  *
367  * Transmit an ethernet packet, as seen from the emulated ethernet controller.
368  * If the packet can be handled here, it will not necessarily be transmitted
369  * to the outside world.
370  */
371 void net_ethernet_tx(struct net *net, void *extra,
372  unsigned char *packet, int len)
373 {
374  int i, eth_type, for_the_gateway;
375 
376  if (net == NULL)
377  return;
378 
379  for_the_gateway = !memcmp(packet, net->gateway_ethernet_addr, 6);
380 
381  /* Drop too small packets: */
382  if (len < 20) {
383  fatal("[ net_ethernet_tx: Warning: dropping tiny packet "
384  "(%i bytes) ]\n", len);
385  return;
386  }
387 
388  /*
389  * Copy this packet to all other NICs on this network (except if
390  * it is aimed specifically at the gateway's ethernet address):
391  */
392  if (!for_the_gateway && extra != NULL && net->n_nics > 0) {
393  for (i=0; i<net->n_nics; i++)
394  if (extra != net->nic_extra[i]) {
395  struct ethernet_packet_link *lp;
397  net->nic_extra[i], len);
398 
399  /* Copy the entire packet: */
400  memcpy(lp->data, packet, len);
401  }
402  }
403 
404  /*
405  * If this network is distributed across multiple emulator processes,
406  * then transmit the packet to those other processes.
407  */
408  if (!for_the_gateway && net->remote_nets != NULL) {
409  struct remote_net *rnp = net->remote_nets;
410  while (rnp != NULL) {
411  send_udp(&rnp->ipv4_addr, rnp->portnr, packet, len);
412  rnp = rnp->next;
413  }
414  }
415 
416 
417  /*
418  * The code below simulates the behaviour of a "NAT"-style gateway.
419  *
420  * Packets that are not destined for the gateway are dropped first:
421  * (DHCP packets are let through, though.)
422  */
423 
424  if (!for_the_gateway && packet[0] != 0xff && packet[0] != 0x00)
425  return;
426 
427 #if 0
428  fatal("[ net: ethernet: ");
429  for (i=0; i<6; i++) fatal("%02x", packet[i]); fatal(" ");
430  for (i=6; i<12; i++) fatal("%02x", packet[i]); fatal(" ");
431  for (i=12; i<14; i++) fatal("%02x", packet[i]); fatal(" ");
432  for (i=14; i<len; i++) fatal("%02x", packet[i]); fatal(" ]\n");
433 #endif
434 
435  eth_type = (packet[12] << 8) + packet[13];
436 
437  /* IP: */
438  if (eth_type == ETHERTYPE_IP) {
439  /* Routed via the gateway? */
440  if (for_the_gateway) {
441  net_ip(net, extra, packet, len);
442  return;
443  }
444 
445  /* Broadcast? (DHCP does this.) */
446  if (packet[0] == 0xff && packet[1] == 0xff &&
447  packet[2] == 0xff && packet[3] == 0xff &&
448  packet[4] == 0xff && packet[5] == 0xff) {
449  net_ip_broadcast(net, extra, packet, len);
450  return;
451  }
452 
453  if (net->n_nics < 2) {
454  fatal("[ net_ethernet_tx: IP packet not for gateway, "
455  "and not broadcast: ");
456  for (i=0; i<14; i++)
457  fatal("%02x", packet[i]);
458  fatal(" ]\n");
459  }
460  return;
461  }
462 
463  /* ARP: */
464  if (eth_type == ETHERTYPE_ARP) {
465  if (len != 42 && len != 60)
466  fatal("[ net_ethernet_tx: WARNING! unusual "
467  "ARP len (%i) ]\n", len);
468  net_arp(net, extra, packet + 14, len - 14, 0);
469  return;
470  }
471 
472  /* RARP: */
473  if (eth_type == ETHERTYPE_REVARP) {
474  net_arp(net, extra, packet + 14, len - 14, 1);
475  return;
476  }
477 
478  /* Sprite: */
479  if (eth_type == ETHERTYPE_SPRITE) {
480  /* TODO. */
481  fatal("[ net: TX: UNIMPLEMENTED Sprite packet ]\n");
482  return;
483  }
484 
485  /* IPv6: */
486  if (eth_type == ETHERTYPE_IPV6) {
487  /* TODO. */
488  fatal("[ net_ethernet_tx: IPv6 is not implemented yet! ]\n");
489  return;
490  }
491 
492  fatal("[ net_ethernet_tx: ethernet packet type 0x%04x not yet "
493  "implemented ]\n", eth_type);
494 }
495 
496 
497 /*
498  * parse_resolvconf():
499  *
500  * This function parses "/etc/resolv.conf" to figure out the nameserver
501  * and domain used by the host.
502  */
503 static void parse_resolvconf(struct net *net)
504 {
505  FILE *f;
506  char buf[8000];
507  size_t len;
508  int res;
509  unsigned int i, start;
510 
511  /*
512  * This is a very ugly hack, which tries to figure out which
513  * nameserver the host uses by looking for the string 'nameserver'
514  * in /etc/resolv.conf.
515  *
516  * This can later on be used for DHCP autoconfiguration. (TODO)
517  *
518  * TODO: This is hardcoded to use /etc/resolv.conf. Not all
519  * operating systems use that filename.
520  *
521  * TODO: This is hardcoded for AF_INET (that is, IPv4).
522  *
523  * TODO: This assumes that the first nameserver listed is the
524  * one to use.
525  */
526  f = fopen("/etc/resolv.conf", "r");
527  if (f == NULL)
528  return;
529 
530  /* TODO: get rid of the hardcoded values */
531  memset(buf, 0, sizeof(buf));
532  len = fread(buf, 1, sizeof(buf) - 100, f);
533  fclose(f);
534  buf[sizeof(buf) - 1] = '\0';
535 
536  for (i=0; i<len; i++)
537  if (strncmp(buf+i, "nameserver", 10) == 0) {
538  char *p;
539 
540  /*
541  * "nameserver" (1 or more whitespace)
542  * "x.y.z.w" (non-digit)
543  */
544 
545  /* debug("found nameserver at offset %i\n", i); */
546  i += 10;
547  while (i<len && (buf[i]==' ' || buf[i]=='\t'))
548  i++;
549  if (i >= len)
550  break;
551  start = i;
552 
553  p = buf+start;
554  while ((*p >= '0' && *p <= '9') || *p == '.')
555  p++;
556  *p = '\0';
557 
558 #ifdef HAVE_INET_PTON
559  res = inet_pton(AF_INET, buf + start,
560  &net->nameserver_ipv4);
561 #else
562  res = inet_aton(buf + start, &net->nameserver_ipv4);
563 #endif
564  if (res < 1)
565  break;
566 
567  net->nameserver_known = 1;
568  break;
569  }
570 
571  for (i=0; i<len; i++)
572  if (strncmp(buf+i, "domain", 6) == 0) {
573  /* "domain" (1 or more whitespace) domain_name */
574  i += 6;
575  while (i<len && (buf[i]==' ' || buf[i]=='\t'))
576  i++;
577  if (i >= len)
578  break;
579 
580  start = i;
581  while (i<len && buf[i]!='\n' && buf[i]!='\r')
582  i++;
583  if (i < len)
584  buf[i] = '\0';
585  /* fatal("DOMAIN='%s'\n", buf + start); */
586  CHECK_ALLOCATION(net->domain_name = strdup(buf+start));
587  break;
588  }
589 }
590 
591 
592 /*
593  * net_add_nic():
594  *
595  * Add a NIC to a network. (All NICs on a network will see each other's
596  * packets.)
597  */
598 void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
599 {
600  if (net == NULL)
601  return;
602 
603  if (extra == NULL) {
604  fprintf(stderr, "net_add_nic(): extra = NULL\n");
605  exit(1);
606  }
607 
608  net->n_nics ++;
609  CHECK_ALLOCATION(net->nic_extra = (void **)
610  realloc(net->nic_extra, sizeof(void *) * net->n_nics));
611 
612  net->nic_extra[net->n_nics - 1] = extra;
613 }
614 
615 
616 /*
617  * net_gateway_init():
618  *
619  * This function creates a "gateway" machine (for example at IPv4 address
620  * 10.0.0.254, if the net is 10.0.0.0/8), which acts as a gateway/router/
621  * nameserver etc.
622  */
623 static void net_gateway_init(struct net *net)
624 {
625  unsigned char *p = (unsigned char *) &net->netmask_ipv4;
626  uint32_t x;
627  int xl;
628 
629  x = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
630  xl = 32 - net->netmask_ipv4_len;
631  if (xl > 8)
632  xl = 8;
633  x |= ((1 << xl) - 1) & ~1;
634 
635  net->gateway_ipv4_addr[0] = x >> 24;
636  net->gateway_ipv4_addr[1] = x >> 16;
637  net->gateway_ipv4_addr[2] = x >> 8;
638  net->gateway_ipv4_addr[3] = x;
639 
640  net->gateway_ethernet_addr[0] = 0x60;
641  net->gateway_ethernet_addr[1] = 0x50;
642  net->gateway_ethernet_addr[2] = 0x40;
643  net->gateway_ethernet_addr[3] = 0x30;
644  net->gateway_ethernet_addr[4] = 0x20;
645  net->gateway_ethernet_addr[5] = 0x10;
646 }
647 
648 
649 /*
650  * net_dumpinfo():
651  *
652  * Called from the debugger's "machine" command, to print some info about
653  * a network.
654  */
655 void net_dumpinfo(struct net *net)
656 {
657  int iadd = DEBUG_INDENTATION;
658  struct remote_net *rnp;
659 
660  debug("net:\n");
661 
662  debug_indentation(iadd);
663 
664  debug("simulated network: ");
666  debug("/%i", net->netmask_ipv4_len);
667 
668  debug(" (max outgoing: TCP=%i, UDP=%i)\n",
670 
671  debug("simulated gateway+nameserver: ");
673  debug(" (");
675  debug(")\n");
676 
677  if (!net->nameserver_known) {
678  debug("(could not determine nameserver)\n");
679  } else {
680  debug("simulated nameserver uses real nameserver ");
682  debug("\n");
683  }
684 
685  if (net->domain_name != NULL && net->domain_name[0])
686  debug("domain: %s\n", net->domain_name);
687 
688  rnp = net->remote_nets;
689  if (net->local_port != 0)
690  debug("distributed network: local port = %i\n",
691  net->local_port);
692  debug_indentation(iadd);
693  while (rnp != NULL) {
694  debug("remote \"%s\": ", rnp->name);
696  debug(" port %i\n", rnp->portnr);
697  rnp = rnp->next;
698  }
699  debug_indentation(-iadd);
700 
701  debug_indentation(-iadd);
702 }
703 
704 
705 /*
706  * net_init():
707  *
708  * This function creates a network, and returns a pointer to it.
709  *
710  * ipv4addr should be something like "10.0.0.0", netipv4len = 8.
711  *
712  * If n_remote is more than zero, remote should be a pointer to an array
713  * of strings of the following format: "host:portnr".
714  *
715  * Network settings are registered if settings_prefix is non-NULL.
716  * (The one calling net_init() is also responsible for calling net_deinit().)
717  *
718  * On failure, exit() is called.
719  */
720 struct net *net_init(struct emul *emul, int init_flags,
721  const char *ipv4addr, int netipv4len,
722  char **remote, int n_remote, int local_port,
723  const char *settings_prefix)
724 {
725  struct net *net;
726  int res;
727 
728  CHECK_ALLOCATION(net = (struct net *) malloc(sizeof(struct net)));
729  memset(net, 0, sizeof(struct net));
730 
731  /* Set the back pointer: */
732  net->emul = emul;
733 
734  /* Sane defaults: */
735  net->timestamp = 0;
737 
738 #ifdef HAVE_INET_PTON
739  res = inet_pton(AF_INET, ipv4addr, &net->netmask_ipv4);
740 #else
741  res = inet_aton(ipv4addr, &net->netmask_ipv4);
742 #endif
743  if (res < 1) {
744  fprintf(stderr, "net_init(): could not parse IPv4 address"
745  " '%s'\n", ipv4addr);
746  exit(1);
747  }
748 
749  if (netipv4len < 1 || netipv4len > 30) {
750  fprintf(stderr, "net_init(): extremely weird ipv4 "
751  "network length (%i)\n", netipv4len);
752  exit(1);
753  }
754  net->netmask_ipv4_len = netipv4len;
755 
756  net->nameserver_known = 0;
757  net->domain_name = strdup("");
758  parse_resolvconf(net);
759 
760  /* Distributed network? Then add remote hosts: */
761  if (local_port != 0) {
762  struct sockaddr_in si_self;
763 
764  net->local_port = local_port;
765  net->local_port_socket = socket(AF_INET, SOCK_DGRAM, 0);
766  if (net->local_port_socket < 0) {
767  perror("socket");
768  exit(1);
769  }
770 
771  memset((char *)&si_self, 0, sizeof(si_self));
772  si_self.sin_family = AF_INET;
773  si_self.sin_port = htons(local_port);
774  si_self.sin_addr.s_addr = htonl(INADDR_ANY);
775  if (bind(net->local_port_socket, (struct sockaddr *)&si_self,
776  sizeof(si_self)) < 0) {
777  perror("bind");
778  exit(1);
779  }
780 
781  /* Set the socket to non-blocking: */
782  res = fcntl(net->local_port_socket, F_GETFL);
783  fcntl(net->local_port_socket, F_SETFL, res | O_NONBLOCK);
784  }
785  if (n_remote != 0) {
786  struct remote_net *rnp;
787  while ((n_remote--) != 0) {
788  struct hostent *hp;
789 
790  /* debug("adding '%s'\n", remote[n_remote]); */
791  CHECK_ALLOCATION(rnp = (struct remote_net *)
792  malloc(sizeof(struct remote_net)));
793  memset(rnp, 0, sizeof(struct remote_net));
794 
795  rnp->next = net->remote_nets;
796  net->remote_nets = rnp;
797 
798  CHECK_ALLOCATION(rnp->name = strdup(remote[n_remote]));
799  if (strchr(rnp->name, ':') != NULL)
800  strchr(rnp->name, ':')[0] = '\0';
801 
802  hp = gethostbyname(rnp->name);
803  if (hp == NULL) {
804  fprintf(stderr, "could not resolve '%s'\n",
805  rnp->name);
806  exit(1);
807  }
808  memcpy(&rnp->ipv4_addr, hp->h_addr, hp->h_length);
809  free(rnp->name);
810 
811  /* And again: */
812  CHECK_ALLOCATION(rnp->name = strdup(remote[n_remote]));
813  if (strchr(rnp->name, ':') == NULL) {
814  fprintf(stderr, "Remote network '%s' is not "
815  "'host:portnr'?\n", rnp->name);
816  exit(1);
817  }
818  rnp->portnr = atoi(strchr(rnp->name, ':') + 1);
819  }
820  }
821 
822  if (init_flags & NET_INIT_FLAG_GATEWAY)
823  net_gateway_init(net);
824 
825  net_dumpinfo(net);
826 
827  /* This is necessary when using the real network: */
828  signal(SIGPIPE, SIG_IGN);
829 
830  return net;
831 }
832 
net::n_nics
int n_nics
Definition: net.h:128
net::nameserver_known
int nameserver_known
Definition: net.h:137
remote_net
Definition: net.h:203
f
void f(int s, int func, int only_name)
Definition: generate_arm_r.c:45
MAX_TCP_CONNECTIONS
#define MAX_TCP_CONNECTIONS
Definition: net.h:116
net::nic_extra
void ** nic_extra
Definition: net.h:129
debug
#define debug
Definition: dev_adb.cc:57
net_tcp_rx_avail
void net_tcp_rx_avail(struct net *net, void *extra)
Definition: net_ip.cc:1384
net_allocate_ethernet_packet_link
struct ethernet_packet_link * net_allocate_ethernet_packet_link(struct net *net, void *extra, size_t len)
Definition: net.cc:72
net::nameserver_ipv4
struct in_addr nameserver_ipv4
Definition: net.h:138
NET_ADDR_IPV4
#define NET_ADDR_IPV4
Definition: net.h:218
ETHERTYPE_IPV6
#define ETHERTYPE_IPV6
Definition: net.h:58
ETHERTYPE_SPRITE
#define ETHERTYPE_SPRITE
Definition: net.h:54
net_dumpinfo
void net_dumpinfo(struct net *net)
Definition: net.cc:655
remote_net::next
struct remote_net * next
Definition: net.h:204
net::local_port_socket
int local_port_socket
Definition: net.h:150
send_udp
void send_udp(struct in_addr *addrp, int portnr, unsigned char *packet, size_t len)
Definition: net_misc.cc:125
net::emul
struct emul * emul
Definition: net.h:121
remote_net::portnr
int portnr
Definition: net.h:208
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
net::first_ethernet_packet
struct ethernet_packet_link * first_ethernet_packet
Definition: net.h:142
misc.h
net_udp_rx_avail
void net_udp_rx_avail(struct net *net, void *extra)
Definition: net_ip.cc:1225
net_ip
void net_ip(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net_ip.cc:885
machine.h
net_debugaddr
void net_debugaddr(void *addr, int type)
Definition: net_misc.cc:50
NET_ADDR_ETHERNET
#define NET_ADDR_ETHERNET
Definition: net.h:220
net_init
struct net * net_init(struct emul *emul, int init_flags, const char *ipv4addr, int netipv4len, char **remote, int n_remote, int local_port, const char *settings_prefix)
Definition: net.cc:720
net::local_port
int local_port
Definition: net.h:149
net_ethernet_rx
int net_ethernet_rx(struct net *net, void *extra, unsigned char **packetp, int *lenp)
Definition: net.cc:316
net::netmask_ipv4_len
int netmask_ipv4_len
Definition: net.h:125
NET_INIT_FLAG_GATEWAY
#define NET_INIT_FLAG_GATEWAY
Definition: net.h:188
net_ip_broadcast
void net_ip_broadcast(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net_ip.cc:1133
MAX_UDP_CONNECTIONS
#define MAX_UDP_CONNECTIONS
Definition: net.h:117
net_ethernet_tx
void net_ethernet_tx(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net.cc:371
net_add_nic
void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
Definition: net.cc:598
net::domain_name
char * domain_name
Definition: net.h:136
net::timestamp
int64_t timestamp
Definition: net.h:140
remote_net::name
char * name
Definition: net.h:206
DEBUG_INDENTATION
#define DEBUG_INDENTATION
Definition: misc.h:212
emul
Definition: emul.h:37
net
Definition: net.h:119
net::last_ethernet_packet
struct ethernet_packet_link * last_ethernet_packet
Definition: net.h:143
net::gateway_ipv4_addr
unsigned char gateway_ipv4_addr[4]
Definition: net.h:132
net::gateway_ethernet_addr
unsigned char gateway_ethernet_addr[6]
Definition: net.h:133
ETHERTYPE_IP
#define ETHERTYPE_IP
Definition: net.h:55
net_ethernet_rx_avail
int net_ethernet_rx_avail(struct net *net, void *extra)
Definition: net.cc:253
remote_net::ipv4_addr
struct in_addr ipv4_addr
Definition: net.h:207
net::netmask_ipv4
struct in_addr netmask_ipv4
Definition: net.h:124
net.h
ETHERTYPE_REVARP
#define ETHERTYPE_REVARP
Definition: net.h:57
ETHERTYPE_ARP
#define ETHERTYPE_ARP
Definition: net.h:56
debug_indentation
void debug_indentation(int diff)
Definition: main.cc:120
net::remote_nets
struct remote_net * remote_nets
Definition: net.h:151
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18