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 3) (safety 1) (space 1) (debug 1)))
23 (declaim (optimize (speed 0) (safety 2) (space 0) (debug 2)))
25 (in-package :net.sockets
)
27 (defmacro define-constant
(name value
&optional doc
)
28 `(defconstant ,name
(if (boundp ',name
) (symbol-value ',name
) ,value
)
29 ,@(when doc
(list doc
))))
31 (deftype ub8
() `(unsigned-byte 8))
32 (deftype ub16
() `(unsigned-byte 16))
33 (deftype ub32
() `(unsigned-byte 32))
34 (deftype sb8
() `(signed-byte 8))
35 (deftype sb16
() `(signed-byte 16))
36 (deftype sb32
() `(signed-byte 32))
38 (defun string-or-parsed-number (val)
45 (multiple-value-bind (parsed pos
)
46 (parse-integer val
:junk-allowed t
)
48 (eql pos
(length val
))) ; the entire string is a number
53 (values type tmpval
))))))
55 (defun c->lisp-bool
(val)
56 (if (zerop val
) nil t
))
58 (defun lisp->c-bool
(val)
61 (defun addrerr-value (keyword)
62 (foreign-enum-value 'et
:addrinfo-errors keyword
))
64 (defun unixerr-value (keyword)
65 (foreign-enum-value 'et
:errno-values keyword
))
68 (not (eql (not x1
) (not x2
))))
71 ;;; Byte-swap functions
77 (declare (type ub16 newshort
)
79 (setf (ldb (byte 8 0) newshort
) (ldb (byte 8 8) short
))
80 (setf (ldb (byte 8 8) newshort
) (ldb (byte 8 0) short
))
90 (declare (type ub32 newlong
)
92 (setf (ldb (byte 8 0) newlong
) (ldb (byte 8 24) long
))
93 (setf (ldb (byte 8 24) newlong
) (ldb (byte 8 0) long
))
94 (setf (ldb (byte 8 8) newlong
) (ldb (byte 8 16) long
))
95 (setf (ldb (byte 8 16) newlong
) (ldb (byte 8 8) long
))
102 (defun copy-simple-array-ub16-to-alien-vector (lisp-vec alien-vec
)
103 (declare (type (simple-array ub16
(8)) lisp-vec
))
105 (setf (mem-aref alien-vec
:uint16 i
)
106 (htons (aref lisp-vec i
)))))
108 (defun map-ipv4-vector-to-ipv6 (addr)
109 (declare (type (simple-array ub8
(*)) addr
))
110 (let ((ipv6addr (make-array 8 :element-type
'ub16
111 :initial-element
0)))
112 ;; setting the IPv4 marker
113 (setf (aref ipv6addr
5) #xFFFF
)
114 ;; setting the first two bytes
115 (setf (aref ipv6addr
6) (+ (ash (aref addr
0) 8)
117 ;; setting the last two bytes
118 (setf (aref ipv6addr
7) (+ (ash (aref addr
2) 8)
123 ;; From CLOCC's PORT library
124 (defun vector-to-ipaddr (vector)
125 (coerce vector
'(simple-array ub8
(4)))
126 (+ (ash (aref vector
0) 24)
127 (ash (aref vector
1) 16)
128 (ash (aref vector
2) 8)
131 (defun make-sockaddr-in (sin ub8-vector
&optional
(port 0))
132 (et:memset sin
0 #.
(foreign-type-size 'et
:sockaddr-in
))
134 (with-foreign-slots ((et:family et
:address et
:port
) sin et
:sockaddr-in
)
135 (setf family et
:af-inet
)
136 (setf address
(htonl (vector-to-ipaddr ub8-vector
)))
137 (setf port
(htons tmp
))))
140 (defun make-sockaddr-in6 (sin6 ub16-vector
&optional
(port 0))
141 (et:memset sin6
0 #.
(foreign-type-size 'et
:sockaddr-in6
))
143 (with-foreign-slots ((et:family et
:address et
:port
) sin6 et
:sockaddr-in6
)
144 (setf family et
:af-inet6
)
145 (copy-simple-array-ub16-to-alien-vector ub16-vector address
)
146 (setf port
(htons tmp
))))
149 (defun make-sockaddr-un (sun string
)
150 (check-type string string
)
151 (et:memset sun
0 (foreign-type-size 'et
:sockaddr-un
))
152 (with-foreign-slots ((et:family et
:path
) sun et
:sockaddr-un
)
153 (setf family et
:af-local
)
154 (with-foreign-string (c-string string
)
156 :for off
:below
(1- et
:unix-path-max
)
157 :do
(setf (mem-aref path
:uint8 off
)
158 (mem-aref c-string
:uint8 off
)))))
161 (defun make-vector-u8-4-from-in-addr (in-addr)
162 (check-type in-addr ub32
)
163 (let ((vector (make-array 4 :element-type
'ub8
)))
164 (setf in-addr
(ntohl in-addr
))
165 (setf (aref vector
0) (ldb (byte 8 24) in-addr
))
166 (setf (aref vector
1) (ldb (byte 8 16) in-addr
))
167 (setf (aref vector
2) (ldb (byte 8 8) in-addr
))
168 (setf (aref vector
3) (ldb (byte 8 0) in-addr
))
171 (defun make-vector-u16-8-from-in6-addr (in6-addr)
172 (let ((newvector (make-array 8 :element-type
'ub16
)))
174 (setf (aref newvector i
)
175 (ntohs (mem-aref in6-addr
:uint16 i
))))
178 (defun sockaddr-in->netaddr
(sin)
179 (with-foreign-slots ((et:address et
:port
) sin et
:sockaddr-in
)
180 (values (make-instance 'ipv4addr
181 :name
(make-vector-u8-4-from-in-addr address
))
184 (defun sockaddr-in6->netaddr
(sin6)
185 (with-foreign-slots ((et:address et
:port
) sin6 et
:sockaddr-in6
)
186 (values (make-instance 'ipv6addr
187 :name
(make-vector-u16-8-from-in6-addr address
))
190 (defun sockaddr-un->netaddr
(sun)
191 (with-foreign-slots ((et:path
) sun et
:sockaddr-un
)
192 (let ((name (make-string (1- et
:unix-path-max
)))
194 (if (zerop (mem-aref path
:uint8
0))
199 :for sindex
:from
0 :below
(1- et
:unix-path-max
)
200 :for pindex
:from
1 :below et
:unix-path-max
201 :do
(setf (schar name sindex
)
202 (code-char (mem-aref path
:uint8 pindex
)))))
203 ;; address is in the filesystem
204 (setf name
(foreign-string-to-lisp path
)))
205 (make-instance 'unixaddr
207 :abstract abstract
))))
209 (defun sockaddr-storage->netaddr
(sa)
210 (with-foreign-slots ((et:family
) sa et
:sockaddr-storage
)
213 (sockaddr-in->netaddr sa
))
215 (sockaddr-in6->netaddr sa
))
217 (sockaddr-un->netaddr sa
)))))
219 (defun netaddr->sockaddr-storage
(sa netaddr
&optional
(port 0))
222 (make-sockaddr-in sa
(name netaddr
) port
))
224 (make-sockaddr-in6 sa
(name netaddr
) port
))
226 (make-sockaddr-un sa
(name netaddr
)))))