1 ;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp -*-
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
4 ; Copyright (C) 2006 by Stelian Ionescu ;
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. ;
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. ;
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
)
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."))
39 ;;; Conversion functions
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
))
60 (setf string
(coerce string
'(vector base-char
)))
62 (declare (ignore err
))
64 (error 'invalid-argument
:argument string
65 :message
(format nil
"The vector: ~A is not a string or contains non-ASCII characters." string
))
66 (return-from dotted-to-vector nil
))))
68 (with-alien ((in-addr et
:in-addr-t
))
69 (sb-sys:with-pinned-objects
(string)
72 (et:inet-pton et
:af-inet
; address family
74 (addr in-addr
)) ; pointer to struct in6_addr
76 (declare (ignore err
))
78 (error 'invalid-address
:address string
:type
:ipv4
)
79 (return-from dotted-to-vector nil
)))))
80 (make-vector-u8-4-from-in-addr in-addr
)))
82 (defun dotted-to-ipaddr (string)
83 (vector-to-ipaddr (dotted-to-vector string
)))
85 (defun vector-to-dotted (vector)
86 (setf vector
(coerce vector
'(simple-array ub8
(4))))
87 (format nil
"~A.~A.~A.~A"
93 (defun colon-separated-to-vector (string &key
(error-p t
))
95 (setf string
(coerce string
'(simple-array base-char
(*))))
97 (declare (ignore err
))
99 (error 'invalid-argument
:argument string
100 :message
(format nil
"The vector: ~A is not a string or contains non-ASCII characters." string
))
101 (return-from colon-separated-to-vector nil
))))
103 (with-alien ((in6-addr et
:in6-addr
))
104 (sb-sys:with-pinned-objects
(string)
105 (et:memset
(addr in6-addr
) 0 et
::size-of-in6-addr
)
107 (et:inet-pton et
:af-inet6
; address family
109 (addr in6-addr
)) ; pointer to struct in6_addr
111 (declare (ignore err
))
113 (error 'invalid-address
:address string
:type
:ipv4
)
114 (return-from colon-separated-to-vector nil
)))))
115 (make-vector-u16-8-from-in6-addr (addr in6-addr
))))
117 (defun vector-to-colon-separated (vector &key
(case :downcase
) (error-p t
))
119 (setf vector
(coerce vector
'(simple-array ub16
(8))))
121 (declare (ignore err
))
123 (error 'invalid-argument
:argument vector
124 :message
(format nil
"The vector: ~A does not contain only 16-bit positive integers or has not length 8." vector
))
125 (return-from vector-to-colon-separated nil
))))
128 ((sin6 et
:sockaddr-in6
)
129 (namebuff (array (unsigned 8) #.et
:inet6-addrstrlen
)))
130 (make-sockaddr-in6 (addr sin6
) vector
)
131 (et:inet-ntop et
:af-inet6
; address family
132 (addr (slot sin6
'et
:address
)) ; pointer to struct in6_addr
133 (alien-sap namebuff
) ; destination buffer
134 et
:inet6-addrstrlen
) ; INET6_ADDRSTRLEN
135 (return-from vector-to-colon-separated
136 (let ((str (cast namebuff c-string
)))
139 (:upcase
(nstring-upcase str
)))))))
141 (defun string-address->vector
(address)
142 (or (dotted-to-vector address
:error-p nil
)
143 (colon-separated-to-vector address
:error-p nil
)))
145 (defun vector-address-or-nil (address)
146 (let (vector addr-type
)
149 ((setf vector
(dotted-to-vector address
:error-p nil
))
150 (setf addr-type
:ipv4
))
151 ((setf vector
(colon-separated-to-vector address
:error-p nil
))
152 (setf addr-type
:ipv6
))))
153 ((array * (4)) (cond ((setf vector
(ignore-errors
154 (coerce address
'(simple-array octet
(4)))))
155 (setf addr-type
:ipv4
))))
156 ((array * (8)) (cond ((setf vector
(ignore-errors
157 (coerce address
'(simple-array ub16
(8)))))
158 (setf addr-type
:ipv6
))))
159 (ipv4addr (setf vector
(name address
)
161 (ipv6addr (setf vector
(name address
)
163 (values vector addr-type
)))
167 ;;; Class definitions
171 ((name :initarg
:name
:reader name
:type vector
))
172 (:documentation
"Base class for the internet addresses."))
174 (defclass ipv4addr
(netaddr) ()
175 (:documentation
"IPv4 address."))
177 (defclass ipv6addr
(netaddr) ()
178 (:documentation
"IPv6 address."))
180 (defclass localaddr
(netaddr)
181 ((abstract :initform nil
:initarg
:abstract
:reader abstract-p
:type boolean
))
182 (:documentation
"UNIX socket address."))
189 (defmethod print-object ((address ipv4addr
) stream
)
190 (print-unreadable-object (address stream
:type nil
:identity nil
)
191 (with-slots (name) address
192 (format stream
"IPv4 address: ~A" (vector-to-dotted name
)))))
194 (defmethod print-object ((address ipv6addr
) stream
)
195 (print-unreadable-object (address stream
:type nil
:identity nil
)
196 (with-slots (name) address
197 (format stream
"IPv6 address: ~A" (vector-to-colon-separated name
)))))
199 (defmethod print-object ((address localaddr
) stream
)
200 (print-unreadable-object (address stream
:type nil
:identity nil
)
201 (with-slots (name abstract
) address
202 (format stream
"Unix socket address: ~A. Abstract: ~:[no~;yes~]" name abstract
))))
204 (defmethod netaddr->presentation
((addr ipv4addr
))
205 (vector-to-dotted (name addr
)))
207 (defmethod netaddr->presentation
((addr ipv6addr
))
208 (vector-to-colon-separated (name addr
)))
210 (defmethod netaddr->presentation
((addr localaddr
))
218 (defun vector-equal (v1 v2
)
219 (and (typep v1
'vector
)
220 (equal (type-of v1
) (type-of v2
))
221 (every #'eql v1 v2
)))
223 (defmethod netaddr= ((addr1 ipv4addr
) (addr2 ipv4addr
))
224 (vector-equal (name addr1
) (name addr2
)))
226 (defmethod netaddr= ((addr1 ipv6addr
) (addr2 ipv6addr
))
227 (vector-equal (name addr1
) (name addr2
)))
229 (defmethod netaddr= ((addr1 localaddr
) (addr2 localaddr
))
230 (equal (name addr1
) (name addr2
)))
237 (defmethod copy-netaddr ((addr ipv4addr
))
238 (make-instance 'ipv4addr
239 :name
(copy-seq (name addr
))))
241 (defmethod copy-netaddr ((addr ipv6addr
))
242 (make-instance 'ipv6addr
243 :name
(copy-seq (name addr
))))
245 (defmethod copy-netaddr ((addr localaddr
))
246 (make-instance 'localaddr
247 :name
(copy-seq (name addr
))
248 :abstract
(abstract-p addr
)))
250 (defmethod map-ipv4-address->ipv6
((addr ipv4addr
))
251 (make-instance 'ipv6addr
252 :name
(map-ipv4-vector-to-ipv6 (name addr
))))
256 (defun make-address (name)
260 (make-instance 'localaddr
:name name
))
261 ((setf n
(ignore-errors
262 (coerce name
'(simple-array ub8
(4)))))
263 (make-instance 'ipv4addr
:name n
))
264 ((setf n
(ignore-errors
265 (coerce name
'(simple-array ub16
(8)))))
266 (make-instance 'ipv6addr
:name n
))
267 (t (error 'invalid-address
:address name
:type
:unknown
)))))
271 ;;; Well-known addresses
274 (defparameter +ipv4-unspecified
+
275 (make-address #(0 0 0 0)))
277 (defparameter +ipv4-loopback
+
278 (make-address #(127 0 0 1)))
280 (defparameter +ipv6-unspecified
+
281 (make-address #(0 0 0 0 0 0 0 0)))
283 (defparameter +ipv6-loopback
+
284 (make-address #(0 0 0 0 0 0 0 1)))
286 ;; Multicast addresses replacing IPv4 broadcast addresses
287 (defparameter +ipv6-interface-local-all-nodes
+
288 (make-address #(#xFF01
0 0 0 0 0 0 1)))
290 (defparameter +ipv6-link-local-all-nodes
+
291 (make-address #(#xFF02
0 0 0 0 0 0 1)))
293 (defparameter +ipv6-interface-local-all-routers
+
294 (make-address #(#xFF01
0 0 0 0 0 0 2)))
296 (defparameter +ipv6-link-local-all-routers
+
297 (make-address #(#xFF02
0 0 0 0 0 0 2)))
299 (defparameter +ipv6-site-local-all-routers
+
300 (make-address #(#xFF05
0 0 0 0 0 0 2)))
307 ;; General predicates
308 (defmethod ipv4-address-p ((addr ipv4addr
))
311 (defmethod ipv4-address-p (addr)
314 (defmethod ipv6-address-p ((addr ipv6addr
))
317 (defmethod ipv6-address-p (addr)
320 (defmethod local-address-p ((addr localaddr
))
323 (defmethod local-address-p (addr)
326 (defmethod address-type ((address ipv4addr
))
329 (defmethod address-type ((address ipv6addr
))
332 (defmethod address-type ((address localaddr
))
335 (defmethod address-type (address)
340 (defmethod netaddr-unspecified-p ((addr ipv4addr
))
341 (netaddr= addr
+ipv4-unspecified
+))
343 (defmethod netaddr-loopback-p ((addr ipv4addr
))
344 (netaddr= addr
+ipv4-loopback
+))
346 (defmethod netaddr-multicast-p ((addr ipv4addr
))
347 (eql (logand (aref (name addr
) 0)
351 (defmethod netaddr-unicast-p ((addr ipv4addr
))
352 (and (not (netaddr-unspecified-p addr
))
353 (not (netaddr-loopback-p addr
))
354 (not (netaddr-multicast-p addr
))))
357 ;; definitions taken from RFC 2460
359 (defmethod netaddr-unspecified-p ((addr ipv6addr
))
360 (netaddr= addr
+ipv6-unspecified
+))
362 (defmethod netaddr-loopback-p ((addr ipv6addr
))
363 (netaddr= addr
+ipv6-loopback
+))
365 (defmethod ipv6-ipv4-mapped-p ((addr ipv6addr
))
366 (with-slots (name) addr
367 (and (zerop (aref name
0))
368 (zerop (aref name
1))
369 (zerop (aref name
2))
370 (zerop (aref name
3))
371 (zerop (aref name
4))
372 (eql (aref name
5) #xFFFF
)
373 (< (ldb (byte 8 0) (aref name
6))
375 (< (ldb (byte 8 8) (aref name
6))
377 (< (ldb (byte 8 0) (aref name
7))
379 (< (ldb (byte 8 8) (aref name
7))
382 (defmethod netaddr-multicast-p ((addr ipv6addr
))
383 (eql (logand (aref (name addr
) 0)
387 (defmethod ipv6-interface-local-multicast-p ((addr ipv6addr
))
388 (eql (logand (aref (name addr
) 0)
392 (defmethod ipv6-link-local-multicast-p ((addr ipv6addr
))
393 (eql (logand (aref (name addr
) 0)
397 (defmethod ipv6-admin-local-multicast-p ((addr ipv6addr
))
398 (eql (logand (aref (name addr
) 0)
402 (defmethod ipv6-site-local-multicast-p ((addr ipv6addr
))
403 (eql (logand (aref (name addr
) 0)
407 (defmethod ipv6-organization-local-multicast-p ((addr ipv6addr
))
408 (eql (logand (aref (name addr
) 0)
412 (defmethod ipv6-global-multicast-p ((addr ipv6addr
))
413 (eql (logand (aref (name addr
) 0)
417 (defmethod ipv6-reserved-multicast-p ((addr ipv6addr
))
418 (member (logand (aref (name addr
) 0)
420 (list #xFF00
#xFF03
#xFF0F
)))
422 (defmethod ipv6-unassigned-multicast-p ((addr ipv6addr
))
423 (member (logand (aref (name addr
) 0)
425 (list #xFF06
#xFF07
#xFF09
#xFF0A
#xFF0B
#xFF0C
#xFF0D
)))
427 (defmethod ipv6-transient-multicast-p ((addr ipv6addr
))
428 (eql (logand (aref (name addr
) 0)
432 (defmethod ipv6-solicited-node-multicast-p ((addr ipv6addr
))
433 (let ((vec (name addr
)))
434 (and (eql (aref vec
0) #xFF02
) ; link-local permanent multicast
436 (eql (logand (aref vec
6)
440 (defmethod ipv6-link-local-unicast-p ((addr ipv6addr
))
441 (eql (aref (name addr
) 0) #xFE80
))
443 (defmethod ipv6-site-local-unicast-p ((addr ipv6addr
))
444 (eql (aref (name addr
) 0) #xFEC0
))
446 (defmethod ipv6-global-unicast-p ((addr ipv6addr
))
447 (and (not (netaddr-unspecified-p addr
))
448 (not (netaddr-loopback-p addr
))
449 (not (netaddr-multicast-p addr
))
450 (not (ipv6-link-local-unicast-p addr
))))
452 (defmethod netaddr-unicast-p ((addr ipv6addr
))
453 (or (ipv6-link-local-unicast-p addr
)
454 (and (not (netaddr-unspecified-p addr
))
455 (not (netaddr-loopback-p addr
))
456 (not (netaddr-multicast-p addr
)))))
458 (defmethod ipv6-multicast-type ((addr ipv6addr
))
460 ((ipv6-interface-local-multicast-p addr
) :interface-local
)
461 ((ipv6-link-local-multicast-p addr
) :link-local
)
462 ((ipv6-admin-local-multicast-p addr
) :admin-local
)
463 ((ipv6-site-local-multicast-p addr
) :site-local
)
464 ((ipv6-organization-local-multicast-p addr
) :organization-local
)
465 ((ipv6-global-multicast-p addr
) :global
)
466 ((ipv6-reserved-multicast-p addr
) :reserved
)
467 ((ipv6-unassigned-multicast-p addr
) :unassigned
)))
469 (defmethod netaddr-type ((addr ipv6addr
))
471 ((netaddr-unspecified-p addr
) (values :ipv6
:unspecified
))
472 ((netaddr-loopback-p addr
) (values :ipv6
:loopback
))
473 ((netaddr-multicast-p addr
) (values :ipv6
:multicast
(ipv6-multicast-type addr
)))
474 ((ipv6-link-local-unicast-p addr
) (values :ipv6
:unicast
:link-local
))
475 (t (values :ipv6
:unicast
:global
))))
477 (defmethod netaddr-type ((addr ipv4addr
))
479 ((netaddr-unspecified-p addr
) (values :ipv4
:unspecified
))
480 ((netaddr-loopback-p addr
) (values :ipv4
:loopback
))
481 ((netaddr-multicast-p addr
) (values :ipv4
:multicast
))
482 ((netaddr-unicast-p addr
) (values :ipv4
:unicast
))))