;;; -*- Mode:Lisp;Package:INTERNET;Base:10 -*- ;;; This is SYS: IP; ADDRESS (DEFCONSTANT IPA-WILD #O100) ; signals wild component of address (DEFMACRO IPA-REF (IPA IDX) `(AREF ,IPA ,IDX)) (DEFMACRO IPA-3 (IPA) `(IPA-REF ,IPA 3)) ; MSB (DEFMACRO IPA-2 (IPA) `(IPA-REF ,IPA 2)) (DEFMACRO IPA-1 (IPA) `(IPA-REF ,IPA 1)) (DEFMACRO IPA-0 (IPA) `(IPA-REF ,IPA 0)) ; LSB (DEFSTRUCT (ADDRESS (:TYPE :NAMED-ARRAY-LEADER) (:MAKE-ARRAY (:TYPE 'ART-16B :LENGTH 4)) (:CONSTRUCTOR MAKE-ADDRESS-INTERNAL)) IPA-HOST) (DEFUN IPA-PRINT-COMPONENT (VAL STREAM) (IF (= VAL IPA-WILD) (SEND STREAM :TYO #/*) (FORMAT STREAM "~D" VAL))) (DEFUN IPA-PRINT-ADDRESS (A STREAM) (IPA-PRINT-COMPONENT (IPA-3 A) STREAM) (SEND STREAM :TYO #/.) (IPA-PRINT-COMPONENT (IPA-2 A) STREAM) (SEND STREAM :TYO #/.) (IPA-PRINT-COMPONENT (IPA-1 A) STREAM) (SEND STREAM :TYO #/.) (IPA-PRINT-COMPONENT (IPA-0 A) STREAM)) (DEFSELECT ((:PROPERTY ADDRESS SI:NAMED-STRUCTURE-INVOKE) () T) (:PRINT-SELF (ME STREAM IGNORE SLASHIFY-P) (IF SLASHIFY-P (FORMAT STREAM "#~S /"~A/"" 'ADDRESS ME) (IPA-PRINT-ADDRESS ME STREAM))) (:WHICH-OPERATIONS (&REST FOO) FOO '(:PRINT-SELF))) (DEFUN (:PROPERTY ADDRESS SI:READ-INSTANCE) (IGNORE IGNORE STREAM) (PARSE-ADDRESS (READ STREAM))) ;;; They are compared LSB first, since that's where addresses from the same network ;;; usually differ; they ALWAYS differ there for the same class C network. (DEFUN ADDRESS-HASH-EQUAL (TEST-ADDRESS IPA) (AND (= (IPA-0 TEST-ADDRESS) (IPA-0 IPA)) (= (IPA-1 TEST-ADDRESS) (IPA-1 IPA)) (= (IPA-2 TEST-ADDRESS) (IPA-2 IPA)) (= (IPA-3 TEST-ADDRESS) (IPA-3 IPA)))) (DEFUN ADDRESS-HASH (A) ; no masterpiece, but it'll do fer now (+ (%LOGDPB (LOGAND #O177 (IPA-3 A)) #O2010 (%LOGDPB (IPA-2 A) #O1010 (IPA-1 A))) (LSH (IPA-0 A) -1))) ;;; Wild address usually differ in the MSB (IPA-3) (DEFUN ADDRESS-MATCH-P (A WILD &AUX TEM) (AND (OR (= IPA-WILD (SETQ TEM (IPA-3 WILD))) (= TEM (IPA-3 A))) (OR (= IPA-WILD (SETQ TEM (IPA-2 WILD))) (= TEM (IPA-2 A))) (OR (= IPA-WILD (SETQ TEM (IPA-1 WILD))) (= TEM (IPA-1 A))) (OR (= IPA-WILD (SETQ TEM (IPA-0 WILD))) (= TEM (IPA-0 A))))) (DEFRESOURCE TEST-ADDRESS () :CONSTRUCTOR (MAKE-ARRAY 4 :TYPE ART-16B)) (DEFVAR *ADDRESS-TABLE* (MAKE-HASH-TABLE :SIZE 100 :COMPARE-FUNCTION 'ADDRESS-HASH-EQUAL :HASH-FUNCTION 'ADDRESS-HASH)) (DEFUN PARSE-ADDRESS-COMPONENT (STRING FROM TO) (IF (AND (= (- TO FROM) 1) (= (AREF STRING FROM) #/*)) IPA-WILD (LET ((NUMBER (PARSE-NUMBER STRING FROM TO 10 T))) (IF (OR (> NUMBER 255) (MINUSP NUMBER)) (FERROR () "Number (~D) out of range in Internet address" NUMBER) NUMBER)))) (DEFUN MAKE-ADDRESS (ARRAY &OPTIONAL HOST) (LET ((IPA (MAKE-ADDRESS-INTERNAL))) (AND HOST (SETF (IPA-HOST IPA) HOST)) (COPY-ARRAY-CONTENTS ARRAY IPA) IPA)) (DEFUN IPA-INTERN (ADDRESS) (OR (GETHASH ADDRESS *ADDRESS-TABLE*) (LET ((IPA (MAKE-ADDRESS ADDRESS))) (PUTHASH IPA IPA *ADDRESS-TABLE*)))) (DEFUN PARSE-ADDRESS (STRING &OPTIONAL (FROM 0) (TO (STRING-LENGTH STRING))) (USING-RESOURCE (TEM TEST-ADDRESS) (DO ((LOCAL-TO 0) (IPA-IDX 3)) ((= IPA-IDX -1) (IPA-INTERN TEM)) (SETQ LOCAL-TO (STRING-SEARCH-CHAR #/. STRING FROM TO)) (IF (NULL LOCAL-TO) (IF (ZEROP IPA-IDX) (SETQ LOCAL-TO TO) (FERROR () "Not enough fields for an Internet address"))) (SETF (IPA-REF TEM IPA-IDX) (PARSE-ADDRESS-COMPONENT STRING FROM LOCAL-TO)) (DECF IPA-IDX) (SETQ FROM (+ LOCAL-TO 1)))))