[Gd-chatter] r10825 - in trunk/libraries: layer network-flow packetizer pcap

hannes at gwydiondylan.org hannes at gwydiondylan.org
Sun Jul 16 22:53:37 CEST 2006


Author: hannes
Date: Sun Jul 16 22:53:35 2006
New Revision: 10825

Modified:
   trunk/libraries/layer/layer.dylan
   trunk/libraries/network-flow/network-flow.dylan
   trunk/libraries/packetizer/ipv4.dylan
   trunk/libraries/pcap/pcap.dylan
Log:
Bug: 7299
*added ip-layer and icmp-handler

Modified: trunk/libraries/layer/layer.dylan
==============================================================================
--- trunk/libraries/layer/layer.dylan	(original)
+++ trunk/libraries/layer/layer.dylan	Sun Jul 16 22:53:35 2006
@@ -6,7 +6,7 @@
 end;
 
 define generic ethernet-fan-in (object :: <ethernet-layer>) => (res :: <fan-in>);
-define generic demultiplexer (object :: <ethernet-layer>) => (res :: <demultiplexer>);
+define generic demultiplexer (object :: <object>) => (res :: <demultiplexer>);
 define generic ethernet-interface (object :: <ethernet-layer>) => (res :: <ethernet-interface>);
 define generic ethernet-interface-setter (object :: <ethernet-interface>, object2 :: <ethernet-layer>) => (res :: <ethernet-interface>);
 define generic default-mac-address (object :: <ethernet-layer>) => (res :: <mac-address>);
@@ -42,6 +42,7 @@
       if (default-field-value)
         field.setter(default-field-value, frame);
       elseif (~ field.fixup-function)
+        format-out("Field %=\n", field.field-name);
         signal(make(<undefined-field-error>));
       end;
     end;
@@ -50,28 +51,33 @@
 end;
 
 define open generic ethernet-type-code (object :: <ethernet-socket>) => (res :: <integer>);
-define generic listen-address (object :: <ethernet-socket>) => (res :: false-or(<mac-address>));
-define open generic demultiplexer-output (object :: <ethernet-socket>) => (res :: <object>);
-define open generic demultiplexer-output-setter (value :: <object>, object :: <ethernet-socket>) => (res :: <object>);
-define generic decapsulator (object :: <ethernet-socket>) => (res :: <decapsulator>);
-define generic completer (object :: <ethernet-socket>) => (res :: <completer>);
-define generic completer-setter (value :: <completer>, object :: <ethernet-socket>) => (res :: <completer>);
+define open generic listen-address (object :: <object>) => (res :: <object>);
+define open generic demultiplexer-output (object :: <object>) => (res :: <object>);
+define open generic demultiplexer-output-setter (value :: <object>, object :: <object>) => (res :: <object>);
+define open generic decapsulator (object :: <object>) => (res :: <decapsulator>);
+define open generic completer (object :: <object>) => (res :: <completer>);
+define open generic completer-setter (value :: <completer>, object :: <object>) => (res :: <completer>);
+define open generic resolve (object :: <object>) => (res :: <object>);
+
 define class <ethernet-socket> (<object>)
   constant slot ethernet-type-code :: <integer>, init-keyword: type-code:;
   constant slot listen-address :: false-or(<mac-address>) = #f, init-keyword: listen-address:;
   slot demultiplexer-output;
   constant slot decapsulator :: <decapsulator> = make(<decapsulator>);
   slot completer :: <completer>;
+  constant slot resolve, init-keyword: resolve:;
 end;
 
 define method create-socket (layer :: <ethernet-layer>,
                              type-code :: <integer>,
-                             #key mac-address)
+                             #key mac-address,
+                             resolve)
  => (socket :: <ethernet-socket>);
   let source-address = mac-address | layer.default-mac-address;
   let socket = make(<ethernet-socket>,
                     type-code: type-code,
-                    listen-address: source-address);
+                    listen-address: source-address,
+                    resolve: resolve);
   let template-frame = make(cache-class(<ethernet-frame>),
                             type-code: type-code,
                             source-address: source-address);
@@ -86,26 +92,38 @@
   socket;
 end;
 
+define method send (socket :: <ethernet-socket>, payload :: <container-frame>, destination :: <mac-address>);
+  let ethernet-frame = make(<ethernet-frame>,
+                            destination-address: destination,
+                            payload: payload);
+  push-data-aux(socket.completer.the-input, socket.completer, ethernet-frame);
+end;
+
+define method send (socket :: <ethernet-socket>, payload :: <container-frame>, destination :: <ipv4-address>);
+  let destination-mac = socket.resolve(destination);
+  send(socket, payload, destination-mac);
+end;
+
 define method delete-socket (socket :: <ethernet-socket>, layer :: <ethernet-layer>)
   disconnect(socket.demultiplexer-output, socket.decapsulator);
   disconnect(socket.completer, layer.ethernet-fan-in);
 end;
 
 define open generic ethernet-layer (object :: <ip-over-ethernet-adapter>) => (res :: <ethernet-layer>);
-define open generic ethernet-layer-setter (value :: <ethernet-layer>, object :: <ip-over-ethernet-adapter>) => (res :: <ethernet-layer>);
 define generic arp-handler (object :: <ip-over-ethernet-adapter>) => (res :: <arp-handler>);
-define generic arp-handler-setter (value :: <arp-handler>, object :: <ip-over-ethernet-adapter>) => (res :: <arp-handler>);
+define generic v4-address (object :: <ip-over-ethernet-adapter>) => (res :: <ipv4-address>);
+define open generic ip-layer (object :: <object>) => (res :: <ip-layer>);
+define open generic ip-layer-setter (value :: <ip-layer>, object :: <object>) => (res :: <ip-layer>);
 
 define class <ip-over-ethernet-adapter> (<object>)
-  //slot ip-layer :: <ip-layer>, required-init-keyword: ip-layer:;
-  slot ethernet-layer :: <ethernet-layer>, required-init-keyword: ethernet:;
-  slot arp-handler :: <arp-handler>, required-init-keyword: arp:;
-  slot v4-address :: <ipv4-address>, required-init-keyword: ipv4-address:;
+  constant slot ip-layer :: <ip-layer>, required-init-keyword: ip-layer:;
+  constant slot ethernet-layer :: <ethernet-layer>, required-init-keyword: ethernet:;
+  constant slot arp-handler :: <arp-handler>, required-init-keyword: arp:;
+  constant slot v4-address :: <ipv4-address>, required-init-keyword: ipv4-address:;
 end;
 
 define method initialize (ip-over-ethernet :: <ip-over-ethernet-adapter>,
                           #rest rest, #key, #all-keys);
-  let ip-socket = create-socket(ip-over-ethernet.ethernet-layer, #x800);
   let arp-socket = create-socket(ip-over-ethernet.ethernet-layer, #x806);
   let arp-broadcast-socket = create-socket(ip-over-ethernet.ethernet-layer,
                                            #x806,
@@ -113,23 +131,102 @@
   let arp-fan-in = make(<fan-in>);
   connect(arp-socket.decapsulator, arp-fan-in);
   connect(arp-broadcast-socket.decapsulator, arp-fan-in);
-  //connect(ip-socket.decapsulator, ip-handler);
-  //connect(ip-handler, ip-socket.completer);
   connect(arp-fan-in, ip-over-ethernet.arp-handler);
-  connect(ip-over-ethernet.arp-handler, arp-socket.completer);
+
+  ip-over-ethernet.arp-handler.ethernet-socket := arp-socket;
   ip-over-ethernet.arp-handler.ip-over-ethernet-adapter := ip-over-ethernet;
   ip-over-ethernet.arp-handler.arp-table[ip-over-ethernet.v4-address]
     := make(<advertised-arp-entry>,
             ip-address: ip-over-ethernet.v4-address,
             mac-address: ip-over-ethernet.ethernet-layer.default-mac-address);
+
+
+  let ip-socket = create-socket(ip-over-ethernet.ethernet-layer,
+                                #x800,
+                                resolve: curry(find-mac-address, ip-over-ethernet.arp-handler));
+  let ip-broadcast-socket = create-socket(ip-over-ethernet.ethernet-layer,
+                                          #x800,
+                                          mac-address: mac-address("ff:ff:ff:ff:ff:ff"));
+  let ipv4-fan-in = make(<fan-in>);
+  connect(ip-socket.decapsulator, ipv4-fan-in);
+  connect(ip-broadcast-socket.decapsulator, ipv4-fan-in);
+  connect(ipv4-fan-in, ip-over-ethernet.ip-layer.demultiplexer);
+  connect(ip-over-ethernet.ip-layer.ip-fan-in, ip-socket.completer);
+
+  ip-over-ethernet.ip-layer.ethernet-socket := ip-socket;
+  ip-over-ethernet.ip-layer.default-ip-address := ip-over-ethernet.v4-address;
 end;
 
-/*
+define class <ip-fan-in> (<fan-in>)
+  slot ip-layer :: <ip-layer>;
+end;
+
+define method push-data-aux (input :: <push-input>,
+                             node :: <ip-fan-in>,
+                             frame :: <frame>)
+  send(node.ip-layer.ethernet-socket, frame, frame.destination-address);
+end;
+
+define open generic ethernet-socket (object :: <object>) => (res :: <ethernet-socket>);
+define open generic ethernet-socket-setter (value :: <ethernet-socket>, object :: <object>) => (res :: <ethernet-socket>);
+define generic ip-fan-in (object :: <ip-layer>) => (res :: <fan-in>);
+define generic default-ip-address (object :: <ip-layer>) => (res :: <ipv4-address>);
+define generic default-ip-address-setter (value :: <ipv4-address>, object :: <ip-layer>) => (res :: <ipv4-address>);
+define generic packet-source-sink (object :: <ip-layer>) => (res :: <filter>);
 define class <ip-layer> (<object>)
-  slot fan-in :: <fan-in> = make(<fan-in>);
-  slot demultiplexer :: <demultiplexer> = make(<demultiplexer>);
-  slot routing-table;
+  //constant slot packet-source-sink :: <filter> = make(<filter>);
+  slot ethernet-socket :: <ethernet-socket>;
+  //slot routing-table = make(<vector-table>);
+  constant slot demultiplexer :: <demultiplexer> = make(<demultiplexer>);
+  constant slot ip-fan-in :: <ip-fan-in> = make(<ip-fan-in>);
+  slot default-ip-address :: <ipv4-address>;
+end;
+
+define method initialize (ip :: <ip-layer>,
+                          #rest rest, #key, #all-keys);
+  ip.ip-fan-in.ip-layer := ip;
+end;
+define open generic ip-protocol (object :: <ip-socket>) => (res :: <integer>);
+define class <ip-socket> (<object>)
+  constant slot ip-protocol :: <integer>, init-keyword: protocol:;
+  constant slot listen-address :: false-or(<ipv4-address>) = #f, init-keyword: listen-address:;
+  slot demultiplexer-output;
+  constant slot decapsulator :: <decapsulator> = make(<decapsulator>);
+  slot completer :: <completer>;
+  constant slot resolve, init-keyword: resolve:;
+end;
+
+define method create-socket (ip-layer :: <ip-layer>,
+                             protocol :: <integer>,
+                             #key ip-address,
+                             resolve)
+ => (res :: <ip-socket>)
+  let source-address = ip-address | ip-layer.default-ip-address;
+  let socket = make(<ip-socket>,
+                    protocol: protocol,
+                    listen-address: source-address,
+                    resolve: resolve);
+  let template-frame = make(cache-class(<ipv4-frame>),
+                            protocol: protocol,
+                            source-address: source-address);
+  socket.completer := make(<completer>,
+                           template-frame: template-frame);
+  socket.demultiplexer-output
+    := create-output-for-filter(ip-layer.demultiplexer,
+                                format-to-string("(ipv4.destination-address = %s) & (ipv4.protocol = %s)",
+                                                 source-address, protocol));
+  connect(socket.demultiplexer-output, socket.decapsulator);
+  connect(socket.completer, ip-layer.ip-fan-in);
+  socket;
+end;
+
+define method send (ip-socket :: <ip-socket>, payload :: <container-frame>, destination :: <ipv4-address>)
+  let frame = make(<ipv4-frame>,
+                   destination-address: destination,
+                   payload: payload);
+  push-data-aux(ip-socket.completer.the-input, ip-socket.completer, frame);
 end;
+/*
 define method add-static-route (ip-layer :: <ip-layer>, cidr :: <cidr>, adapter)
 end;
 
@@ -141,17 +238,53 @@
 end;
 */
 
+define generic ip-socket (object :: <icmp-handler>) => (res :: <ip-socket>);
+define generic ip-socket-setter (value :: <ip-socket>, object :: <icmp-handler>) => (res :: <ip-socket>);
+
+define class <icmp-handler> (<filter>)
+  slot ip-socket :: <ip-socket>;
+end;
+
+define method push-data-aux (input :: <push-input>,
+                             node :: <icmp-handler>,
+                             frame :: <container-frame>)
+  //format-out("ICMP Handler received %=\n", frame);
+  if (frame.type = 8 & frame.code = 0)
+    let response = make(<icmp-frame>,
+                        type: 0,
+                        code: 0,
+                        payload: frame.payload);
+    make(<thread>, function: curry(send, node.ip-socket, response, frame.parent.source-address));
+  end;
+end;
+define generic icmp-handler (object :: <icmp-over-ip-adapter>) => (res :: <icmp-handler>);
+
+define class <icmp-over-ip-adapter> (<object>)
+  constant slot ip-layer :: <ip-layer>, required-init-keyword: ip-layer:;
+  constant slot icmp-handler :: <icmp-handler>, required-init-keyword: icmp-handler:;
+end;
+
+define method initialize (icmp-over-ip :: <icmp-over-ip-adapter>,
+                          #rest rest, #key, #all-keys);
+  let icmp-socket = create-socket(icmp-over-ip.ip-layer, 1);
+  connect(icmp-socket.decapsulator, icmp-over-ip.icmp-handler);
+  icmp-over-ip.icmp-handler.ip-socket := icmp-socket;
+end;
+
 define generic arp-table (object :: <arp-handler>) => (res :: <vector-table>);
 define generic lock (object :: <arp-handler>) => (res :: <lock>);
 define generic ip-over-ethernet-adapter (object :: <arp-handler>) => (res :: <ip-over-ethernet-adapter>);
 define generic ip-over-ethernet-adapter-setter (value :: <ip-over-ethernet-adapter>, object :: <arp-handler>) => (res :: <ip-over-ethernet-adapter>);
+
 define class <arp-handler> (<filter>)
   constant slot arp-table :: <vector-table> = make(<vector-table>);
   constant slot lock :: <lock> = make(<lock>);
   slot ip-over-ethernet-adapter :: <ip-over-ethernet-adapter>;
+  slot ethernet-socket :: <ethernet-socket>;
 end;
 
 define generic original-request (object :: <outstanding-arp-request>) => (res :: <frame>);
+define generic destination (object :: <outstanding-arp-request>) => (res :: <mac-address>);
 define open generic notification (object :: <outstanding-arp-request>) => (res :: <notification>);
 define open generic notification-setter (value :: <notification>, object :: <outstanding-arp-request>) => (res :: <notification>);
 define open generic timer (object :: <outstanding-arp-request>) => (res :: <timer>);
@@ -159,17 +292,20 @@
 define open generic counter (object :: <outstanding-arp-request>) => (res :: <object>);
 define open generic counter-setter (value :: <object>, object :: <outstanding-arp-request>) => (res :: <object>);
 
+define open generic ip-address (object :: <arp-entry>) => (res :: <ipv4-address>);
 define abstract class <arp-entry> (<object>)
   constant slot ip-address :: <ipv4-address>, required-init-keyword: ip-address:;
 end;
 
 define class <outstanding-arp-request> (<arp-entry>)
   constant slot original-request :: <frame>, required-init-keyword: request:;
+  constant slot destination :: <mac-address>, required-init-keyword: destination:;
   slot notification :: <notification>;
   slot timer :: <timer>;
   slot counter = 0;
 end;
 
+define generic arp-mac-address (object :: <known-arp-entry>) => (res :: <mac-address>);
 define abstract class <known-arp-entry> (<arp-entry>)
   constant slot arp-mac-address :: <mac-address>, required-init-keyword: mac-address:;
 end;
@@ -180,6 +316,7 @@
 define class <advertised-arp-entry> (<static-arp-entry>)
 end;
 
+define open generic timestamp (object :: <dynamic-arp-entry>) => (res :: <date>);
 define class <dynamic-arp-entry> (<known-arp-entry>)
   constant slot timestamp :: <date> = current-date()
 end;
@@ -189,7 +326,7 @@
     if (request.counter > 3)
       release-all(request.notification)
     else
-      push-data(handler.the-output, request.original-request);
+      send(handler.ethernet-socket, request.original-request, request.destination);
       request.timer := make(<timer>, in: 5, event: curry(try-again, request, handler));
       request.counter := request.counter + 1;
     end
@@ -215,9 +352,7 @@
                               target-ip-address: frame.source-ip-address,
                               source-mac-address: arp-entry.arp-mac-address,
                               source-ip-address: arp-entry.ip-address);
-      push-data(node.the-output, make(<ethernet-frame>,
-                                      payload: arp-response,
-                                      destination-address: frame.source-mac-address));
+      send(node.ethernet-socket, arp-response, frame.source-mac-address);
     end;
   elseif (frame.operation = 2)
     with-lock(node.lock)
@@ -276,13 +411,11 @@
                                source-ip-address: arp-handler.ip-over-ethernet-adapter.v4-address,
                                target-ip-address: ip,
                                target-mac-address: mac-address("00:00:00:00:00:00"));
-        let ethernet-frame = make(<ethernet-frame>,
-                                  destination-address: mac-address("ff:ff:ff:ff:ff:ff"),
-                                  payload: arp-request);
-        push-data(arp-handler.the-output, ethernet-frame);
+        send(arp-handler.ethernet-socket, arp-request, mac-address("ff:ff:ff:ff:ff:ff"));
         let outstanding-request = make(<outstanding-arp-request>,
                                        handler: arp-handler,
-                                       request: ethernet-frame,
+                                       request: arp-request,
+                                       destination: mac-address("ff:ff:ff:ff:ff:ff"),
                                        ip-address: ip);
         let timer* = make(<timer>, in: 5, event: curry(try-again, outstanding-request, arp-handler));
         outstanding-request.timer := timer*;
@@ -303,19 +436,43 @@
 
 
 begin
-  let int = make(<ethernet-interface>, name: "NetXtreme");
+  let int = make(<ethernet-interface>, name: "Intel");
   let ethernet-layer = make(<ethernet-layer>, ethernet-interface: int);
   let arp-handler = make(<arp-handler>);
   arp-handler.arp-table[ipv4-address("192.168.0.23")]
     := make(<advertised-arp-entry>,
             mac-address: mac-address("00:de:ad:be:ef:00"),
             ip-address: ipv4-address("192.168.0.23"));
+  let ip-layer = make(<ip-layer>);
   let ip-over-ethernet = make(<ip-over-ethernet-adapter>,
                               ethernet: ethernet-layer,
                               arp: arp-handler,
+                              ip-layer: ip-layer,
                               ipv4-address: ipv4-address("192.168.0.24"));
+  let icmp-handler = make(<icmp-handler>);
+  let icmp-over-ip = make(<icmp-over-ip-adapter>,
+                          ip-layer: ip-layer,
+                          icmp-handler: icmp-handler);
   let thr = make(<thread>, function: curry(toplevel, int));
-  //format-out("Mac 192.168.0.1: %=\n", find-mac-address(arp-handler, ipv4-address("192.168.0.1")));
+  send(ip-layer.ethernet-socket,
+       make(<ipv4-frame>,
+            identification: 23,
+            protocol: 1,
+            source-address: ipv4-address("192.168.0.24"),
+            destination-address: ipv4-address("192.168.0.1"),
+            options: make(<stretchy-vector>),
+            payload: make(<icmp-frame>,
+                          type: 8,
+                          code: 0,
+                          payload: parse-frame(<raw-frame>, as(<byte-vector>, #(#x23, #x42, #x0, #x0))))),
+       ipv4-address("192.168.0.1"));
+  send(icmp-handler.ip-socket,
+       make(<icmp-frame>,
+            type: 8,
+            code: 0,
+            payload: parse-frame(<raw-frame>, as(<byte-vector>, #(#x23, #x42, #x0, #x0)))),
+       ipv4-address("192.168.0.1"));
+  format-out("Mac 192.168.0.1: %=\n", find-mac-address(arp-handler, ipv4-address("192.168.0.1")));
   sleep(1200);
 end;
 

Modified: trunk/libraries/network-flow/network-flow.dylan
==============================================================================
--- trunk/libraries/network-flow/network-flow.dylan	(original)
+++ trunk/libraries/network-flow/network-flow.dylan	Sun Jul 16 22:53:35 2006
@@ -39,7 +39,7 @@
   slot outputs :: <stretchy-vector> = make(<stretchy-vector>);
 end;
 
-define class <fan-in> (<single-push-output-node>)
+define open class <fan-in> (<single-push-output-node>)
   slot inputs :: <stretchy-vector> = make(<stretchy-vector>);
 end;
 

Modified: trunk/libraries/packetizer/ipv4.dylan
==============================================================================
--- trunk/libraries/packetizer/ipv4.dylan	(original)
+++ trunk/libraries/packetizer/ipv4.dylan	Sun Jul 16 22:53:35 2006
@@ -119,7 +119,7 @@
   field type-of-service :: <unsigned-byte> = 0;
   field total-length :: <2byte-big-endian-unsigned-integer>,
     fixup: frame.header-length * 4 + byte-offset(frame-size(frame.payload));
-  field identification :: <2byte-big-endian-unsigned-integer>;
+  field identification :: <2byte-big-endian-unsigned-integer> = 23;
   field evil :: <1bit-unsigned-integer> = 0;
   field dont-fragment :: <1bit-unsigned-integer> = 0;
   field more-fragments :: <1bit-unsigned-integer> = 0;
@@ -129,7 +129,7 @@
   field header-checksum :: <2byte-big-endian-unsigned-integer> = 0;
   field source-address :: <ipv4-address>;
   field destination-address :: <ipv4-address>;
-  repeated field options :: <ip-option-frame>,
+  repeated field options :: <ip-option-frame> = make(<stretchy-vector>),
     reached-end?: method(value :: <ip-option-frame>)
                       instance?(value, <end-of-option-ip-option>)
                   end;

Modified: trunk/libraries/pcap/pcap.dylan
==============================================================================
--- trunk/libraries/pcap/pcap.dylan	(original)
+++ trunk/libraries/pcap/pcap.dylan	Sun Jul 16 22:53:35 2006
@@ -32,10 +32,10 @@
   c-name: "pcap_dispatch";
 end;
 
-//XXX needed because c-ffi stuff needs to be compiled in tight mode
-define open generic interface-name (object :: <ethernet-interface>) => (res :: <string>);
-define open generic pcap-t (object :: <ethernet-interface>) => (res :: <object>);
-define open generic pcap-t-setter (value :: <object>, object :: <ethernet-interface>) => (res :: <object>);
+//XXX needed because bug #7192 c-ffi stuff needs to be compiled in tight mode
+define generic interface-name (object :: <ethernet-interface>) => (res :: <string>);
+define generic pcap-t (object :: <ethernet-interface>) => (res :: <object>);
+define generic pcap-t-setter (value :: <object>, object :: <ethernet-interface>) => (res :: <object>);
 
 define open class <ethernet-interface> (<filter>)
   constant slot interface-name :: <string> = "ath0", init-keyword: name:;
@@ -77,6 +77,7 @@
   let errbuf = make(<byte-vector>);
   block(ret)
     local method open-interface (name)
+            format-out("trying interface %s\n", name);
             let res = pcap-open-live(name,
                                      $ethernet-buffer-size,
                                      $promisc,
@@ -84,13 +85,17 @@
                                      buffer-offset(errbuf, 0));
             if (res ~= null-pointer(<C-void*>))
               interface.pcap-t := res;
+              format-out("Opened Interface %s\n", name);
               ret();
             end;
           end;
-    open-interface(interface.interface-name);
+    //open-interface(interface.interface-name);
 
+    format-out("trying pcap-find-alldevices\n");
     let (errorcode, devices) = pcap-find-all-devices(buffer-offset(errbuf, 0));
+    format-out("errcode %=\n", errorcode);
     for (device = devices then device.next, while: device ~= null-pointer(<pcap-if*>))
+      format-out("device %s %s\n", device.name, device.description);
       if (subsequence-position(device.description, interface.interface-name))
         open-interface(device.name);
       end;



More information about the chatter mailing list