;;; -*- Mode:Lisp; Readtable:CL; Package:USER; Base:10; Patch-File:T -*-
;;; Patch file for System version 123.118
;;; Reason:
;;;  When IP initializes its route table, it now remembers all the directly connected network
;;;  numbers.  The si:smart-address-chooser property of :internet now takes this into account
;;;  when choosing an address from a list of addresses.  (ip:parse-internet-address) requests
;;;  usage of the smart address finder.
;;; Written 20-Nov-87 15:35:55 by pld at site Gigamos Cambridge
;;; while running on Jack Flanders from band 2
;;; with Experimental System 123.117, Experimental Local-File 73.2, Experimental FILE-Server 22.1, Experimental Unix-Interface 11.0, Experimental Tape 18.0, Experimental KERMIT 34.0, Experimental ZMail 71.0, Experimental Lambda-Diag 15.0, Experimental Site Data Editor 8.4, microcode 1754, SDU Boot Tape 3.12, SDU ROM 8.



; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; IP.LISP#275 at 20-Nov-87 15:36:22
#10R INTERNET#: 
(COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "INTERNET")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; IP  "

(defvar *default-network-numbers* nil "The network numbers of directly connected networks")

))

; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; IP.LISP#275 at 20-Nov-87 15:40:44
#10R INTERNET#: 
(COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "INTERNET")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; IP  "

(defun initialize-route-table (default-internet-address)
  (when default-internet-address
    (when (consp default-internet-address)
      ;;If given a list of addresses, assume the first is the default
      (setq default-internet-address (first default-internet-address)))
    (let ((r (global:get-site-option :default-internet-routing))
	  (default-interface nil))
      (setq *route-table* nil)
      ;;Add entries for directly connected networks
      (setq *default-network-numbers* nil)
      (dolist (ni *network-interfaces*)
	(let ((my-address (second (assoc :internet (net:ni-address-alist ni) :test #'eq))))
	  (when my-address
	    (when (= my-address default-internet-address)
	      (setq default-interface ni))
	    (let* ((ip-on-ni (assoc :internet (net:ni-network-alist ni) :test #'eq))
		   (my-network (second ip-on-ni))
		   (mask (third ip-on-ni)))
	      (when my-network
		(let ((network-number (logand mask my-network)))
		  (push (cons network-number mask) *default-network-numbers*)
		  (add-gateway network-number my-address ni)))))))
      ;;Add entries for gateways listed in site files
      (cond ((null r))
	    ((atom r)
	     (add-gateway 0			;Network = 0 means default gateway
			  (parse-internet-address r)	;the gateway
			  default-interface))
	    ((listp r)
	     (dolist (elem r)
	       (add-gateway (parse-internet-address (first elem))
			    (parse-internet-address (second elem))
			    default-interface)))
	    (t nil)))
    (cond ((null si:*ethernet-hardware-controller*))	;No network interface?  Too bad...
	  ((eq si:*ethernet-hardware-controller* si:*my-op*))	;We talk directly to ethernet?  Good...
	  (t
	   ;;If we don't talk directly to the ethernet, add the real ethernet hardware controller
	   ;;as default gateway
	   (add-gateway 0
			(net:find-network-address-for-other-processor si:*ethernet-hardware-controller*
								      :internet)
			si:share-interface)))))

))

; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; IP.LISP#275 at 20-Nov-87 15:46:36
#10R INTERNET#: 
(COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "INTERNET")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; IP  "

(defun (:property :internet si:smart-address-chooser) (addresses)
  (or (dolist (x addresses)
	(when (member x *default-network-numbers*
			:test #'(lambda (a b)
				  (= (logand a (cdr b)) (car b))))
	  (return x)))
      (first addresses)))

))

; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; IP.LISP#276 at 20-Nov-87 19:44:52
#10R INTERNET#: 
(COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "INTERNET")))
  (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; IP  "

(defun parse-internet-address (address &aux name)
  (labels ((glom-address (string)
	     (let* ((first (string-search-char #\. string))
		    (second (and first (string-search-char #\. string (1+ first))))
		    (third (and second (string-search-char #\. string (1+ second)))))
	       (if first			;If at least one dot, must be three of them...
		   (when (and second third)
		     (let ((one (parse-integer string :start 0 :end first :junk-allowed t))
			   (two (parse-integer string :start (1+ first) :end second :junk-allowed t))
			   (three (parse-integer string :start (1+ second) :end third :junk-allowed t))
			   (four (parse-integer string :start (1+ third) :junk-allowed t)))
		       (when (and one (not (minusp one)) (< one 256)
				  two (not (minusp two)) (< two 256)
				  three (not (minusp three)) (< three 256)
				  four (not (minusp four)) (< four 256))
			 (dpb one (byte 8 24)
			      (dpb two (byte 8 16)
				   (dpb three (byte 8 8)
					four))))))
		 (parse-integer string :junk-allowed t)))))	;If no dots, address given as an integer
    (cond ((null address) nil)
	  ((numberp address) address)
	  ((or (and (symbolp address)
		    (setq name (symbol-name address)))
	       (and (stringp address)
		    (setq name address)))
	   (let ((host (si:parse-host name t nil)))
	     (if host
		 (send host :network-address :internet t)
	       (glom-address name))))
	  ((typep address 'si:host)
	   (send address :network-address :internet t))
	  (t nil))))

))
