/[gxemul]/trunk/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 /trunk/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 12 by dpavlin, Mon Oct 8 16:18:38 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.80 2005/08/12 05:49:46 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          /*  TODO: Remember the mac addresses somewhere?  */          /*  TODO: Remember the mac addresses somewhere?  */
176          machine->nr_of_nics ++;          machine->nr_of_nics ++;
# Line 1223  static void net_ip_broadcast_dhcp(struct Line 1220  static void net_ip_broadcast_dhcp(struct
1220          /*  This is a Reply:  */          /*  This is a Reply:  */
1221          lp->data[42] = 0x02;          lp->data[42] = 0x02;
1222    
1223          sprintf(lp->data + 70+16+64, "gxemul");          snprintf(lp->data + 70+16+64, 8, "gxemul");
1224    
1225          /*  Recalculate IP header checksum:  */          /*  Recalculate IP header checksum:  */
1226          net_ip_checksum(lp->data + 14, 10, 20);          net_ip_checksum(lp->data + 14, 10, 20);
# Line 1482  static void net_arp(struct net *net, voi Line 1479  static void net_arp(struct net *net, voi
1479                           *  generated from the MAC address. :-)                           *  generated from the MAC address. :-)
1480                           *                           *
1481                           *  packet+8 points to the client's mac address,                           *  packet+8 points to the client's mac address,
1482                           *  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.
1483                           *  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.  
1484                           */                           */
1485                          q = (((packet[8 + 3]) >> 4) - 1);                          /*  q = (packet[8 + 3]) >> 4;  */
1486                          q = q*15 + (((packet[8 + 4]) >> 4) - 1);                          /*  q = q*15 + ((packet[8 + 4]) >> 4);  */
1487                          q = q*15 + (((packet[8 + 5]) >> 4) - 1);                          q = (packet[8 + 5]) >> 4;
1488                          lp->data[24 + 14] = 10;                          lp->data[24 + 14] = 10;
1489                          lp->data[25 + 14] =  q / 225;   q /= 15;                          lp->data[25 + 14] =  0;
1490                          lp->data[26 + 14] =  q / 15;    q /= 15;                          lp->data[26 + 14] =  0;
1491                          lp->data[27 + 14] =  q + 1;                          lp->data[27 + 14] =  q;
   
1492                          break;                          break;
1493                  case 2:         /*  Reply  */                  case 2:         /*  Reply  */
1494                  case 4:         /*  Reverse Reply  */                  case 4:         /*  Reverse Reply  */
# Line 1531  int net_ethernet_rx_avail(struct net *ne Line 1526  int net_ethernet_rx_avail(struct net *ne
1526                  return 0;                  return 0;
1527    
1528          /*          /*
1529             *  If the network is distributed across multiple emulator processes,
1530             *  then receive incoming packets from those processes.
1531             */
1532            if (net->local_port != 0) {
1533                    struct sockaddr_in si;
1534                    socklen_t si_len = sizeof(si);
1535                    int res, i;
1536                    unsigned char buf[60000];
1537    
1538                    if ((res = recvfrom(net->local_port_socket, buf, sizeof(buf), 0,
1539                        (struct sockaddr *)&si, &si_len)) != -1) {
1540                            /*  fatal("DISTRIBUTED packet, %i bytes from %s:%d\n",
1541                                res, inet_ntoa(si.sin_addr), ntohs(si.sin_port)); */
1542                            for (i=0; i<net->n_nics; i++) {
1543                                    struct ethernet_packet_link *lp;
1544                                    lp = net_allocate_packet_link(net,
1545                                        net->nic_extra[i], res);
1546                                    memcpy(lp->data, buf, res);
1547                            }
1548                    }
1549            }
1550    
1551            /*
1552           *  UDP:           *  UDP:
1553           */           */
1554          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 1930  int net_ethernet_rx(struct net *net, voi
1930    
1931    
1932  /*  /*
1933     *  send_udp():
1934     *
1935     *  Send a simple UDP packet to some other (real) host. Used for distributed
1936     *  network simulations.
1937     */
1938    void send_udp(struct in_addr *addrp, int portnr, unsigned char *packet,
1939            size_t len)
1940    {
1941            int s;
1942            struct sockaddr_in si;
1943    
1944            s = socket(AF_INET, SOCK_DGRAM, 0);
1945            if (s < 0) {
1946                    perror("send_udp(): socket");
1947                    return;
1948            }
1949    
1950            /*  fatal("send_udp(): sending to port %i\n", portnr);  */
1951    
1952            si.sin_family = AF_INET;
1953            si.sin_addr = *addrp;
1954            si.sin_port = htons(portnr);
1955    
1956            if (sendto(s, packet, len, 0, (struct sockaddr *)&si,
1957                sizeof(si)) != len) {
1958                    perror("send_udp(): sendto");
1959            }
1960    
1961            close(s);
1962    }
1963    
1964    
1965    /*
1966   *  net_ethernet_tx():   *  net_ethernet_tx():
1967   *   *
1968   *  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 1981  void net_ethernet_tx(struct net *net, vo
1981          if (len < 20)          if (len < 20)
1982                  return;                  return;
1983    
1984          /*  Copy this packet to all other NICs on this network:  */          /*
1985             *  Copy this packet to all other NICs on this network:
1986             */
1987          if (extra != NULL && net->n_nics > 0) {          if (extra != NULL && net->n_nics > 0) {
1988                  for (i=0; i<net->n_nics; i++)                  for (i=0; i<net->n_nics; i++)
1989                          if (extra != net->nic_extra[i]) {                          if (extra != net->nic_extra[i]) {
# Line 1943  void net_ethernet_tx(struct net *net, vo Line 1996  void net_ethernet_tx(struct net *net, vo
1996                          }                          }
1997          }          }
1998    
1999            /*
2000             *  If this network is distributed across multiple emulator processes,
2001             *  then transmit the packet to those other processes.
2002             */
2003            if (net->remote_nets != NULL) {
2004                    struct remote_net *rnp = net->remote_nets;
2005                    while (rnp != NULL) {
2006                            send_udp(&rnp->ipv4_addr, rnp->portnr, packet, len);
2007                            rnp = rnp->next;
2008                    }
2009            }
2010    
2011          /*  Drop packets that are not destined for the gateway:  */          /*  Drop packets that are not destined for the gateway:  */
2012          if (memcmp(packet, net->gateway_ethernet_addr, 6) != 0          if (memcmp(packet, net->gateway_ethernet_addr, 6) != 0
2013              && packet[0] != 0xff && packet[0] != 0x00)              && packet[0] != 0xff && packet[0] != 0x00)
2014                  return;                  return;
2015    
2016            /*
2017             *  The code below simulates the behaviour of a "NAT"-style
2018             *  gateway.
2019             */
2020  #if 0  #if 0
2021          fatal("[ net: ethernet: ");          fatal("[ net: ethernet: ");
2022          for (i=0; i<6; i++)          for (i=0; i<6; i++)     fatal("%02x", packet[i]); fatal(" ");
2023                  fatal("%02x", packet[i]);          for (i=6; i<12; i++)    fatal("%02x", packet[i]); fatal(" ");
2024          fatal(" ");          for (i=12; i<14; i++)   fatal("%02x", packet[i]); fatal(" ");
2025          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");  
2026  #endif  #endif
2027    
2028          /*  Sprite:  */          /*  Sprite:  */
# Line 2191  static void net_gateway_init(struct net Line 2252  static void net_gateway_init(struct net
2252  void net_dumpinfo(struct net *net)  void net_dumpinfo(struct net *net)
2253  {  {
2254          int iadd = 4;          int iadd = 4;
2255            struct remote_net *rnp;
2256    
2257          debug("net: ");          debug("net: simulating ");
2258    
2259          net_debugaddr(&net->netmask_ipv4, ADDR_IPV4);          net_debugaddr(&net->netmask_ipv4, ADDR_IPV4);
2260          debug("/%i", net->netmask_ipv4_len);          debug("/%i", net->netmask_ipv4_len);
# Line 2202  void net_dumpinfo(struct net *net) Line 2264  void net_dumpinfo(struct net *net)
2264    
2265          debug_indentation(iadd);          debug_indentation(iadd);
2266    
2267          debug("gateway: ");          debug("simulated gateway: ");
2268          net_debugaddr(&net->gateway_ipv4_addr, ADDR_IPV4);          net_debugaddr(&net->gateway_ipv4_addr, ADDR_IPV4);
2269          debug(" (");          debug(" (");
2270          net_debugaddr(&net->gateway_ethernet_addr, ADDR_ETHERNET);          net_debugaddr(&net->gateway_ethernet_addr, ADDR_ETHERNET);
2271          debug(")\n");          debug(")\n");
2272    
2273          debug_indentation(iadd);          debug_indentation(iadd);
         if (net->domain_name != NULL && net->domain_name[0])  
                 debug("domain \"%s\", ", net->domain_name);  
2274          if (!net->nameserver_known) {          if (!net->nameserver_known) {
2275                  debug("(could not determine nameserver)");                  debug("(could not determine nameserver)");
2276          } else {          } else {
2277                  debug("nameserver ");                  debug("using nameserver ");
2278                  net_debugaddr(&net->nameserver_ipv4, ADDR_IPV4);                  net_debugaddr(&net->nameserver_ipv4, ADDR_IPV4);
2279          }          }
2280            if (net->domain_name != NULL && net->domain_name[0])
2281                    debug(", domain \"%s\"", net->domain_name);
2282          debug("\n");          debug("\n");
2283          debug_indentation(-iadd);          debug_indentation(-iadd);
2284    
2285            rnp = net->remote_nets;
2286            if (net->local_port != 0)
2287                    debug("distributed network: local port = %i\n",
2288                        net->local_port);
2289            debug_indentation(iadd);
2290            while (rnp != NULL) {
2291                    debug("remote \"%s\": ", rnp->name);
2292                    net_debugaddr(&rnp->ipv4_addr, ADDR_IPV4);
2293                    debug(" port %i\n", rnp->portnr);
2294                    rnp = rnp->next;
2295            }
2296            debug_indentation(-iadd);
2297    
2298          debug_indentation(-iadd);          debug_indentation(-iadd);
2299  }  }
2300    
# Line 2228  void net_dumpinfo(struct net *net) Line 2303  void net_dumpinfo(struct net *net)
2303   *  net_init():   *  net_init():
2304   *   *
2305   *  This function creates a network, and returns a pointer to it.   *  This function creates a network, and returns a pointer to it.
2306   *  Example: ipv4addr should be something like "10.0.0.0", netipv4len = 8.   *  ipv4addr should be something like "10.0.0.0", netipv4len = 8.
2307     *  If n_remote is more than zero, remote should be a pointer to an array
2308     *  of strings of the following format: "host:portnr".
2309   *   *
2310   *  (On failure, exit() is called.)   *  On failure, exit() is called.
2311   */   */
2312  struct net *net_init(struct emul *emul, int init_flags,  struct net *net_init(struct emul *emul, int init_flags,
2313          char *ipv4addr, int netipv4len)          char *ipv4addr, int netipv4len, char **remote, int n_remote,
2314            int local_port)
2315  {  {
2316          struct net *net;          struct net *net;
2317          int res;          int res;
# Line 2275  struct net *net_init(struct emul *emul, Line 2353  struct net *net_init(struct emul *emul,
2353          net->domain_name = "";          net->domain_name = "";
2354          parse_resolvconf(net);          parse_resolvconf(net);
2355    
2356            /*  Distributed network? Then add remote hosts:  */
2357            if (local_port != 0) {
2358                    struct sockaddr_in si_self;
2359    
2360                    net->local_port = local_port;
2361                    net->local_port_socket = socket(AF_INET, SOCK_DGRAM, 0);
2362                    if (net->local_port_socket < 0) {
2363                            perror("socket");
2364                            exit(1);
2365                    }
2366    
2367                    memset((char *)&si_self, sizeof(si_self), 0);
2368                    si_self.sin_family = AF_INET;
2369                    si_self.sin_port = htons(local_port);
2370                    si_self.sin_addr.s_addr = htonl(INADDR_ANY);
2371                    if (bind(net->local_port_socket, (struct sockaddr *)&si_self,
2372                        sizeof(si_self)) < 0) {
2373                            perror("bind");
2374                            exit(1);
2375                    }
2376    
2377                    /*  Set the socket to non-blocking:  */
2378                    res = fcntl(net->local_port_socket, F_GETFL);
2379                    fcntl(net->local_port_socket, F_SETFL, res | O_NONBLOCK);
2380            }
2381            if (n_remote != 0) {
2382                    struct remote_net *rnp;
2383                    while ((n_remote--) != 0) {
2384                            struct hostent *hp;
2385    
2386                            /*  debug("adding '%s'\n", remote[n_remote]);  */
2387                            rnp = malloc(sizeof(struct remote_net));
2388                            memset(rnp, 0, sizeof(struct remote_net));
2389    
2390                            rnp->next = net->remote_nets;
2391                            net->remote_nets = rnp;
2392    
2393                            rnp->name = strdup(remote[n_remote]);
2394                            if (strchr(rnp->name, ':') != NULL)
2395                                    strchr(rnp->name, ':')[0] = '\0';
2396    
2397                            hp = gethostbyname(rnp->name);
2398                            if (hp == NULL) {
2399                                    fprintf(stderr, "could not resolve '%s'\n",
2400                                        rnp->name);
2401                                    exit(1);
2402                            }
2403                            memcpy(&rnp->ipv4_addr, hp->h_addr, hp->h_length);
2404                            free(rnp->name);
2405    
2406                            /*  And again:  */
2407                            rnp->name = strdup(remote[n_remote]);
2408                            if (strchr(rnp->name, ':') == NULL) {
2409                                    fprintf(stderr, "Remote network '%s' is not "
2410                                        "'host:portnr'?\n", rnp->name);
2411                                    exit(1);
2412                            }
2413                            rnp->portnr = atoi(strchr(rnp->name, ':') + 1);
2414                    }
2415            }
2416    
2417          if (init_flags & NET_INIT_FLAG_GATEWAY)          if (init_flags & NET_INIT_FLAG_GATEWAY)
2418                  net_gateway_init(net);                  net_gateway_init(net);
2419    

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

  ViewVC Help
Powered by ViewVC 1.1.26