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)))
24 (in-package #:net.sockets
)
27 ;;; Conversion functions
30 ;; From CLOCC's PORT library
31 (defun vector-to-ipaddr (vector)
32 (declare (type (simple-array ub8
(*)) vector
))
33 (+ (ash (aref vector
0) 24)
34 (ash (aref vector
1) 16)
35 (ash (aref vector
2) 8)
38 ;; From CLOCC's PORT library
39 (defun ipaddr-to-vector (ipaddr)
40 (declare (type ub32 ipaddr
))
41 (vector (ldb (byte 8 24) ipaddr
)
42 (ldb (byte 8 16) ipaddr
)
43 (ldb (byte 8 8) ipaddr
)
44 (ldb (byte 8 0) ipaddr
)))
46 (defun ipaddr-to-dotted (ipaddr)
47 (declare (type ub32 ipaddr
))
48 (format nil
"~a.~a.~a.~a"
49 (ldb (byte 8 24) ipaddr
)
50 (ldb (byte 8 16) ipaddr
)
51 (ldb (byte 8 8) ipaddr
)
52 (ldb (byte 8 0) ipaddr
)))
54 (defun dotted-to-ipaddr (string)
55 (vector-to-ipaddr (dotted-to-vector string
)))
57 (defun dotted-to-vector (string &key
(error-p t
))
59 (setf string
(coerce string
'(vector base-char
)))
61 (declare (ignore err
))
63 (error 'invalid-argument
:argument string
64 :message
(format nil
"The vector: ~a is not a string or contains non-ASCII characters." string
))
65 (return-from dotted-to-vector nil
))))
67 (with-alien ((in-addr sb-posix
::in-addr-t
))
68 (sb-sys:with-pinned-objects
(in-addr string
)
71 (sb-posix::inet-pton sb-posix
::af-inet
; address family
73 (addr in-addr
)) ; pointer to struct in6_addr
74 (sb-posix:syscall-error
(err)
75 (declare (ignore err
))
77 (error 'invalid-address
:address string
:type
:ipv4
)
78 (return-from dotted-to-vector nil
)))))
79 (make-vector-u8-4-from-in-addr in-addr
)))
81 (defun vector-to-dotted (vector)
82 (declare (type (simple-array ub8
(*)) vector
))
83 (format nil
"~a.~a.~a.~a"
89 (defun colon-separated-to-vector (string &key
(error-p t
))
91 (setf string
(coerce string
'(simple-array base-char
(*))))
93 (declare (ignore err
))
95 (error 'invalid-argument
:argument string
96 :message
(format nil
"The vector: ~a is not a string or contains non-ASCII characters." string
))
97 (return-from colon-separated-to-vector nil
))))
99 (with-alien ((in6-addr sb-posix
::in6-addr
))
100 (sb-sys:with-pinned-objects
(in6-addr string
)
101 (sb-posix::memset
(addr in6-addr
) 0 sb-posix
::size-of-in6-addr
)
103 (sb-posix::inet-pton sb-posix
::af-inet6
; address family
105 (addr in6-addr
)) ; pointer to struct in6_addr
106 (sb-posix:syscall-error
(err)
107 (declare (ignore err
))
109 (error 'invalid-address
:address string
:type
:ipv4
)
110 (return-from colon-separated-to-vector nil
)))))
111 (make-vector-u16-8-from-in6-addr (addr in6-addr
))))
113 (defun vector-to-colon-separated (vector &key
(case :downcase
) (error-p t
))
115 (setf vector
(coerce vector
'(simple-array ub16
(8))))
117 (declare (ignore err
))
119 (error 'invalid-argument
:argument vector
120 :message
(format nil
"The vector: ~a does not contain only 16-bit positive integers or has not length 8." vector
))
121 (return-from vector-to-colon-separated nil
))))
124 ((sin6 sb-posix
::sockaddr-in6
)
125 (namebuff (array (unsigned 8) #.sb-posix
::inet6-addrstrlen
)))
126 (make-sockaddr-in6 (addr sin6
) vector
)
127 (sb-posix::inet-ntop sb-posix
::af-inet6
; address family
128 (addr (slot sin6
'sb-posix
::addr
)) ; pointer to struct in6_addr
129 (alien-sap namebuff
) ; destination buffer
130 sb-posix
::inet6-addrstrlen
) ; INET6_ADDRSTRLEN
131 (return-from vector-to-colon-separated
132 (let ((str (cast namebuff c-string
)))
135 (:upcase
(nstring-upcase str
)))))))
139 ;;; Class definitions
143 ((name :initarg
:name
:reader name
:type vector
))
144 (:documentation
"Base class for the internet addresses."))
146 (defclass ipv4addr
(netaddr) ()
147 (:documentation
"IPv4 address."))
149 (defclass ipv6addr
(netaddr) ()
150 (:documentation
"IPv6 address."))
152 (defclass unixaddr
(netaddr)
153 ((abstract :initform nil
:initarg
:abstract
:reader abstract-p
:type boolean
))
154 (:documentation
"UNIX socket address."))
161 (defmethod print-object ((address ipv4addr
) stream
)
162 (print-unreadable-object (address stream
:type nil
:identity nil
)
163 (with-slots (name) address
164 (format stream
"IPv4 address: ~a" (vector-to-dotted name
)))))
166 (defmethod print-object ((address ipv6addr
) stream
)
167 (print-unreadable-object (address stream
:type nil
:identity nil
)
168 (with-slots (name) address
169 (format stream
"IPv6 address: ~a" (vector-to-colon-separated name
)))))
171 (defmethod print-object ((address unixaddr
) stream
)
172 (print-unreadable-object (address stream
:type nil
:identity nil
)
173 (with-slots (name abstract
) address
174 (format stream
"Unix socket address: ~a. Abstract: ~:[no~;yes~]" name abstract
))))
176 (defmethod netaddr->presentation
((addr ipv4addr
))
177 (vector-to-dotted (name addr
)))
179 (defmethod netaddr->presentation
((addr ipv6addr
))
180 (vector-to-colon-separated (name addr
)))
187 (defmethod netaddr= ((addr1 ipv4addr
) (addr2 ipv4addr
))
188 (equalp (name addr1
) (name addr2
)))
190 (defmethod netaddr= ((addr1 ipv6addr
) (addr2 ipv6addr
))
191 (equalp (name addr1
) (name addr2
)))
193 (defmethod netaddr= ((addr1 unixaddr
) (addr2 unixaddr
))
194 (equal (name addr1
) (name addr2
)))
201 (defmethod copy-netaddr ((addr ipv4addr
))
202 (make-instance 'ipv4addr
203 :name
(copy-seq (name addr
))))
205 (defmethod copy-netaddr ((addr ipv6addr
))
206 (make-instance 'ipv6addr
207 :name
(copy-seq (name addr
))))
209 (defmethod copy-netaddr ((addr unixaddr
))
210 (make-instance 'unixaddr
211 :name
(copy-seq (name addr
))
212 :abstract
(abstract-p addr
)))
216 (defun make-address (type name
)
218 (:ipv4
(make-instance 'ipv4addr
219 :name
(coerce name
'(simple-array ub8
(4)))))
220 (:ipv6
(make-instance 'ipv6addr
221 :name
(coerce name
'(simple-array ub16
(8)))))
222 (:unix
(make-instance 'unixaddr
227 ;;; Well-known addresses
230 (defparameter +ipv4-unspecified
+
231 (make-address :ipv4
#(0 0 0 0)))
233 (defparameter +ipv4-loopback
+
234 (make-address :ipv4
#(127 0 0 1)))
236 (defparameter +ipv6-unspecified
+
237 (make-address :ipv6
#(0 0 0 0 0 0 0 0)))
239 (defparameter +ipv6-loopback
+
240 (make-address :ipv6
#(0 0 0 0 0 0 0 1)))
242 ;; Multicast addresses replacing IPv4 broadcast addresses
243 (defparameter +ipv6-interface-local-all-nodes
+
244 (make-address :ipv6
#(#xFF01
0 0 0 0 0 0 1)))
246 (defparameter +ipv6-link-local-all-nodes
+
247 (make-address :ipv6
#(#xFF02
0 0 0 0 0 0 1)))
249 (defparameter +ipv6-interface-local-all-routers
+
250 (make-address :ipv6
#(#xFF01
0 0 0 0 0 0 2)))
252 (defparameter +ipv6-link-local-all-routers
+
253 (make-address :ipv6
#(#xFF02
0 0 0 0 0 0 2)))
255 (defparameter +ipv6-site-local-all-routers
+
256 (make-address :ipv6
#(#xFF05
0 0 0 0 0 0 2)))
263 ;; General predicates
264 (defmethod ipv4-address-p ((addr ipv4addr
))
267 (defmethod ipv4-address-p ((addr netaddr
))
270 (defmethod ipv6-address-p ((addr ipv6addr
))
273 (defmethod ipv6-address-p ((addr netaddr
))
276 (defmethod unix-address-p ((addr unixaddr
))
279 (defmethod unix-address-p ((addr netaddr
))
284 (defmethod netaddr-unspecified-p ((addr ipv4addr
))
285 (netaddr= addr
+ipv4-unspecified
+))
287 (defmethod netaddr-loopback-p ((addr ipv4addr
))
288 (netaddr= addr
+ipv4-loopback
+))
290 (defmethod netaddr-multicast-p ((addr ipv4addr
))
291 (eql (logand (aref (name addr
) 0)
295 (defmethod netaddr-unicast-p ((addr ipv4addr
))
296 (and (not (netaddr-unspecified-p addr
))
297 (not (netaddr-loopback-p addr
))
298 (not (netaddr-multicast-p addr
))))
301 ;; definitions taken from RFC 2460
303 (defmethod netaddr-unspecified-p ((addr ipv6addr
))
304 (netaddr= addr
+ipv6-unspecified
+))
306 (defmethod netaddr-loopback-p ((addr ipv6addr
))
307 (netaddr= addr
+ipv6-loopback
+))
309 (defmethod ipv6-ipv4-mapped-p ((addr ipv6addr
))
310 (with-slots (name) addr
311 (and (zerop (aref name
0))
312 (zerop (aref name
1))
313 (zerop (aref name
2))
314 (zerop (aref name
3))
315 (zerop (aref name
4))
316 (eql (aref name
5) #xFFFF
)
317 (< (ldb (byte 8 0) (aref name
6))
319 (< (ldb (byte 8 8) (aref name
6))
321 (< (ldb (byte 8 0) (aref name
7))
323 (< (ldb (byte 8 8) (aref name
7))
326 (defmethod netaddr-multicast-p ((addr ipv6addr
))
327 (eql (logand (aref (name addr
) 0)
331 (defmethod ipv6-interface-local-multicast-p ((addr ipv6addr
))
332 (eql (logand (aref (name addr
) 0)
336 (defmethod ipv6-link-local-multicast-p ((addr ipv6addr
))
337 (eql (logand (aref (name addr
) 0)
341 (defmethod ipv6-admin-local-multicast-p ((addr ipv6addr
))
342 (eql (logand (aref (name addr
) 0)
346 (defmethod ipv6-site-local-multicast-p ((addr ipv6addr
))
347 (eql (logand (aref (name addr
) 0)
351 (defmethod ipv6-organization-local-multicast-p ((addr ipv6addr
))
352 (eql (logand (aref (name addr
) 0)
356 (defmethod ipv6-global-multicast-p ((addr ipv6addr
))
357 (eql (logand (aref (name addr
) 0)
361 (defmethod ipv6-reserved-multicast-p ((addr ipv6addr
))
362 (member (logand (aref (name addr
) 0)
364 (list #xFF00
#xFF03
#xFF0F
)))
366 (defmethod ipv6-unassigned-multicast-p ((addr ipv6addr
))
367 (member (logand (aref (name addr
) 0)
369 (list #xFF06
#xFF07
#xFF09
#xFF0A
#xFF0B
#xFF0C
#xFF0D
)))
371 (defmethod ipv6-transient-multicast-p ((addr ipv6addr
))
372 (eql (logand (aref (name addr
) 0)
376 (defmethod ipv6-solicited-node-multicast-p ((addr ipv6addr
))
377 (let ((vec (name addr
)))
378 (and (eql (aref vec
0) #xFF02
) ; link-local permanent multicast
380 (eql (logand (aref vec
6)
384 (defmethod ipv6-link-local-unicast-p ((addr ipv6addr
))
385 (eql (aref (name addr
) 0) #xFE80
))
387 (defmethod ipv6-site-local-unicast-p ((addr ipv6addr
))
388 (eql (aref (name addr
) 0) #xFEC0
))
390 (defmethod ipv6-global-unicast-p ((addr ipv6addr
))
391 (and (not (netaddr-unspecified-p addr
))
392 (not (netaddr-loopback-p addr
))
393 (not (netaddr-multicast-p addr
))
394 (not (ipv6-link-local-unicast-p addr
))))
396 (defmethod netaddr-unicast-p ((addr ipv6addr
))
397 (or (ipv6-link-local-unicast-p addr
)
398 (and (not (netaddr-unspecified-p addr
))
399 (not (netaddr-loopback-p addr
))
400 (not (netaddr-multicast-p addr
)))))
402 (defmethod ipv6-multicast-type ((addr ipv6addr
))
404 ((ipv6-interface-local-multicast-p addr
) :interface-local
)
405 ((ipv6-link-local-multicast-p addr
) :link-local
)
406 ((ipv6-admin-local-multicast-p addr
) :admin-local
)
407 ((ipv6-site-local-multicast-p addr
) :site-local
)
408 ((ipv6-organization-local-multicast-p addr
) :organization-local
)
409 ((ipv6-global-multicast-p addr
) :global
)
410 ((ipv6-reserved-multicast-p addr
) :reserved
)
411 ((ipv6-unassigned-multicast-p addr
) :unassigned
)))
413 (defmethod netaddr-type ((addr ipv6addr
))
415 ((netaddr-unspecified-p addr
) (values :ipv6
:unspecified
))
416 ((netaddr-loopback-p addr
) (values :ipv6
:loopback
))
417 ((netaddr-multicast-p addr
) (values :ipv6
:multicast
(ipv6-multicast-type addr
)))
418 ((ipv6-link-local-unicast-p addr
) (values :ipv6
:unicast
:link-local
))
419 (t (values :ipv6
:unicast
:global
))))
421 (defmethod netaddr-type ((addr ipv4addr
))
423 ((netaddr-unspecified-p addr
) (values :ipv4
:unspecified
))
424 ((netaddr-loopback-p addr
) (values :ipv4
:loopback
))
425 ((netaddr-multicast-p addr
) (values :ipv4
:multicast
))
426 ((netaddr-unicast-p addr
) (values :ipv4
:unicast
))))