33.17. Raw Socket Access

33.17.1. Introduction
33.17.2. Single System Call Functions
33.17.3. Common arguments Platform-dependent Keywords
33.17.4. Return Values
33.17.5. Not Implemented
33.17.6. Errors
33.17.7. High-Level Functions

33.17.1. Introduction

This is the raw socket interface, as described in <sys/socket.h>. Sockets are represented by their FIXNUM file descriptors.

When this module is present, *FEATURES* contains the symbol :RAWSOCK.


For most uses of sockets, the facilities described in Section 32.4, “Socket Streams” are adequate and much more convenient than these. You are encouraged to consider SOCKET:SOCKET-STREAMs and ensure that they are not adequate for your purposes before you use raw sockets.


You can turn such a raw socket into a usual lisp STREAM using EXT:MAKE-STREAM, but you should be extremely careful with such dubious actions! See the clisp-devel mailing list archives for more details. Note that EXT:MAKE-STREAM will duplicate the file descriptor (using dup), so you still have to CLOSE the original raw socket.

Test file modules/rawsock/test.tst and the demos in modules/rawsock/demos/ contain plenty of examples.

33.17.2. Single System Call Functions

We implement access to

(accept socket address)
(bind socket address)
(connect socket address)
(getaddrinfo &KEY node service protocol socktype family passive canonname numerichost numericserv v4mapped all addrconfig)
(getnameinfo address &KEY nofqdn numerichost namereqd numericserv numericscope dgram)
(getpeername socket address)
(getsockname socket address)
(htonl n)
(htons n)
(ntohl n)
(ntohs n)
(recv socket buffer &KEY start end peek oob waitall)
(recvfrom socket buffer address &KEY start end peek oob waitall)
(recvmsg socket message &KEY start end peek oob waitall)
(send socket buffer &KEY start end oob eor)
(sendmsg socket message &KEY start end oob eor)
(sendto socket buffer address &KEY start end oob eor)
(sockatmark socket)
(socket domain type protocol)
(socketpair domain type protocol)

using same-named lisp functions in package RAWSOCK. Additionally,

(RAWSOCK:SOCK-CLOSE socket) calls close.
(RAWSOCK:SOCK-LISTEN socket &OPTIONAL (backlog SOMAXCONN)) calls listen.


When the OS does not provide socketpair, it is emulated using socket + connect + accept.

33.17.3. Common arguments

void* buffer
A (VECTOR (UNSIGNED-BYTE 8)). The vector may be adjustable and have a fill pointer. Whenever a function accepts a buffer argument, it also accepts :START and :END keyword arguments with the usual meaning and defaults. You do not have to supply the vector length because Lisp can determine it itself, but, if you want to, you can use :END argument for that.
int socket
An INTEGER (returned by socketpair or socket).
int family
int domain
A NIL (stands for AF_UNSPEC), INTEGER, or a platform-specific keyword, e.g., :INET stands for AF_INET.
int type
A NIL (stands for 0); INTEGER; or a platform-specific keyword, e.g., :DGRAM stands for SOCK_DGRAM.
int protocol
A NIL (stands for 0); INTEGER; a platform-specific keyword, e.g., :ETH_P_ARP stands for ETH_P_ARP, :IPPROTO-ICMP stands for IPPROTO_ICMP; or a STRING (passed to getprotobyname).
int flags
This C argument corresponds to keyword arguments to the Lisp functions. E.g., rawsock:send accepts :OOB and EOR arguments, while rawsock:recv accepts PEEK, OOB and WAITALL.
struct sockaddr address
A STRUCTURE-OBJECT RAWSOCK:SOCKADDR returned by MAKE-SOCKADDR. You do not need to supply its length because Lisp can determine it itself.
struct msghdr message

A STRUCTURE-OBJECT RAWSOCK:MESSAGE with the following slots:




a (VECTOR (VECTOR (UNSIGNED-BYTE 8))) (:START and :END arguments are applied to this vector)




a LIST Platform-dependent Keywords

One can extract the list of acceptable platform-dependent keywords for, e.g., socket domain, using the following code:

                    (LAMBDA (c)
                      (FORMAT T "~&error: ~A~%" c)
                      (RETURN (CDDR (THIRD (TYPE-ERROR-EXPECTED-TYPE c)))))))
     (rawsock:socket "bad" NIL NIL)))

33.17.4. Return Values

The return values of the functions described in section Section 33.17.2, “Single System Call Functions” are derived from the return values of the underlying system call: if, say, the address argument is modified by the system call, two values are returned (in addition to the possible values coming from the return value of the system call): the (modified) address structure and its new size. If the system call fails, an ERROR is SIGNALed.

33.17.5. Not Implemented

We do not interface to select or poll in this module, they are already available through SOCKET:SOCKET-STATUS.

We do not interface to shutdown in this module, it is already available through SOCKET:SOCKET-STREAM-SHUTDOWN.

We do not interface to gethostbyname or gethostbyaddr in this module, they are already available through POSIX:RESOLVE-HOST-IPADDR.

33.17.6. Errors

Errors in getaddrinfo and getnameinfo are SIGNALed as CONDITIONs of type RAWSOCK:EAI using gai_strerror.

Errors in other functions are reported as the usual OS errors (using strerror).

33.17.7. High-Level Functions

Functions that do not correspond to a single system call

(RAWSOCK:SOCK-READ socket buffer &KEY start end)
(RAWSOCK:SOCK-WRITE socket buffer &KEY start end)

Call one of read/readv or write/writev (depending on whether buffer is a (VECTOR (UNSIGNED-BYTE 8)) or a (VECTOR (VECTOR (UNSIGNED-BYTE 8)))). Return the number of bytes read or written.

When readv and writev and not available, they are emulated by repeated calls to read and write.

On Win32 we have to use recv instead of read and send instead of write because Win32 read and write do not work on sockets, only on regular files.

Call getprotobyname when protocol is a STRING, or call getprotobynumber when protocol is an INTEGER. Return a RAWSOCK:PROTOCOL structure object. When protocol is NIL, return a LIST of all known protocols using setprotoent, getprotoent, and endprotoent.
Call getnetbyname when network is a STRING, or call getnetbyaddr when network is an INTEGER. Return a RAWSOCK:NETWORK structure object. When network is NIL, return a LIST of all known networks using setnetent, getnetent, and endnetent.
Call if_nametoindex when what is a STRING and return an INTEGER; or call if_indextoname when what is an INTEGER and return a STRING. When what is NIL, return an association list of pairs (index . name) using if_nameindex.
Call getifaddrs and return a LIST of ifaddrs objects, optionally filtered using flags, e.g., (ifaddrs :flags-or '(a b) :flags-and '(c d)) will return a list of objects which have flags c and d and at least one of a or b set.
Call getsockopt and setsockopt, returns and sets individual (for specific option name and level) and multiple (when name is NIL and/or level is :ALL) options. (See also SOCKET:SOCKET-OPTIONS.)

Convert between STRING and INTEGER IP address representations using

Create a sockaddr object. data should be a sequence of (UNSIGNED-BYTE 8) or an INTEGER (meaning (MAKE-LIST data :initial-element 0)). When omitted, the standard platform-specific size is used.
Return the symbolic family of the sockaddr object.

Return a fresh VECTOR displaced to the data field of the C struct sockaddr object.


Modifying this VECTOR's content will modify the address argument data!

Open a UNIX socket special file. Returns two values: socket and address.
Open a UNIX socket special file. Returns two values: stream and address. type is passed to RAWSOCK:OPEN-UNIX-SOCKET, other options to EXT:MAKE-STREAM (but see Do not use EXT:MAKE-STREAM!).
(RAWSOCK:IPCSUM buffer &KEY start end) - IP
(RAWSOCK:ICMPCSUM buffer &KEY start end) - ICMP
(RAWSOCK:TCPCSUM buffer &KEY start end) - TCP
(RAWSOCK:UDPCSUM buffer &KEY start end) - UDP

Compute the appropriate protocol checksum and record it in the appropriate location. buffer is assumed to be a suitable ethernet frame for the protocol, with the appropriate header etc.

Note that buffer is an ethernet frame, starting with 6 bytes of the destination MAC address, 6 bytes of the source MAC address, and 2 bytes specifying the next level protocol, (e.g., #x0800 for IP and #x0806 for ARP), i.e., the first 14 bytes of buffer are ignored by these functions.

A typical packet you send is both IP and TCP and thus has two checksums, so you would want to call two functions.

(RAWSOCK:CONFIGDEV socket ifname address &KEY promisc noarp)
Set some socket options and IP address with ioctl.

These notes document CLISP version 2.49Last modified: 2010-07-07