Fixes for CLISP compatibility.
[iolib.git] / sockets / address.lisp
blob596bc568ca41edb17e6c2a0af29a1ec9739af675
1 ;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp -*-
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ; Copyright (C) 2006 by Stelian Ionescu ;
5 ; ;
6 ; This program is free software; you can redistribute it and/or modify ;
7 ; it under the terms of the GNU General Public License as published by ;
8 ; the Free Software Foundation; either version 2 of the License, or ;
9 ; (at your option) any later version. ;
10 ; ;
11 ; This program is distributed in the hope that it will be useful, ;
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of ;
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;
14 ; GNU General Public License for more details. ;
15 ; ;
16 ; You should have received a copy of the GNU General Public License ;
17 ; along with this program; if not, write to the ;
18 ; Free Software Foundation, Inc., ;
19 ; 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ;
20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22 ;; (declaim (optimize (speed 2) (safety 2) (space 1) (debug 2)))
23 (declaim (optimize (speed 0) (safety 2) (space 0) (debug 2)))
25 (in-package :net.sockets)
27 ;;;;;;;;;;;;;;;;
28 ;;; ERRORS ;;;
29 ;;;;;;;;;;;;;;;;
31 (define-condition invalid-address ()
32 ((address :initarg :address :initform nil :reader address)
33 (addrtype :initarg :type :initform nil :reader address-type))
34 (:report (lambda (condition stream)
35 (format stream "Invalid ~A address: ~A" (address-type condition) (address condition))))
36 (:documentation "Condition raised when an address designator is invalid."))
38 ;;;
39 ;;; Conversion functions
40 ;;;
42 ;; From CLOCC's PORT library
43 (defun ipaddr-to-vector (ipaddr)
44 (declare (type ub32 ipaddr))
45 (vector (ldb (byte 8 24) ipaddr)
46 (ldb (byte 8 16) ipaddr)
47 (ldb (byte 8 8) ipaddr)
48 (ldb (byte 8 0) ipaddr)))
50 (defun ipaddr-to-dotted (ipaddr)
51 (declare (type ub32 ipaddr))
52 (format nil "~A.~A.~A.~A"
53 (ldb (byte 8 24) ipaddr)
54 (ldb (byte 8 16) ipaddr)
55 (ldb (byte 8 8) ipaddr)
56 (ldb (byte 8 0) ipaddr)))
58 (defun dotted-to-vector (string &key (error-p t))
59 (when (not (stringp string))
60 (if error-p
61 (error 'type-error :datum string
62 :expected-type 'string)
63 (return-from dotted-to-vector nil)))
65 (with-foreign-pointer (in-addr #.(foreign-type-size :in-addr))
66 (with-foreign-string (string-pointer string)
67 (setf (mem-ref in-addr :in-addr) 0)
68 (handler-case
69 (et:inet-pton et:af-inet ; address family
70 string-pointer ; name
71 in-addr) ; pointer to struct in6_addr
72 (unix-error (err)
73 (declare (ignore err))
74 (if error-p
75 (error 'invalid-address :address string :type :ipv4)
76 (return-from dotted-to-vector nil)))))
77 (make-vector-u8-4-from-in-addr (mem-ref in-addr :in-addr))))
79 (defun dotted-to-ipaddr (string)
80 (vector-to-ipaddr (dotted-to-vector string)))
82 (defun vector-to-dotted (vector)
83 (setf vector (coerce vector '(simple-array ub8 (4))))
84 (format nil "~A.~A.~A.~A"
85 (aref vector 0)
86 (aref vector 1)
87 (aref vector 2)
88 (aref vector 3)))
90 (defun colon-separated-to-vector (string &key (error-p t))
91 (when (not (stringp string))
92 (if error-p
93 (error 'type-error :datum string
94 :expected-type 'string)
95 (return-from colon-separated-to-vector nil)))
97 (with-foreign-object (in6-addr :uint16 8)
98 (with-foreign-string (string-pointer string)
99 (et:memset in6-addr 0 16)
100 (handler-case
101 (et:inet-pton et:af-inet6 ; address family
102 string-pointer ; name
103 in6-addr) ; pointer to struct in6_addr
104 (unix-error (err)
105 (declare (ignore err))
106 (if error-p
107 (error 'invalid-address :address string :type :ipv6)
108 (return-from colon-separated-to-vector nil)))))
109 (make-vector-u16-8-from-in6-addr in6-addr)))
111 (defun vector-to-colon-separated (vector &key (case :downcase) (error-p t))
112 (handler-case
113 (setf vector (coerce vector '(simple-array ub16 (8))))
114 (type-error (err)
115 (declare (ignore err))
116 (if error-p
117 (error 'type-error :datum vector
118 :expected-type '(simple-array (unsigned-byte 16) (8)))
119 (return-from vector-to-colon-separated nil))))
121 (with-foreign-object (sin6 'et:sockaddr-in6)
122 (with-foreign-pointer (namebuf et:inet6-addrstrlen bufsize)
123 (make-sockaddr-in6 sin6 vector)
124 (et:inet-ntop et:af-inet6 ; address family
125 (foreign-slot-pointer
126 sin6 'et:sockaddr-in6 'et:address) ; pointer to struct in6_addr
127 namebuf ; destination buffer
128 bufsize) ; INET6_ADDRSTRLEN
129 (return-from vector-to-colon-separated
130 (let ((str (foreign-string-to-lisp namebuf bufsize)))
131 (ecase case
132 (:downcase str)
133 (:upcase (nstring-upcase str))))))))
135 (defun string-address->vector (address)
136 (or (dotted-to-vector address :error-p nil)
137 (colon-separated-to-vector address :error-p nil)))
139 (defun vector-address-or-nil (address)
140 (let (vector addr-type)
141 (typecase address
142 (string (cond
143 ((setf vector (dotted-to-vector address :error-p nil))
144 (setf addr-type :ipv4))
145 ((setf vector (colon-separated-to-vector address :error-p nil))
146 (setf addr-type :ipv6))))
147 ((array * (4)) (cond ((setf vector (ignore-errors
148 (coerce address '(simple-array octet (4)))))
149 (setf addr-type :ipv4))))
150 ((array * (8)) (cond ((setf vector (ignore-errors
151 (coerce address '(simple-array ub16 (8)))))
152 (setf addr-type :ipv6))))
153 (ipv4addr (setf vector (name address)
154 addr-type :ipv4))
155 (ipv6addr (setf vector (name address)
156 addr-type :ipv6)))
157 (values vector addr-type)))
161 ;;; Class definitions
164 (defclass netaddr ()
165 ((name :initarg :name :reader name :type vector))
166 (:documentation "Base class for the internet addresses."))
168 (defclass ipv4addr (netaddr) ()
169 (:documentation "IPv4 address."))
171 (defclass ipv6addr (netaddr) ()
172 (:documentation "IPv6 address."))
174 (defclass localaddr (netaddr)
175 ((abstract :initform nil :initarg :abstract :reader abstract-p :type boolean))
176 (:documentation "UNIX socket address."))
180 ;;; Print methods
183 (defmethod print-object ((address ipv4addr) stream)
184 (print-unreadable-object (address stream :type nil :identity nil)
185 (with-slots (name) address
186 (format stream "IPv4 address: ~A"
187 (netaddr->presentation address)))))
189 (defmethod print-object ((address ipv6addr) stream)
190 (print-unreadable-object (address stream :type nil :identity nil)
191 (with-slots (name) address
192 (format stream "IPv6 address: ~A"
193 (netaddr->presentation address)))))
195 (defmethod print-object ((address localaddr) stream)
196 (print-unreadable-object (address stream :type nil :identity nil)
197 (with-slots (name abstract) address
198 (format stream "Unix socket address: ~A. Abstract: ~:[no~;yes~]"
199 (netaddr->presentation address) abstract))))
201 (defgeneric netaddr->presentation (addr))
203 (defmethod netaddr->presentation ((addr ipv4addr))
204 (vector-to-dotted (name addr)))
206 (defmethod netaddr->presentation ((addr ipv6addr))
207 (vector-to-colon-separated (name addr)))
209 (defmethod netaddr->presentation ((addr localaddr))
210 (if (abstract-p addr)
211 "unknown socket"
212 (name addr)))
216 ;;; Equality methods
219 ;; (defun vector-equal (v1 v2)
220 ;; (and (typep v1 'vector)
221 ;; (equal (type-of v1) (type-of v2))
222 ;; (every #'eql v1 v2)))
224 (defun vector-equal (v1 v2)
225 (and (equal (length v1) (length v2))
226 (every #'eql v1 v2)))
228 (defgeneric netaddr= (addr1 addr2))
230 (defmethod netaddr= ((addr1 ipv4addr) (addr2 ipv4addr))
231 (vector-equal (name addr1) (name addr2)))
233 (defmethod netaddr= ((addr1 ipv6addr) (addr2 ipv6addr))
234 (vector-equal (name addr1) (name addr2)))
236 (defmethod netaddr= ((addr1 localaddr) (addr2 localaddr))
237 (equal (name addr1) (name addr2)))
241 ;;; Copy methods
244 (defgeneric copy-netaddr (addr))
246 (defmethod copy-netaddr ((addr ipv4addr))
247 (make-instance 'ipv4addr
248 :name (copy-seq (name addr))))
250 (defmethod copy-netaddr ((addr ipv6addr))
251 (make-instance 'ipv6addr
252 :name (copy-seq (name addr))))
254 (defmethod copy-netaddr ((addr localaddr))
255 (make-instance 'localaddr
256 :name (copy-seq (name addr))
257 :abstract (abstract-p addr)))
259 (defgeneric map-ipv4-address->ipv6 (addr))
260 (defmethod map-ipv4-address->ipv6 ((addr ipv4addr))
261 (make-instance 'ipv6addr
262 :name (map-ipv4-vector-to-ipv6 (name addr))))
265 ;;; Constructor
266 (defun make-address (name)
267 (let (n)
268 (cond
269 ((stringp name)
270 (make-instance 'localaddr :name name))
271 ((setf n (ignore-errors
272 (coerce name '(simple-array ub8 (4)))))
273 (make-instance 'ipv4addr :name n))
274 ((setf n (ignore-errors
275 (coerce name '(simple-array ub16 (8)))))
276 (make-instance 'ipv6addr :name n))
277 (t (error 'invalid-address :address name :type :unknown)))))
281 ;;; Well-known addresses
284 (defparameter +ipv4-unspecified+
285 (make-address #(0 0 0 0)))
287 (defparameter +ipv4-loopback+
288 (make-address #(127 0 0 1)))
290 (defparameter +ipv6-unspecified+
291 (make-address #(0 0 0 0 0 0 0 0)))
293 (defparameter +ipv6-loopback+
294 (make-address #(0 0 0 0 0 0 0 1)))
296 ;; Multicast addresses replacing IPv4 broadcast addresses
297 (defparameter +ipv6-interface-local-all-nodes+
298 (make-address #(#xFF01 0 0 0 0 0 0 1)))
300 (defparameter +ipv6-link-local-all-nodes+
301 (make-address #(#xFF02 0 0 0 0 0 0 1)))
303 (defparameter +ipv6-interface-local-all-routers+
304 (make-address #(#xFF01 0 0 0 0 0 0 2)))
306 (defparameter +ipv6-link-local-all-routers+
307 (make-address #(#xFF02 0 0 0 0 0 0 2)))
309 (defparameter +ipv6-site-local-all-routers+
310 (make-address #(#xFF05 0 0 0 0 0 0 2)))
314 ;;; Predicates
317 ;; General predicates
318 (defgeneric ipv4-address-p (addr))
320 (defmethod ipv4-address-p ((addr ipv4addr))
323 (defmethod ipv4-address-p (addr)
324 nil)
326 (defgeneric ipv6-address-p (addr))
328 (defmethod ipv6-address-p ((addr ipv6addr))
331 (defmethod ipv6-address-p (addr)
332 nil)
334 (defgeneric local-address-p (addr))
336 (defmethod local-address-p ((addr localaddr))
339 (defmethod local-address-p (addr)
340 nil)
342 (defmethod address-type ((address ipv4addr))
343 :ipv4)
345 (defmethod address-type ((address ipv6addr))
346 :ipv6)
348 (defmethod address-type ((address localaddr))
349 :local)
351 (defmethod address-type (address)
352 nil)
354 ;; IPv4 predicates
356 (defgeneric netaddr-unspecified-p (addr))
357 (defmethod netaddr-unspecified-p ((addr ipv4addr))
358 (netaddr= addr +ipv4-unspecified+))
360 (defgeneric netaddr-loopback-p (addr))
361 (defmethod netaddr-loopback-p ((addr ipv4addr))
362 (netaddr= addr +ipv4-loopback+))
364 (defgeneric netaddr-multicast-p (addr))
365 (defmethod netaddr-multicast-p ((addr ipv4addr))
366 (eql (logand (aref (name addr) 0)
367 #xE0)
368 #xE0))
370 (defgeneric netaddr-unicast-p (addr))
371 (defmethod netaddr-unicast-p ((addr ipv4addr))
372 (and (not (netaddr-unspecified-p addr))
373 (not (netaddr-loopback-p addr))
374 (not (netaddr-multicast-p addr))))
376 ;; IPv6 predicates
377 ;; definitions taken from RFC 2460
379 (defmethod netaddr-unspecified-p ((addr ipv6addr))
380 (netaddr= addr +ipv6-unspecified+))
382 (defmethod netaddr-loopback-p ((addr ipv6addr))
383 (netaddr= addr +ipv6-loopback+))
385 (defgeneric ipv6-ipv4-mapped-p (addr))
386 (defmethod ipv6-ipv4-mapped-p ((addr ipv6addr))
387 (with-slots (name) addr
388 (and (zerop (aref name 0))
389 (zerop (aref name 1))
390 (zerop (aref name 2))
391 (zerop (aref name 3))
392 (zerop (aref name 4))
393 (eql (aref name 5) #xFFFF)
394 (< (ldb (byte 8 0) (aref name 6))
395 255)
396 (< (ldb (byte 8 8) (aref name 6))
397 255)
398 (< (ldb (byte 8 0) (aref name 7))
399 255)
400 (< (ldb (byte 8 8) (aref name 7))
401 255))))
403 (defmethod netaddr-multicast-p ((addr ipv6addr))
404 (eql (logand (aref (name addr) 0)
405 #xFF00)
406 #xFF00))
408 (defgeneric ipv6-interface-local-multicast-p (addr))
409 (defmethod ipv6-interface-local-multicast-p ((addr ipv6addr))
410 (eql (logand (aref (name addr) 0)
411 #xFF0F)
412 #xFF01))
414 (defgeneric ipv6-link-local-multicast-p (addr))
415 (defmethod ipv6-link-local-multicast-p ((addr ipv6addr))
416 (eql (logand (aref (name addr) 0)
417 #xFF0F)
418 #xFF02))
420 (defgeneric ipv6-admin-local-multicast-p (addr))
421 (defmethod ipv6-admin-local-multicast-p ((addr ipv6addr))
422 (eql (logand (aref (name addr) 0)
423 #xFF0F)
424 #xFF04))
426 (defgeneric ipv6-site-local-multicast-p (addr))
427 (defmethod ipv6-site-local-multicast-p ((addr ipv6addr))
428 (eql (logand (aref (name addr) 0)
429 #xFF0F)
430 #xFF05))
432 (defgeneric ipv6-organization-local-multicast-p (addr))
433 (defmethod ipv6-organization-local-multicast-p ((addr ipv6addr))
434 (eql (logand (aref (name addr) 0)
435 #xFF0F)
436 #xFF08))
438 (defgeneric ipv6-global-multicast-p (addr))
439 (defmethod ipv6-global-multicast-p ((addr ipv6addr))
440 (eql (logand (aref (name addr) 0)
441 #xFF0F)
442 #xFF0E))
444 (defgeneric ipv6-reserved-multicast-p (addr))
445 (defmethod ipv6-reserved-multicast-p ((addr ipv6addr))
446 (member (logand (aref (name addr) 0)
447 #xFF0F)
448 (list #xFF00 #xFF03 #xFF0F)))
450 (defgeneric ipv6-unassigned-multicast-p (addr))
451 (defmethod ipv6-unassigned-multicast-p ((addr ipv6addr))
452 (member (logand (aref (name addr) 0)
453 #xFF0F)
454 (list #xFF06 #xFF07 #xFF09 #xFF0A #xFF0B #xFF0C #xFF0D)))
456 (defgeneric ipv6-transient-multicast-p (addr))
457 (defmethod ipv6-transient-multicast-p ((addr ipv6addr))
458 (eql (logand (aref (name addr) 0)
459 #xFF10)
460 #xFF10))
462 (defgeneric ipv6-solicited-node-multicast-p (addr))
463 (defmethod ipv6-solicited-node-multicast-p ((addr ipv6addr))
464 (let ((vec (name addr)))
465 (and (eql (aref vec 0) #xFF02) ; link-local permanent multicast
466 (eql (aref vec 5) 1)
467 (eql (logand (aref vec 6)
468 #xFF00)
469 #xFF00))))
471 (defgeneric ipv6-link-local-unicast-p (addr))
472 (defmethod ipv6-link-local-unicast-p ((addr ipv6addr))
473 (eql (aref (name addr) 0) #xFE80))
475 (defgeneric ipv6-site-local-unicast-p (addr))
476 (defmethod ipv6-site-local-unicast-p ((addr ipv6addr))
477 (eql (aref (name addr) 0) #xFEC0))
479 (defgeneric ipv6-global-unicast-p (addr))
480 (defmethod ipv6-global-unicast-p ((addr ipv6addr))
481 (and (not (netaddr-unspecified-p addr))
482 (not (netaddr-loopback-p addr))
483 (not (netaddr-multicast-p addr))
484 (not (ipv6-link-local-unicast-p addr))))
486 (defmethod netaddr-unicast-p ((addr ipv6addr))
487 (or (ipv6-link-local-unicast-p addr)
488 (and (not (netaddr-unspecified-p addr))
489 (not (netaddr-loopback-p addr))
490 (not (netaddr-multicast-p addr)))))
492 (defgeneric ipv6-multicast-type (addr))
493 (defmethod ipv6-multicast-type ((addr ipv6addr))
494 (cond
495 ((ipv6-interface-local-multicast-p addr) :interface-local)
496 ((ipv6-link-local-multicast-p addr) :link-local)
497 ((ipv6-admin-local-multicast-p addr) :admin-local)
498 ((ipv6-site-local-multicast-p addr) :site-local)
499 ((ipv6-organization-local-multicast-p addr) :organization-local)
500 ((ipv6-global-multicast-p addr) :global)
501 ((ipv6-reserved-multicast-p addr) :reserved)
502 ((ipv6-unassigned-multicast-p addr) :unassigned)))
504 (defgeneric netaddr-type (addr))
506 (defmethod netaddr-type ((addr ipv6addr))
507 (cond
508 ((netaddr-unspecified-p addr) (values :ipv6 :unspecified))
509 ((netaddr-loopback-p addr) (values :ipv6 :loopback))
510 ((netaddr-multicast-p addr) (values :ipv6 :multicast (ipv6-multicast-type addr)))
511 ((ipv6-link-local-unicast-p addr) (values :ipv6 :unicast :link-local))
512 (t (values :ipv6 :unicast :global))))
514 (defmethod netaddr-type ((addr ipv4addr))
515 (cond
516 ((netaddr-unspecified-p addr) (values :ipv4 :unspecified))
517 ((netaddr-loopback-p addr) (values :ipv4 :loopback))
518 ((netaddr-multicast-p addr) (values :ipv4 :multicast))
519 ((netaddr-unicast-p addr) (values :ipv4 :unicast))))