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

Diff of /upstream/0.4.0.1/src/net.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2 by dpavlin, Mon Oct 8 16:17:48 2007 UTC revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: net.c,v 1.72 2005/03/14 19:14:05 debug Exp $   *  $Id: net.c,v 1.84 2005/11/25 03:38:00 debug Exp $
29   *   *
30   *  Emulated (ethernet / internet) network support.   *  Emulated (ethernet / internet) network support.
31   *   *
32   *   *
33   *      NOTE:   This is just an ugly hack, and just barely enough to get some   *  NOTE:  This is just an ugly hack, and just barely enough to get some
34   *              Internet networking up and running for the guest OS.   *         Internet networking up and running for the guest OS.
35   *   *
36   *      TODO:   o)  TCP: fin/ack stuff, and connection time-outs and   *  TODO:
37   *                  connection refused (reset on connect?), resend   *      o)  TCP: fin/ack stuff, and connection time-outs and
38   *                  data to the guest OS if no ack has arrived for   *          connection refused (reset on connect?), resend
39   *                  some time (? buffers?)   *          data to the guest OS if no ack has arrived for
40   *                  http://www.tcpipguide.com/free/   *          some time (? buffers?)
41   *                      t_TCPConnectionTermination-2.htm   *              http://www.tcpipguide.com/free/t_TCPConnectionTermination-2.htm
42   *              o)  remove the netbsd-specific options in the tcp header (?)   *      o)  remove the netbsd-specific options in the tcp header (?)
43   *              o)  Outgoing UDP packet fragment support.   *      o)  Outgoing UDP packet fragment support.
44   *              o)  IPv6  (outgoing, incoming, and the nameserver/gateway)   *      o)  IPv6  (outgoing, incoming, and the nameserver/gateway)
45   *              o)  Incoming connections   *      o)  Incoming connections
  *              o)  if multiple NICs are connected to the same network,  
  *                  they should be able to see each other's packets, and  
  *                  they should have different MAC addresses!  
46   *   *
47     *  TODO 2: The following comments are old! Fix this.
48   *   *
49   *  The emulated NIC has a MAC address of (for example) 10:20:30:40:50:60.   *
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   *  From the emulated environment, the only other machine existing on the
52   *  network is a "gateway" or "firewall", which has an address of   *  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   *  60:50:40:30:20:10. This module (net.c) contains the emulation of that
# Line 65  Line 64 
64   *  for some other controller.   *  for some other controller.
65   *   *
66   *   *
67   *      <------------------  a network  ------------------------------>   *      |------------------  a network  --------------------------------|
68   *              ^               ^                               ^   *              ^               ^                               ^
69   *              |               |                               |   *              |               |                               |
70   *          a NIC connected    another NIC                the gateway   *          a NIC connected    another NIC                the gateway
# Line 159  void net_generate_unique_mac(struct mach Line 158  void net_generate_unique_mac(struct mach
158          y = machine->nr_of_nics;          y = machine->nr_of_nics;
159    
160          /*          /*
161           *  TODO: What is a good starting value? Right now, it looks like this:           *  TODO: What is a good starting value? Something like this?
162           *           *
163           *  +-----------+-------------------+-------------+-------------+           *  +-----------+-------------------+-------------+-------------+
164           *  |  16 bits  |  16 bits machine  |  12 bits    |  4 bits of  |           *  |  16 bits  |  16 bits machine  |  12 bits    |  4 bits of  |
165           *  |  fixed    |  serial nr        |  NIC nr(*)  |  zeroes     |           *  |  fixed    |  serial nr        |  NIC nr(*)  |  zeroes     |
166           *  +-----------+-------------------+-------------+-------------+           *  +-----------+-------------------+-------------+-------------+
          *  
          *  (*) = almost  
167           */           */
168          macbuf[0] = 0x10;          macbuf[0] = 0x10;
169          macbuf[1] = 0x20;          macbuf[1] = 0x20;
170          macbuf[2] = x >> 8;          macbuf[2] = 0x30;
171          macbuf[3] = x & 255;          macbuf[3] = 0;
172          macbuf[4] = y / 15;          macbuf[4] = 0;
173          macbuf[5] = (y % 15) * 0x10 + 0x10;          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?  */          /*  TODO: Remember the mac addresses somewhere?  */
181          machine->nr_of_nics ++;          machine->nr_of_nics ++;
# Line 1223  static void net_ip_broadcast_dhcp(struct Line 1225  static void net_ip_broadcast_dhcp(struct
1225          /*  This is a Reply:  */          /*  This is a Reply:  */
1226          lp->data[42] = 0x02;          lp->data[42] = 0x02;
1227    
1228          sprintf(lp->data + 70+16+64, "gxemul");          snprintf(lp->data + 70+16+64, 8, "gxemul");
1229    
1230          /*  Recalculate IP header checksum:  */          /*  Recalculate IP header checksum:  */
1231          net_ip_checksum(lp->data + 14, 10, 20);          net_ip_checksum(lp->data + 14, 10, 20);
# Line 1433  static void net_arp(struct net *net, voi Line 1435  static void net_arp(struct net *net, voi
1435                          if (memcmp(packet+24, net->gateway_ipv4_addr, 4) != 0)                          if (memcmp(packet+24, net->gateway_ipv4_addr, 4) != 0)
1436                                  break;                                  break;
1437    
1438                          lp = net_allocate_packet_link(net, extra, len + 14);                          lp = net_allocate_packet_link(net, extra, 60 + 14);
1439    
1440                          /*  Copy the old packet first:  */                          /*  Copy the old packet first:  */
1441                            memset(lp->data, 0, 60 + 14);
1442                          memcpy(lp->data + 14, packet, len);                          memcpy(lp->data + 14, packet, len);
1443    
1444                          /*  Add ethernet ARP header:  */                          /*  Add ethernet ARP header:  */
# Line 1456  static void net_arp(struct net *net, voi Line 1459  static void net_arp(struct net *net, voi
1459    
1460                          break;                          break;
1461                  case 3:         /*  Reverse Request  */                  case 3:         /*  Reverse Request  */
1462                          lp = net_allocate_packet_link(net, extra, len + 14);                          lp = net_allocate_packet_link(net, extra, 60 + 14);
1463    
1464                          /*  Copy the old packet first:  */                          /*  Copy the old packet first:  */
1465                            memset(lp->data, 0, 60 + 14);
1466                          memcpy(lp->data + 14, packet, len);                          memcpy(lp->data + 14, packet, len);
1467    
1468                          /*  Add ethernet RARP header:  */                          /*  Add ethernet RARP header:  */
# Line 1482  static void net_arp(struct net *net, voi Line 1486  static void net_arp(struct net *net, voi
1486                           *  generated from the MAC address. :-)                           *  generated from the MAC address. :-)
1487                           *                           *
1488                           *  packet+8 points to the client's mac address,                           *  packet+8 points to the client's mac address,
1489                           *  for example 10:20:30:x0:y0:z0, where x,y,z are                           *  for example 10:20:30:00:00:z0, where z is 0..15.
1490                           *  1..15.                           *  10:20:30:00:00:10 results in 10.0.0.1.
                          *  10:20:30:10:10:10 results in 10.0.0.1.  
1491                           */                           */
1492                          q = (((packet[8 + 3]) >> 4) - 1);                          /*  q = (packet[8 + 3]) >> 4;  */
1493                          q = q*15 + (((packet[8 + 4]) >> 4) - 1);                          /*  q = q*15 + ((packet[8 + 4]) >> 4);  */
1494                          q = q*15 + (((packet[8 + 5]) >> 4) - 1);                          q = (packet[8 + 5]) >> 4;
1495                          lp->data[24 + 14] = 10;                          lp->data[24 + 14] = 10;
1496                          lp->data[25 + 14] =  q / 225;   q /= 15;                          lp->data[25 + 14] =  0;
1497                          lp->data[26 + 14] =  q / 15;    q /= 15;                          lp->data[26 + 14] =  0;
1498                          lp->data[27 + 14] =  q + 1;                          lp->data[27 + 14] =  q;
   
1499                          break;                          break;
1500                  case 2:         /*  Reply  */                  case 2:         /*  Reply  */
1501                  case 4:         /*  Reverse Reply  */                  case 4:         /*  Reverse Reply  */
# Line 1531  int net_ethernet_rx_avail(struct net *ne Line 1533  int net_ethernet_rx_avail(struct net *ne
1533                  return 0;                  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:           *  UDP:
1560           */           */
1561          for (con_id=0; con_id<MAX_UDP_CONNECTIONS; con_id++) {          for (con_id=0; con_id<MAX_UDP_CONNECTIONS; con_id++) {
# Line 1912  int net_ethernet_rx(struct net *net, voi Line 1937  int net_ethernet_rx(struct net *net, voi
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():   *  net_ethernet_tx():
1974   *   *
1975   *  Transmit an ethernet packet, as seen from the emulated ethernet controller.   *  Transmit an ethernet packet, as seen from the emulated ethernet controller.
# Line 1930  void net_ethernet_tx(struct net *net, vo Line 1988  void net_ethernet_tx(struct net *net, vo
1988          if (len < 20)          if (len < 20)
1989                  return;                  return;
1990    
1991          /*  Copy this packet to all other NICs on this network:  */          /*
1992             *  Copy this packet to all other NICs on this network:
1993             */
1994          if (extra != NULL && net->n_nics > 0) {          if (extra != NULL && net->n_nics > 0) {
1995                  for (i=0; i<net->n_nics; i++)                  for (i=0; i<net->n_nics; i++)
1996                          if (extra != net->nic_extra[i]) {                          if (extra != net->nic_extra[i]) {
# Line 1943  void net_ethernet_tx(struct net *net, vo Line 2003  void net_ethernet_tx(struct net *net, vo
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:  */          /*  Drop packets that are not destined for the gateway:  */
2019          if (memcmp(packet, net->gateway_ethernet_addr, 6) != 0          if (memcmp(packet, net->gateway_ethernet_addr, 6) != 0
2020              && packet[0] != 0xff && packet[0] != 0x00)              && packet[0] != 0xff && packet[0] != 0x00)
2021                  return;                  return;
2022    
2023            /*
2024             *  The code below simulates the behaviour of a "NAT"-style
2025             *  gateway.
2026             */
2027  #if 0  #if 0
2028          fatal("[ net: ethernet: ");          fatal("[ net: ethernet: ");
2029          for (i=0; i<6; i++)          for (i=0; i<6; i++)     fatal("%02x", packet[i]); fatal(" ");
2030                  fatal("%02x", packet[i]);          for (i=6; i<12; i++)    fatal("%02x", packet[i]); fatal(" ");
2031          fatal(" ");          for (i=12; i<14; i++)   fatal("%02x", packet[i]); fatal(" ");
2032          for (i=6; i<12; i++)          for (i=14; i<len; i++)  fatal("%02x", packet[i]); fatal(" ]\n");
                 fatal("%02x", packet[i]);  
         fatal(" ");  
         for (i=12; i<14; i++)  
                 fatal("%02x", packet[i]);  
         fatal(" ");  
         for (i=14; i<len; i++)  
                 fatal("%02x", packet[i]);  
         fatal(" ]\n");  
2033  #endif  #endif
2034    
2035          /*  Sprite:  */          /*  Sprite:  */
# Line 2001  void net_ethernet_tx(struct net *net, vo Line 2069  void net_ethernet_tx(struct net *net, vo
2069    
2070          /*  ARP:  */          /*  ARP:  */
2071          if (packet[12] == 0x08 && packet[13] == 0x06) {          if (packet[12] == 0x08 && packet[13] == 0x06) {
2072                  if (len != 60)                  if (len != 42 && len != 60)
2073                          fatal("[ net_ethernet_tx: WARNING! unusual "                          fatal("[ net_ethernet_tx: WARNING! unusual "
2074                              "ARP len (%i) ]\n", len);                              "ARP len (%i) ]\n", len);
2075                  net_arp(net, extra, packet + 14, len - 14, 0);                  net_arp(net, extra, packet + 14, len - 14, 0);
# Line 2191  static void net_gateway_init(struct net Line 2259  static void net_gateway_init(struct net
2259  void net_dumpinfo(struct net *net)  void net_dumpinfo(struct net *net)
2260  {  {
2261          int iadd = 4;          int iadd = 4;
2262            struct remote_net *rnp;
2263    
2264          debug("net: ");          debug("net: simulating ");
2265    
2266          net_debugaddr(&net->netmask_ipv4, ADDR_IPV4);          net_debugaddr(&net->netmask_ipv4, ADDR_IPV4);
2267          debug("/%i", net->netmask_ipv4_len);          debug("/%i", net->netmask_ipv4_len);
# Line 2202  void net_dumpinfo(struct net *net) Line 2271  void net_dumpinfo(struct net *net)
2271    
2272          debug_indentation(iadd);          debug_indentation(iadd);
2273    
2274          debug("gateway: ");          debug("simulated gateway: ");
2275          net_debugaddr(&net->gateway_ipv4_addr, ADDR_IPV4);          net_debugaddr(&net->gateway_ipv4_addr, ADDR_IPV4);
2276          debug(" (");          debug(" (");
2277          net_debugaddr(&net->gateway_ethernet_addr, ADDR_ETHERNET);          net_debugaddr(&net->gateway_ethernet_addr, ADDR_ETHERNET);
2278          debug(")\n");          debug(")\n");
2279    
2280          debug_indentation(iadd);          debug_indentation(iadd);
         if (net->domain_name != NULL && net->domain_name[0])  
                 debug("domain \"%s\", ", net->domain_name);  
2281          if (!net->nameserver_known) {          if (!net->nameserver_known) {
2282                  debug("(could not determine nameserver)");                  debug("(could not determine nameserver)");
2283          } else {          } else {
2284                  debug("nameserver ");                  debug("using nameserver ");
2285                  net_debugaddr(&net->nameserver_ipv4, ADDR_IPV4);                  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");          debug("\n");
2290          debug_indentation(-iadd);          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);          debug_indentation(-iadd);
2306  }  }
2307    
# Line 2228  void net_dumpinfo(struct net *net) Line 2310  void net_dumpinfo(struct net *net)
2310   *  net_init():   *  net_init():
2311   *   *
2312   *  This function creates a network, and returns a pointer to it.   *  This function creates a network, and returns a pointer to it.
2313   *  Example: ipv4addr should be something like "10.0.0.0", netipv4len = 8.   *  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.)   *  On failure, exit() is called.
2318   */   */
2319  struct net *net_init(struct emul *emul, int init_flags,  struct net *net_init(struct emul *emul, int init_flags,
2320          char *ipv4addr, int netipv4len)          char *ipv4addr, int netipv4len, char **remote, int n_remote,
2321            int local_port)
2322  {  {
2323          struct net *net;          struct net *net;
2324          int res;          int res;
# Line 2275  struct net *net_init(struct emul *emul, Line 2360  struct net *net_init(struct emul *emul,
2360          net->domain_name = "";          net->domain_name = "";
2361          parse_resolvconf(net);          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)          if (init_flags & NET_INIT_FLAG_GATEWAY)
2425                  net_gateway_init(net);                  net_gateway_init(net);
2426    

Legend:
Removed from v.2  
changed lines
  Added in v.20

  ViewVC Help
Powered by ViewVC 1.1.26